Refactoring of $clinit and $init method accessors.
Change-Id: I5caab1249df99e44d0113481a596536897833a43
Review-Link: https://gwt-review.googlesource.com/#/c/1171/
git-svn-id: https://google-web-toolkit.googlecode.com/svn/trunk@11375 8db76d5a-ed1c-0410-87a9-c151d255dfc7
diff --git a/dev/core/src/com/google/gwt/dev/jjs/ast/JDeclaredType.java b/dev/core/src/com/google/gwt/dev/jjs/ast/JDeclaredType.java
index 7b127d2..2e3270a 100755
--- a/dev/core/src/com/google/gwt/dev/jjs/ast/JDeclaredType.java
+++ b/dev/core/src/com/google/gwt/dev/jjs/ast/JDeclaredType.java
@@ -27,7 +27,22 @@
import java.util.List;
/**
- * Base class for any reference type.
+ * Base class for any declared type.
+ *
+ * Declared types have fields and methods. Two of the methods are treated specially: the class
+ * initializer method (named <code>$clinit</code>) and the instance initializer method
+ * (named <code>$init</code>).
+ *
+ * The class initializer method is responsible for initializing all class variables as well as
+ * those of the superclasses (by calling the superclass class initializer method).
+ *
+ * The instance initializer is responsible for initializing all instance variables as well as those
+ * of the superclasses (by calling the superclass instance initializer method).
+ *
+ * Optimizations may eliminate class initializers (<code>$clinit</code>) if no static variables need
+ * initialization, and use the private variable <code>clinitTarget</code>to keep track which
+ * initializer in the superclass chain needs to be called.
+ *
*/
public abstract class JDeclaredType extends JReferenceType {
@@ -48,8 +63,8 @@
protected transient List<JMethod> methods = Lists.create();
/**
- * Tracks the target static initialization for this class. Default to self
- * until removed or set to be a superclass.
+ * Tracks the target static initialization for this class. Default to self (if it has a non
+ * empty initializer) or point to a superclass or be null.
*/
private JDeclaredType clinitTarget = this;
@@ -100,8 +115,12 @@
/**
* Adds a method to this type.
*/
- public void addMethod(JMethod method) {
+ public final void addMethod(JMethod method) {
assert method.getEnclosingType() == this;
+ assert !method.getName().equals("$clinit") || getMethods().size() == 0 : "Attempted adding "
+ + "$clinit method with index != 0";
+ assert !method.getName().equals("$init") || getMethods().size() == 1 : "Attempted adding $init "
+ + "method with index != 1";
methods = Lists.add(methods, method);
}
@@ -140,10 +159,40 @@
}
/**
+ * Returns the instance initializer ($init) method.
+ * Can only be called after making sure the class has an instance initializer method.
+ *
+ * @return The instance initializer method.
+ */
+ public final JMethod getInitMethod() {
+ assert getMethods().size() > 1;
+ JMethod init = this.getMethods().get(1);
+
+ assert init != null;
+ assert init.getName().equals("$init");
+ return init;
+ }
+
+ /**
+ * Returns the class initializer method.
+ * Can only be called after making sure the class has a class initializer method.
+ *
+ * @return The class initializer method.
+ */
+ public final JMethod getClinitMethod() {
+ assert getMethods().size() != 0;
+ JMethod clinit = this.getMethods().get(0);
+
+ assert clinit != null;
+ assert clinit.getName().equals("$clinit");
+ return clinit;
+ }
+
+ /**
* Returns the class that must be initialized to use this class. May be a
* superclass, or <code>null</code> if this class has no static initializer.
*/
- public JDeclaredType getClinitTarget() {
+ public final JDeclaredType getClinitTarget() {
return clinitTarget;
}
@@ -186,7 +235,7 @@
* Returns this type's declared methods; does not include methods defined in a
* super type unless they are overridden by this type.
*/
- public List<JMethod> getMethods() {
+ public final List<JMethod> getMethods() {
return methods;
}
@@ -218,7 +267,7 @@
* Removes the field at the specified index.
*/
public void removeField(int i) {
- assert !isExternal() : "External types can not be modiified.";
+ assert !isExternal() : "External types can not be modified.";
fields = Lists.remove(fields, i);
}
@@ -226,11 +275,23 @@
* Removes the method at the specified index.
*/
public void removeMethod(int i) {
- assert !isExternal() : "External types can not be modiified.";
+ assert !isExternal() : "External types can not be modified.";
methods = Lists.remove(methods, i);
}
/**
+ * Resets the clinitTarget to the current class. Used by optimizations that move initializers from
+ * superclasses down.
+ *
+ * Prerequisite: the $clinit method must exist and be non empty.
+ */
+ public void resetClinitTarget() {
+ assert !((JMethodBody) getClinitMethod().getBody()).getStatements().isEmpty() : "Attempted to "
+ + "reset the clinitTarget to an empty $clinit";
+ this.clinitTarget = this;
+ }
+
+ /**
* Resolves external references during AST stitching.
*/
public void resolve(List<JInterfaceType> resolvedInterfaces, List<JNode> resolvedRescues) {
diff --git a/dev/core/src/com/google/gwt/dev/jjs/ast/JProgram.java b/dev/core/src/com/google/gwt/dev/jjs/ast/JProgram.java
index ad4542f..bcc1331 100644
--- a/dev/core/src/com/google/gwt/dev/jjs/ast/JProgram.java
+++ b/dev/core/src/com/google/gwt/dev/jjs/ast/JProgram.java
@@ -231,7 +231,7 @@
public static boolean isClinit(JMethod method) {
JDeclaredType enclosingType = method.getEnclosingType();
- if ((enclosingType != null) && (method == enclosingType.getMethods().get(0))) {
+ if ((enclosingType != null) && (method == enclosingType.getClinitMethod())) {
assert (method.getName().equals("$clinit"));
return true;
} else {
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 8850cb6..5963dd1 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
@@ -729,7 +729,7 @@
// Track that we've been seen.
alreadySeen.add(type);
- JMethod method = type.getMethods().get(0);
+ JMethod method = type.getClinitMethod();
assert (JProgram.isClinit(method));
CheckClinitVisitor v = new CheckClinitVisitor();
v.accept(method);
diff --git a/dev/core/src/com/google/gwt/dev/jjs/impl/ControlFlowAnalyzer.java b/dev/core/src/com/google/gwt/dev/jjs/impl/ControlFlowAnalyzer.java
index f9b3aaa..93485dd 100644
--- a/dev/core/src/com/google/gwt/dev/jjs/impl/ControlFlowAnalyzer.java
+++ b/dev/core/src/com/google/gwt/dev/jjs/impl/ControlFlowAnalyzer.java
@@ -226,7 +226,7 @@
// Rescue my clinit (it won't ever be explicitly referenced)
if (type.hasClinit()) {
- rescue(type.getMethods().get(0));
+ rescue(type.getClinitMethod());
}
// JLS 12.4.1: don't rescue my super interfaces just because I'm rescued.
@@ -304,7 +304,7 @@
// Rescue my clinit (it won't ever be explicitly referenced)
if (type.hasClinit()) {
- rescue(type.getMethods().get(0));
+ rescue(type.getClinitMethod());
}
// JLS 12.4.1: don't rescue my super interfaces just because I'm rescued.
@@ -671,7 +671,7 @@
JField field = (JField) var;
accept(field.getInitializer());
referencedTypes.add(field.getEnclosingType());
- liveFieldsAndMethods.add(field.getEnclosingType().getMethods().get(0));
+ liveFieldsAndMethods.add(field.getEnclosingType().getClinitMethod());
} else if (argsToRescueIfParameterRead != null && var instanceof JParameter) {
List<JExpression> list = argsToRescueIfParameterRead.remove(var);
if (list != null) {
diff --git a/dev/core/src/com/google/gwt/dev/jjs/impl/DeadCodeElimination.java b/dev/core/src/com/google/gwt/dev/jjs/impl/DeadCodeElimination.java
index 7013f53..c44be1a 100644
--- a/dev/core/src/com/google/gwt/dev/jjs/impl/DeadCodeElimination.java
+++ b/dev/core/src/com/google/gwt/dev/jjs/impl/DeadCodeElimination.java
@@ -703,7 +703,7 @@
}
private JMethodCall createClinitCall(SourceInfo sourceInfo, JDeclaredType targetType) {
- JMethod clinit = targetType.getClinitTarget().getMethods().get(0);
+ JMethod clinit = targetType.getClinitTarget().getClinitMethod();
assert (JProgram.isClinit(clinit));
return new JMethodCall(sourceInfo, null, clinit);
}
diff --git a/dev/core/src/com/google/gwt/dev/jjs/impl/EnumOrdinalizer.java b/dev/core/src/com/google/gwt/dev/jjs/impl/EnumOrdinalizer.java
index 959abc1..d7ea10c 100644
--- a/dev/core/src/com/google/gwt/dev/jjs/impl/EnumOrdinalizer.java
+++ b/dev/core/src/com/google/gwt/dev/jjs/impl/EnumOrdinalizer.java
@@ -667,10 +667,9 @@
if (canBeOrdinal(x)) {
/*
- * Cleanup clinit method for ordinalizable enums. Note, method 0 is
- * always the clinit.
+ * Cleanup clinit method for ordinalizable enums.
*/
- updateClinit(x.getMethods().get(0));
+ updateClinit(x.getClinitMethod());
/*
* Remove any static impl mappings for any methods in an ordinal enum
diff --git a/dev/core/src/com/google/gwt/dev/jjs/impl/GenerateJavaScriptAST.java b/dev/core/src/com/google/gwt/dev/jjs/impl/GenerateJavaScriptAST.java
index 1616123..81ad168 100644
--- a/dev/core/src/com/google/gwt/dev/jjs/impl/GenerateJavaScriptAST.java
+++ b/dev/core/src/com/google/gwt/dev/jjs/impl/GenerateJavaScriptAST.java
@@ -1187,7 +1187,7 @@
return;
} else if (type != clinitTarget) {
// replace the method with its retargeted clinit
- method = clinitTarget.getMethods().get(0);
+ method = clinitTarget.getClinitMethod();
}
}
@@ -1774,7 +1774,7 @@
* refs to super classes are preserved.
*/
JMethodBody clinitBody =
- (JMethodBody) program.getTypeClassLiteralHolder().getMethods().get(0).getBody();
+ (JMethodBody) program.getTypeClassLiteralHolder().getClinitMethod().getBody();
for (JStatement stmt : clinitBody.getStatements()) {
if (stmt instanceof JDeclarationStatement) {
generateClassLiteral((JDeclarationStatement) stmt, vars);
@@ -2157,7 +2157,7 @@
return null;
}
- JMethod clinitMethod = targetType.getMethods().get(0);
+ JMethod clinitMethod = targetType.getClinitMethod();
SourceInfo sourceInfo = x.getSourceInfo();
JsInvocation jsInvocation = new JsInvocation(sourceInfo);
jsInvocation.setQualifier(names.get(clinitMethod).makeRef(sourceInfo));
@@ -2180,7 +2180,7 @@
return null;
}
- JMethod clinitMethod = enclosingType.getClinitTarget().getMethods().get(0);
+ JMethod clinitMethod = enclosingType.getClinitTarget().getClinitMethod();
SourceInfo sourceInfo = x.getSourceInfo();
JsInvocation jsInvocation = new JsInvocation(sourceInfo);
jsInvocation.setQualifier(names.get(clinitMethod).makeRef(sourceInfo));
diff --git a/dev/core/src/com/google/gwt/dev/jjs/impl/GwtAstBuilder.java b/dev/core/src/com/google/gwt/dev/jjs/impl/GwtAstBuilder.java
index 30102bc..3ecdefb 100644
--- a/dev/core/src/com/google/gwt/dev/jjs/impl/GwtAstBuilder.java
+++ b/dev/core/src/com/google/gwt/dev/jjs/impl/GwtAstBuilder.java
@@ -686,8 +686,7 @@
* explicit this constructor call, in which case the callee will.
*/
if (!hasExplicitThis) {
- // $init is always in position 1 (clinit is in 0)
- JMethod initMethod = curClass.type.getMethods().get(1);
+ JMethod initMethod = curClass.type.getInitMethod();
JMethodCall initCall = new JMethodCall(info, makeThisRef(info), initMethod);
block.addStmt(initCall.makeStatement());
}
@@ -1743,11 +1742,11 @@
JDeclaredType type = curClass.type;
/*
* Make clinits chain to super class (JDT doesn't write code to do this).
- * Call super class $clinit; $clinit is always in position 0.
+ * Call super class $clinit;
*/
if (type.getSuperClass() != null) {
- JMethod myClinit = type.getMethods().get(0);
- JMethod superClinit = type.getSuperClass().getMethods().get(0);
+ JMethod myClinit = type.getClinitMethod();
+ JMethod superClinit = type.getSuperClass().getClinitMethod();
JMethodCall superClinitCall = new JMethodCall(myClinit.getSourceInfo(), null, superClinit);
JMethodBody body = (JMethodBody) myClinit.getBody();
body.getBlock().addStmt(0, superClinitCall.makeStatement());
@@ -2051,7 +2050,7 @@
JNewArray newExpr = JNewArray.createInitializers(info, enumArrayType, initializers);
JFieldRef valuesRef = new JFieldRef(info, null, valuesField, type);
JDeclarationStatement declStmt = new JDeclarationStatement(info, valuesRef, newExpr);
- JBlock clinitBlock = ((JMethodBody) type.getMethods().get(0).getBody()).getBlock();
+ JBlock clinitBlock = ((JMethodBody) type.getClinitMethod().getBody()).getBlock();
/*
* HACKY: the $VALUES array must be initialized immediately after all of
@@ -2433,9 +2432,9 @@
private void pushInitializerMethodInfo(FieldDeclaration x, MethodScope scope) {
JMethod initMeth;
if (x.isStatic()) {
- initMeth = curClass.type.getMethods().get(0);
+ initMeth = curClass.type.getClinitMethod();
} else {
- initMeth = curClass.type.getMethods().get(1);
+ initMeth = curClass.type.getInitMethod();
}
pushMethodInfo(new MethodInfo(initMeth, (JMethodBody) initMeth.getBody(), scope));
}
diff --git a/dev/core/src/com/google/gwt/dev/jjs/impl/ImplementClassLiteralsAsFields.java b/dev/core/src/com/google/gwt/dev/jjs/impl/ImplementClassLiteralsAsFields.java
index d13c0fc..868cd93 100644
--- a/dev/core/src/com/google/gwt/dev/jjs/impl/ImplementClassLiteralsAsFields.java
+++ b/dev/core/src/com/google/gwt/dev/jjs/impl/ImplementClassLiteralsAsFields.java
@@ -113,7 +113,7 @@
this.program = program;
this.typeClassLiteralHolder = program.getTypeClassLiteralHolder();
this.classLiteralHolderClinitBody =
- (JMethodBody) typeClassLiteralHolder.getMethods().get(0).getBody();
+ (JMethodBody) typeClassLiteralHolder.getClinitMethod().getBody();
assert program.getDeclaredTypes().contains(typeClassLiteralHolder);
}
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 92eb2bb..beaf790 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
@@ -110,7 +110,7 @@
List<JStatement> stmts = body.getStatements();
if (method.getEnclosingType() != null
- && method.getEnclosingType().getMethods().get(0) == method && !stmts.isEmpty()) {
+ && method.getEnclosingType().getClinitMethod() == method && !stmts.isEmpty()) {
// clinit() calls cannot be inlined unless they are empty
possibleToInline = false;
} else if (!body.getLocals().isEmpty()) {
@@ -177,7 +177,7 @@
return null;
}
- JMethod clinit = targetType.getMethods().get(0);
+ JMethod clinit = targetType.getClinitMethod();
// If the clinit is a non-native, empty body we can optimize it out here
if (!clinit.isNative() && (((JMethodBody) clinit.getBody())).getStatements().size() == 0) {
diff --git a/dev/core/src/com/google/gwt/dev/jjs/impl/UnifyAst.java b/dev/core/src/com/google/gwt/dev/jjs/impl/UnifyAst.java
index b6967c4..a7aa3a9 100644
--- a/dev/core/src/com/google/gwt/dev/jjs/impl/UnifyAst.java
+++ b/dev/core/src/com/google/gwt/dev/jjs/impl/UnifyAst.java
@@ -641,7 +641,7 @@
}
// Special clinit handling.
- JMethod clinit = type.getMethods().get(0);
+ JMethod clinit = type.getClinitMethod();
if (!liveFieldsAndMethods.contains(clinit)) {
clinit.setBody(new JMethodBody(SourceOrigin.UNKNOWN));
}
@@ -994,7 +994,7 @@
assert errorsFound;
return;
}
- JMethod clinit = type.getMethods().get(0);
+ JMethod clinit = type.getClinitMethod();
if (!liveFieldsAndMethods.contains(clinit)) {
flowInto(clinit);
if (type.getSuperClass() != null) {