Roberto Lublinerman has uploaded a new change for review.

  https://gwt-review.googlesource.com/2701


Change subject: Make sub/superclass queries in JTypeOracle  more efficient.
......................................................................

Make sub/superclass queries in JTypeOracle  more efficient.

Assign a unique id to each class during for global optimization, such
that the following invariant holds:
  a.id < b.id   for b != a and b subclass of a.
  forall c.id > a.id, c.id <= max_{b subclass of a}(b.id) . c subclass of a

The aforementioned invariant allows to respond to the query subclass(a,b) very
cheaply  with just two integer comparisons (plus pointer dereferences).

Change-Id: Ibe256bc07834b1518a9e90872fdd655e3e242790
---
M dev/core/src/com/google/gwt/dev/jjs/ast/JClassType.java
M dev/core/src/com/google/gwt/dev/jjs/ast/JTypeOracle.java
2 files changed, 94 insertions(+), 2 deletions(-)



diff --git a/dev/core/src/com/google/gwt/dev/jjs/ast/JClassType.java b/dev/core/src/com/google/gwt/dev/jjs/ast/JClassType.java
index 6c12533..1217c88 100644
--- a/dev/core/src/com/google/gwt/dev/jjs/ast/JClassType.java
+++ b/dev/core/src/com/google/gwt/dev/jjs/ast/JClassType.java
@@ -40,6 +40,7 @@
   private final boolean isAbstract;
   private boolean isFinal;
   private JClassType superClass;
+  private int classId = -1;

public JClassType(SourceInfo info, String name, boolean isAbstract, boolean isFinal) {
     super(info, name);
@@ -85,6 +86,23 @@
     isFinal = true;
   }

+
+  /**
+ * Returns a numeric id for the class. The id is only assigned in the global + * optimization phase and should not be used before the global ast is built.
+   */
+  public int getClassId() {
+    return classId;
+  }
+
+  /**
+ * Set a classid. Only to be used after the global AST is build at the beginning of the
+   * optimization phase.
+   */
+  public void setClassId(int classId) {
+    this.classId = classId;
+  }
+
   /**
    * Sets this type's super class.
    */
diff --git a/dev/core/src/com/google/gwt/dev/jjs/ast/JTypeOracle.java b/dev/core/src/com/google/gwt/dev/jjs/ast/JTypeOracle.java
index 5963dd1..deded26 100644
--- a/dev/core/src/com/google/gwt/dev/jjs/ast/JTypeOracle.java
+++ b/dev/core/src/com/google/gwt/dev/jjs/ast/JTypeOracle.java
@@ -23,7 +23,10 @@
 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 com.google.gwt.dev.util.log.speedtracer.CompilerEventType;
+import com.google.gwt.dev.util.log.speedtracer.SpeedTracerLogger;

+import java.io.IOException;
 import java.io.Serializable;
 import java.util.ArrayList;
 import java.util.Collections;
@@ -297,6 +300,13 @@
   private final Map<JClassType, Map<String, JMethod>> polyClassMethodMap =
       new IdentityHashMap<JClassType, Map<String, JMethod>>();

+
+  /**
+   * The number of declared types.
+   */
+  private int declaredTypesSize;
+
+
   public JTypeOracle(JProgram program) {
     this.program = program;
   }
@@ -481,6 +491,8 @@
     jsoSingleImpls.clear();
     dualImpls.clear();

+    this.declaredTypesSize = program.getDeclaredTypes().size();
+
     for (JDeclaredType type : program.getDeclaredTypes()) {
       if (type instanceof JClassType) {
         recordSuperSubInfo((JClassType) type);
@@ -488,6 +500,13 @@
         recordSuperSubInfo((JInterfaceType) type);
       }
     }
+
+    /*
+ * Compute efficient representation for hierarchy sub/supertype queries.
+     */
+    computeIds();
+
+//    HierarchyEncoder.compute(program);

     /*
      * Now that the basic type hierarchy is computed, compute which JSOs
@@ -645,14 +664,14 @@
    * Returns true if qType is a subclass of type, directly or indirectly.
    */
   public boolean isSubClass(JClassType type, JClassType qType) {
-    return get(subClassMap, type).contains(qType);
+    return isSubtype(qType, type);
   }

   /**
    * Returns true if qType is a superclass of type, directly or indirectly.
    */
   public boolean isSuperClass(JClassType type, JClassType qType) {
-    return get(superClassMap, type).contains(qType);
+    return isSubtype(type, qType);
   }

   /**
@@ -686,6 +705,8 @@
       }
     }
   }
+
+

   public void setInstantiatedTypes(Set<JReferenceType> instantiatedTypes) {
     this.instantiatedTypes = instantiatedTypes;
@@ -1011,4 +1032,57 @@
     }
   }

+  /*
+ * Make sure we recompute class ids when reloading serialized type oracles.
+   */
+  private void readObject(java.io.ObjectInputStream in) throws IOException,
+      ClassNotFoundException {
+    in.defaultReadObject();
+    // recompute class hierarchy query data structure;
+    computeIds();
+  }
+
+
+  /**
+   * Compute class ids for efficient lookups.
+   *
+ * A clever encoding of the class hierarchy reduces the cost of one of the hottest methods
+   * during optimize.
+   *
+   * NOTE: Only encodes the (single inheritance) class hierarchy.
+   *
+   * The encoding preserves the following invariant
+ * A is strict subclass of B <=> id(A) < id(B) ^ id(B) =< max{C subclass A}(Id(C))
+   *
+ * An easy way to guaranteed this propery is to number sequentially while traversing the
+   * hierarchy tree in preorder.
+   */
+  private transient int lastClassId = -1;
+  private transient int[] maxDescendants = null;
+
+  boolean isSubtype(JClassType sub, JClassType sup) {
+    int supId = sup.getClassId();
+    int subId = sub.getClassId();
+    return supId < subId  &&
+        subId <= maxDescendants[supId];
+  }
+
+  private void computeIds() {
+    SpeedTracerLogger.Event computeHierarchyEvent =
+ SpeedTracerLogger.start(CompilerEventType.OPTIMIZE, "pass", "Compute Type Hierarchy");
+    lastClassId = -1;
+    maxDescendants = new int[declaredTypesSize];
+    computeIdTraversal(javaLangObject);
+    computeHierarchyEvent.end();
+  }
+
+  private void computeIdTraversal(JClassType type) {
+    type.setClassId(++lastClassId);
+    for (JClassType sub : get(subClassMap, type)) {
+      if (sub.getSuperClass() == type) {
+        computeIdTraversal(sub);
+      }
+    }
+    maxDescendants[type.getClassId()] = lastClassId;
+  }
 }

--
To view, visit https://gwt-review.googlesource.com/2701
To unsubscribe, visit https://gwt-review.googlesource.com/settings

Gerrit-MessageType: newchange
Gerrit-Change-Id: Ibe256bc07834b1518a9e90872fdd655e3e242790
Gerrit-PatchSet: 1
Gerrit-Project: gwt
Gerrit-Branch: master
Gerrit-Owner: Roberto Lublinerman <[email protected]>

--
--
http://groups.google.com/group/Google-Web-Toolkit-Contributors
--- You received this message because you are subscribed to the Google Groups "Google Web Toolkit Contributors" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
For more options, visit https://groups.google.com/groups/opt_out.


Reply via email to