Revision: 8255
Author: sco...@google.com
Date: Mon Jun 14 14:39:55 2010
Log: A new model for external types

http://gwt-code-reviews.appspot.com/589801/show
Patch by: tobyr
Review by: me, bobv

http://code.google.com/p/google-web-toolkit/source/detail?r=8255

Deleted:
 /trunk/dev/core/src/com/google/gwt/dev/jjs/ast/JExternalType.java
Modified:
 /trunk/dev/core/src/com/google/gwt/dev/jjs/ArtificialRescueRecorder.java
 /trunk/dev/core/src/com/google/gwt/dev/jjs/ast/JAnnotation.java
 /trunk/dev/core/src/com/google/gwt/dev/jjs/ast/JArrayType.java
 /trunk/dev/core/src/com/google/gwt/dev/jjs/ast/JClassLiteral.java
 /trunk/dev/core/src/com/google/gwt/dev/jjs/ast/JDeclaredType.java
 /trunk/dev/core/src/com/google/gwt/dev/jjs/ast/JMethod.java
 /trunk/dev/core/src/com/google/gwt/dev/jjs/ast/JProgram.java
 /trunk/dev/core/src/com/google/gwt/dev/jjs/ast/JType.java
 /trunk/dev/core/src/com/google/gwt/dev/jjs/ast/JTypeOracle.java
 /trunk/dev/core/src/com/google/gwt/dev/jjs/impl/DeadCodeElimination.java
 /trunk/dev/core/src/com/google/gwt/dev/jjs/impl/Finalizer.java
 /trunk/dev/core/src/com/google/gwt/dev/jjs/impl/GenerateJavaAST.java
 /trunk/dev/core/src/com/google/gwt/dev/jjs/impl/MakeCallsStatic.java
 /trunk/dev/core/test/com/google/gwt/dev/jjs/impl/JAnnotationTest.java

=======================================
--- /trunk/dev/core/src/com/google/gwt/dev/jjs/ast/JExternalType.java Mon Feb 8 08:29:30 2010
+++ /dev/null
@@ -1,49 +0,0 @@
-/*
- * Copyright 2010 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.dev.jjs.ast;
-
-import com.google.gwt.dev.jjs.SourceInfo;
-
-/**
- * Represents a type outside of the client type system, usually a binary-only
- * annotation reference.
- */
-public class JExternalType extends JDeclaredType {
-
-  JExternalType(SourceInfo info, String name) {
-    super(info, name);
-  }
-
-  @Override
-  public String getClassLiteralFactoryMethod() {
-    return "Class.createForInterface";
-  }
-
-  public boolean isAbstract() {
-    return true;
-  }
-
-  public boolean isFinal() {
-    return false;
-  }
-
-  public void traverse(JVisitor visitor, Context ctx) {
-    if (visitor.visit(this, ctx)) {
-      annotations = visitor.acceptImmutable(annotations);
-    }
-    visitor.endVisit(this, ctx);
-  }
-}
=======================================
--- /trunk/dev/core/src/com/google/gwt/dev/jjs/ArtificialRescueRecorder.java Wed Feb 10 02:57:10 2010 +++ /trunk/dev/core/src/com/google/gwt/dev/jjs/ArtificialRescueRecorder.java Mon Jun 14 14:39:55 2010
@@ -22,6 +22,7 @@
 import com.google.gwt.dev.jjs.ast.JAnnotation;
 import com.google.gwt.dev.jjs.ast.JDeclaredType;
 import com.google.gwt.dev.jjs.ast.JField;
+import com.google.gwt.dev.jjs.ast.JInterfaceType;
 import com.google.gwt.dev.jjs.ast.JNode;
 import com.google.gwt.dev.jjs.ast.JProgram;
 import com.google.gwt.dev.jjs.ast.JReferenceType;
@@ -124,12 +125,12 @@
     new ArtificialRescueRecorder(program).execImpl();
   }

-  private final JDeclaredType artificialRescueType;
+  private final JInterfaceType artificialRescueType;
   private final JProgram program;

   private ArtificialRescueRecorder(JProgram program) {
     this.program = program;
- artificialRescueType = program.getFromTypeMap(ArtificialRescue.class.getName()); + artificialRescueType = (JInterfaceType) program.getFromTypeMap(ArtificialRescue.class.getName());
   }

   private void execImpl() {
=======================================
--- /trunk/dev/core/src/com/google/gwt/dev/jjs/ast/JAnnotation.java Wed Feb 10 02:57:10 2010 +++ /trunk/dev/core/src/com/google/gwt/dev/jjs/ast/JAnnotation.java Mon Jun 14 14:39:55 2010
@@ -240,14 +240,9 @@
     return null;
   }

-  private final JType type;
+  private final JInterfaceType type;
   private List<Property> properties = Lists.create();

-  public JAnnotation(SourceInfo sourceInfo, JExternalType type) {
-    super(sourceInfo);
-    this.type = type;
-  }
-
   public JAnnotation(SourceInfo sourceInfo, JInterfaceType type) {
     super(sourceInfo);
     this.type = type;
@@ -277,7 +272,7 @@
     return null;
   }

-  public JType getType() {
+  public JInterfaceType getType() {
     return type;
   }

=======================================
--- /trunk/dev/core/src/com/google/gwt/dev/jjs/ast/JArrayType.java Mon May 18 11:47:32 2009 +++ /trunk/dev/core/src/com/google/gwt/dev/jjs/ast/JArrayType.java Mon Jun 14 14:39:55 2010
@@ -79,6 +79,11 @@
   public boolean isAbstract() {
     return false;
   }
+
+  @Override
+  public boolean isExternal() {
+    return elementType.isExternal();
+  }

   public boolean isFinal() {
     return leafType.isFinal();
=======================================
--- /trunk/dev/core/src/com/google/gwt/dev/jjs/ast/JClassLiteral.java Fri May 28 09:34:24 2010 +++ /trunk/dev/core/src/com/google/gwt/dev/jjs/ast/JClassLiteral.java Mon Jun 14 14:39:55 2010
@@ -131,7 +131,7 @@
JClassLiteral componentLiteral = program.getLiteralClass(arrayType.getElementType());
       call.addArg(componentLiteral);
     } else {
- assert (type instanceof JExternalType || type instanceof JInterfaceType || type instanceof JPrimitiveType); + assert (type instanceof JInterfaceType || type instanceof JPrimitiveType);
     }
assert call.getArgs().size() == method.getParams().size() : "Argument / param mismatch "
         + call.toString() + " versus " + method.toString();
=======================================
--- /trunk/dev/core/src/com/google/gwt/dev/jjs/ast/JDeclaredType.java Mon Jun 7 12:20:31 2010 +++ /trunk/dev/core/src/com/google/gwt/dev/jjs/ast/JDeclaredType.java Mon Jun 14 14:39:55 2010
@@ -66,6 +66,14 @@
    */
   private JDeclaredType enclosingType;

+  /**
+ * True if this class is provided externally to the program by the program's + * host execution environment. For example, while compiling for the JVM, JRE + * types are external types. External types definitions are provided by class
+   * files which are considered opaque by the GWT compiler.
+   */
+  private boolean isExternal;
+
   /**
    * This type's super class.
    */
@@ -225,11 +233,17 @@
   public boolean hasClinit() {
     return clinitTarget != null;
   }
+
+  @Override
+  public boolean isExternal() {
+    return isExternal;
+  }

   /**
    * Removes the field at the specified index.
    */
   public void removeField(int i) {
+    assert !isExternal() : "External types can not be modiified.";
     fields = Lists.remove(fields, i);
   }

@@ -237,6 +251,7 @@
    * Removes the method at the specified index.
    */
   public void removeMethod(int i) {
+    assert !isExternal() : "External types can not be modiified.";
     methods = Lists.remove(methods, i);
   }

@@ -248,6 +263,10 @@
   public void setEnclosingType(JDeclaredType enclosingType) {
     this.enclosingType = enclosingType;
   }
+
+  public void setExternal(boolean isExternal) {
+    this.isExternal = isExternal;
+  }

   /**
    * Sets this type's super class.
=======================================
--- /trunk/dev/core/src/com/google/gwt/dev/jjs/ast/JMethod.java Thu Mar 11 17:23:20 2010 +++ /trunk/dev/core/src/com/google/gwt/dev/jjs/ast/JMethod.java Mon Jun 14 14:39:55 2010
@@ -148,6 +148,7 @@
   }

   public JAbstractMethodBody getBody() {
+ assert !enclosingType.isExternal() : "External types do not have method bodies.";
     return body;
   }

=======================================
--- /trunk/dev/core/src/com/google/gwt/dev/jjs/ast/JProgram.java Fri Jun 4 12:47:18 2010 +++ /trunk/dev/core/src/com/google/gwt/dev/jjs/ast/JProgram.java Mon Jun 14 14:39:55 2010
@@ -303,8 +303,6 @@
    */
private final ArrayList<HashMap<JType, JArrayType>> dimensions = new ArrayList<HashMap<JType, JArrayType>>();

- private final Map<String, JExternalType> externalTypes = new HashMap<String, JExternalType>();
-
private final Map<String, JField> indexedFields = new HashMap<String, JField>();

private final Map<String, JMethod> indexedMethods = new HashMap<String, JMethod>();
@@ -480,20 +478,6 @@
     enclosingType.addField(x);
     return x;
   }
-
-  public JExternalType createExternalType(SourceInfo info, String name) {
-    JExternalType x;
-    x = externalTypes.get(name);
-    if (x != null) {
-      return x;
-    }
-
-    x = new JExternalType(info, name);
-    if (INDEX_TYPES_SET.contains(name)) {
-      indexedTypes.put(x.getShortName(), x);
-    }
-    return x;
-  }

   public JField createField(SourceInfo info, String name,
       JDeclaredType enclosingType, JType type, boolean isStatic,
=======================================
--- /trunk/dev/core/src/com/google/gwt/dev/jjs/ast/JType.java Thu Apr 9 08:41:34 2009 +++ /trunk/dev/core/src/com/google/gwt/dev/jjs/ast/JType.java Mon Jun 14 14:39:55 2010
@@ -44,5 +44,9 @@
   public String getName() {
     return name;
   }
+
+  public boolean isExternal() {
+    return false;
+  }

 }
=======================================
--- /trunk/dev/core/src/com/google/gwt/dev/jjs/ast/JTypeOracle.java Sat Apr 3 06:52:10 2010 +++ /trunk/dev/core/src/com/google/gwt/dev/jjs/ast/JTypeOracle.java Mon Jun 14 14:39:55 2010
@@ -611,7 +611,7 @@

   private void computeClinitTarget(JDeclaredType type,
       Set<JDeclaredType> computed) {
-    if (!type.hasClinit() || computed.contains(type)) {
+ if (type.isExternal() || !type.hasClinit() || computed.contains(type)) {
       return;
     }
     if (type.getSuperClass() != null) {
@@ -876,6 +876,18 @@
       Set<JReferenceType> instantiatedTypes) {
     type = program.getRunTimeType(type);

+    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;
     }
=======================================
--- /trunk/dev/core/src/com/google/gwt/dev/jjs/impl/DeadCodeElimination.java Fri Apr 2 12:42:00 2010 +++ /trunk/dev/core/src/com/google/gwt/dev/jjs/impl/DeadCodeElimination.java Mon Jun 14 14:39:55 2010
@@ -257,11 +257,6 @@
         ctx.replaceMe(updated);
       }
     }
-
-    @Override
-    public void endVisit(JClassType x, Context ctx) {
-      // previously set currentClass = null;
-    }

     @Override
     public void endVisit(JConditional x, Context ctx) {
@@ -614,8 +609,8 @@

     @Override
     public boolean visit(JClassType x, Context ctx) {
-      // previously set currentClass = x;
-      return true;
+      // We can't eliminate code from an external type
+      return !x.isExternal();
     }

     @Override
@@ -1463,8 +1458,8 @@
     /**
      * Simplify the expression <code>-exp</code>.
      *
+     * @param original An expression equivalent to <code>-exp</code>.
      * @param exp The expression to negate.
-     * @param An expression equivalent to <code>-exp</code>.
      *
      * @return A simplified expression equivalent to <code>- exp</code>.
      */
=======================================
--- /trunk/dev/core/src/com/google/gwt/dev/jjs/impl/Finalizer.java Fri Apr 2 09:39:56 2010 +++ /trunk/dev/core/src/com/google/gwt/dev/jjs/impl/Finalizer.java Mon Jun 14 14:39:55 2010
@@ -101,6 +101,13 @@
     public void endVisit(JParameter x, Context ctx) {
       maybeFinalize(x);
     }
+
+    @Override
+    public boolean visit(JClassType x, Context ctx) {
+      // Don't visit external types, because we can't change their final
+      // specifiers.
+      return !x.isExternal();
+    }

     @Override
     public boolean visit(JMethodBody x, Context ctx) {
@@ -179,6 +186,13 @@
         recordAssignment(x);
       }
     }
+
+    @Override
+    public boolean visit(JClassType x, Context ctx) {
+      // Don't visit external types, because we can't change their final
+      // specifiers.
+      return !x.isExternal();
+    }

     private void recordAssignment(JExpression lhs) {
       if (lhs instanceof JVariableRef) {
=======================================
--- /trunk/dev/core/src/com/google/gwt/dev/jjs/impl/GenerateJavaAST.java Fri Jun 4 16:25:02 2010 +++ /trunk/dev/core/src/com/google/gwt/dev/jjs/impl/GenerateJavaAST.java Mon Jun 14 14:39:55 2010
@@ -48,7 +48,6 @@
 import com.google.gwt.dev.jjs.ast.JEnumType;
 import com.google.gwt.dev.jjs.ast.JExpression;
 import com.google.gwt.dev.jjs.ast.JExpressionStatement;
-import com.google.gwt.dev.jjs.ast.JExternalType;
 import com.google.gwt.dev.jjs.ast.JField;
 import com.google.gwt.dev.jjs.ast.JFieldRef;
 import com.google.gwt.dev.jjs.ast.JFloatLiteral;
@@ -2011,12 +2010,9 @@
       }
     }

-    private void addThrownExceptions(MethodBinding methodBinding,
-        JMethod method) {
-      for (ReferenceBinding exceptionReference :
-        methodBinding.thrownExceptions) {
-        method.addThrownException((JClassType)
-            typeMap.get(exceptionReference.erasure()));
+ private void addThrownExceptions(MethodBinding methodBinding, JMethod method) { + for (ReferenceBinding exceptionReference : methodBinding.thrownExceptions) { + method.addThrownException((JClassType) typeMap.get(exceptionReference.erasure()));
       }
     }

@@ -2238,6 +2234,17 @@
       }
       return (SourceTypeBinding) typeBinding;
     }
+
+    private JInterfaceType getOrCreateExternalType(SourceInfo info,
+        char[][] compoundName) {
+      String name = BuildTypeMap.dotify(compoundName);
+ JInterfaceType external = (JInterfaceType) program.getFromTypeMap(name);
+      if (external == null) {
+        external = program.createInterface(info, name);
+        external.setExternal(true);
+      }
+      return external;
+    }

     /**
* Get a new label of a particular name, or create a new one if it doesn't
@@ -2450,25 +2457,26 @@

       for (ElementValuePair pair : elementValuePairs) {
         String name = CharOperation.charToString(pair.getName());
- List<JAnnotationArgument> values = processAnnotationPropertyValue(sourceInfo,
-            pair.getValue());
+        List<JAnnotationArgument> values = processAnnotationPropertyValue(
+            sourceInfo, pair.getValue());
         annotation.addValue(new Property(sourceInfo, name, values));
       }
     }

- private List<JAnnotationArgument> processAnnotationPropertyValue(SourceInfo info,
-        Object value) {
+    private List<JAnnotationArgument> processAnnotationPropertyValue(
+        SourceInfo info, Object value) {
       if (value instanceof TypeBinding) {
         JType type = (JType) typeMap.tryGet((TypeBinding) value);
         if (type == null) {
           // Indicates a binary-only class literal
-          type = program.createExternalType(info,
- BuildTypeMap.dotify(((ReferenceBinding) value).compoundName));
+          type = getOrCreateExternalType(info,
+              ((ReferenceBinding) value).compoundName);
         }
return Lists.<JAnnotationArgument> create(program.getLiteralClass(type));

       } else if (value instanceof Constant) {
- return Lists.create((JAnnotationArgument) dispatch("processConstant", value)); + return Lists.create((JAnnotationArgument) dispatch("processConstant",
+            value));

       } else if (value instanceof Object[]) {
         Object[] array = (Object[]) value;
@@ -2487,8 +2495,8 @@
         if (type != null) {
           toReturn = new JAnnotation(info, type);
         } else {
-          JExternalType external = program.createExternalType(info,
-              BuildTypeMap.dotify(annotationType.compoundName));
+          JInterfaceType external = getOrCreateExternalType(info,
+              annotationType.compoundName);
           toReturn = new JAnnotation(info, external);
         }

@@ -2554,8 +2562,8 @@
           annotation = new JAnnotation(x.getSourceInfo(), annotationType);
         } else {
           // Indicates a binary-only annotation type
-          JExternalType externalType = program.createExternalType(
- x.getSourceInfo(), BuildTypeMap.dotify(binding.compoundName));
+          JInterfaceType externalType = getOrCreateExternalType(
+              x.getSourceInfo(), binding.compoundName);
           annotation = new JAnnotation(x.getSourceInfo(), externalType);
         }
         processAnnotationProperties(x.getSourceInfo(), annotation,
@@ -2805,7 +2813,7 @@
JDeclarationStatement declStmt = new JDeclarationStatement(sourceInfo,
             valuesRef, newExpr);
JBlock clinitBlock = ((JMethodBody) type.getMethods().get(0).getBody()).getBlock();
-
+
         /*
* HACKY: the $VALUES array must be initialized immediately after all of * the enum fields, but before any user initialization (which might rely
=======================================
--- /trunk/dev/core/src/com/google/gwt/dev/jjs/impl/MakeCallsStatic.java Mon Jun 7 12:20:31 2010 +++ /trunk/dev/core/src/com/google/gwt/dev/jjs/impl/MakeCallsStatic.java Mon Jun 14 14:39:55 2010
@@ -250,6 +250,15 @@
     public void endVisit(JMethodCall x, Context ctx) {
       JMethod method = x.getTarget();

+      if (method.getEnclosingType() != null) {
+        if (method.getEnclosingType().isExternal()) {
+ // Staticifying a method requires modifying the type, which we can't + // do for external types. Theoretically we could put the static method
+          // in some generated code, but what does that really buy us?
+          return;
+        }
+      }
+
       // Did we already do this one?
       if (program.getStaticImpl(method) != null
           || toBeMadeStatic.contains(method)) {
=======================================
--- /trunk/dev/core/test/com/google/gwt/dev/jjs/impl/JAnnotationTest.java Mon Jun 7 12:20:31 2010 +++ /trunk/dev/core/test/com/google/gwt/dev/jjs/impl/JAnnotationTest.java Mon Jun 14 14:39:55 2010
@@ -20,7 +20,6 @@
 import com.google.gwt.dev.jjs.ast.JAnnotation;
 import com.google.gwt.dev.jjs.ast.JClassLiteral;
 import com.google.gwt.dev.jjs.ast.JDeclaredType;
-import com.google.gwt.dev.jjs.ast.JExternalType;
 import com.google.gwt.dev.jjs.ast.JField;
 import com.google.gwt.dev.jjs.ast.JLocal;
 import com.google.gwt.dev.jjs.ast.JMethod;
@@ -231,7 +230,7 @@
     JAnnotation a = JAnnotation.findAnnotation(useDefaults,
         BinaryAnnotation.class.getName());
     assertNotNull(a);
-    assertTrue(a.getType() instanceof JExternalType);
+    assertTrue(a.getType().isExternal());

     BinaryAnnotation instance = JAnnotation.createAnnotation(
         BinaryAnnotation.class, a);
@@ -265,7 +264,8 @@

     Property p = a.getProperty("value");
     JClassLiteral literal = (JClassLiteral) p.getSingleValue();
-    JExternalType externalType = (JExternalType) literal.getRefType();
-    assertEquals(JAnnotationTest.class.getName(), externalType.getName());
+    JDeclaredType type = (JDeclaredType) literal.getRefType();
+    assertTrue(type.isExternal());
+    assertEquals(JAnnotationTest.class.getName(), type.getName());
   }
 }

--
http://groups.google.com/group/Google-Web-Toolkit-Contributors

Reply via email to