ordercheck passes.
git-svn-id: https://google-web-toolkit.googlecode.com/svn/trunk@34 8db76d5a-ed1c-0410-87a9-c151d255dfc7
diff --git a/dev/core/src/com/google/gwt/dev/jjs/impl/ArrayNormalizer.java b/dev/core/src/com/google/gwt/dev/jjs/impl/ArrayNormalizer.java
index 23e9e66..fc5e56e 100644
--- a/dev/core/src/com/google/gwt/dev/jjs/impl/ArrayNormalizer.java
+++ b/dev/core/src/com/google/gwt/dev/jjs/impl/ArrayNormalizer.java
@@ -1,4 +1,18 @@
-// Copyright 2006 Google Inc. All Rights Reserved.
+/*
+ * Copyright 2006 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.impl;
import com.google.gwt.dev.jjs.ast.JAbsentArrayDimension;
@@ -26,14 +40,22 @@
*/
public class ArrayNormalizer {
- private final JMethod setCheckMethod;
- private final JMethod initDims;
- private final JMethod initValues;
-
private class ArrayVisitor extends JVisitor {
private final ChangeList changeList = new ChangeList(
- "Transform array accesses to check bounds.");
+ "Transform array accesses to check bounds.");
+
+ // @Override
+ public void endVisit(JNewArray x, Mutator m) {
+ JArrayType type = x.getArrayType();
+ JLiteral litTypeName = program.getLiteralString(calcClassName(type));
+
+ if (x.initializers != null) {
+ processInitializers(x, m, type, litTypeName);
+ } else {
+ processDims(x, m, type, litTypeName);
+ }
+ }
public ChangeList getChangeList() {
return changeList;
@@ -53,7 +75,7 @@
// see if we need to do a checked store
// primitives and (effectively) final are statically correct
if (elementType instanceof JReferenceType
- && !((JReferenceType) elementType).isFinal()) {
+ && !((JReferenceType) elementType).isFinal()) {
// replace this assignment with a call to setCheck()
// DON'T VISIT ARRAYREF, but do visit its children
@@ -63,7 +85,7 @@
JMethodCall call = new JMethodCall(program, null, setCheckMethod);
ChangeList myChanges = new ChangeList("Replace " + x
- + " with a call to Array.setCheck()");
+ + " with a call to Array.setCheck()");
myChanges.replaceExpression(m, call);
myChanges.addExpression(arrayRef.instance, call.args);
myChanges.addExpression(arrayRef.indexExpr, call.args);
@@ -75,22 +97,24 @@
return true;
}
- // @Override
- public void endVisit(JNewArray x, Mutator m) {
- JArrayType type = x.getArrayType();
- JLiteral litTypeName = program.getLiteralString(calcClassName(type));
-
- if (x.initializers != null) {
- processInitializers(x, m, type, litTypeName);
- } else {
- processDims(x, m, type, litTypeName);
+ private char[] calcClassName(JArrayType type) {
+ String leafName = type.getLeafType().getJsniSignatureName();
+ leafName = leafName.replace('/', '.');
+ int leafLength = leafName.length();
+ int nDims = type.getDims();
+ char[] className = new char[leafLength + nDims];
+ for (int i = 0; i < nDims; ++i) {
+ className[i] = '[';
}
+
+ leafName.getChars(0, leafLength, className, nDims);
+ return className;
}
private void processDims(JNewArray x, Mutator m, JArrayType arrayType,
JLiteral litTypeName) {
ChangeList myChanges = new ChangeList("Replace " + x
- + " with a call to Array.initDims()");
+ + " with a call to Array.initDims()");
// override the type of the called method with the array's type
JMethodCall call = new JMethodCall(program, null, initDims, arrayType);
JsonArray typeIdList = new JsonArray(program);
@@ -103,7 +127,7 @@
if (dim.get() instanceof JAbsentArrayDimension) {
break;
}
-
+
/*
* For each non-empty dimension, reduce the number of dims on the end
* type.
@@ -126,7 +150,7 @@
if (outstandingDims > 0) {
targetType = program.getTypeArray(targetType, outstandingDims);
}
-
+
myChanges.addExpression(litTypeName, call.args);
myChanges.addExpression(typeIdList, call.args);
myChanges.addExpression(queryIdList, call.args);
@@ -144,7 +168,7 @@
JLiteral queryIdLit = program.getLiteralInt(tryGetQueryId(arrayType));
JsonArray initList = new JsonArray(program);
ChangeList myChanges = new ChangeList("Replace " + x
- + " with a call to Array.initValues()");
+ + " with a call to Array.initValues()");
for (int i = 0; i < x.initializers.size(); ++i) {
Mutator initializer = x.initializers.getMutator(i);
myChanges.addExpression(initializer, initList.exprs);
@@ -165,31 +189,18 @@
}
return leafTypeId;
}
-
- private char[] calcClassName(JArrayType type) {
- String leafName = type.getLeafType().getJsniSignatureName();
- leafName = leafName.replace('/', '.');
- int leafLength = leafName.length();
- int nDims = type.getDims();
- char[] className = new char[leafLength + nDims];
- for (int i = 0; i < nDims; ++i) {
- className[i] = '[';
- }
-
- leafName.getChars(0, leafLength, className, nDims);
- return className;
- }
}
- private void execImpl() {
- ArrayVisitor visitor = new ArrayVisitor();
- program.traverse(visitor);
- ChangeList changes = visitor.getChangeList();
- if (!changes.empty()) {
- changes.apply();
- }
+ public static void exec(JProgram program) {
+ new ArrayNormalizer(program).execImpl();
}
+ private final JMethod setCheckMethod;
+
+ private final JMethod initDims;
+
+ private final JMethod initValues;
+
private final JProgram program;
private ArrayNormalizer(JProgram program) {
@@ -199,8 +210,13 @@
initValues = program.getSpecialMethod("Array.initValues");
}
- public static void exec(JProgram program) {
- new ArrayNormalizer(program).execImpl();
+ private void execImpl() {
+ ArrayVisitor visitor = new ArrayVisitor();
+ program.traverse(visitor);
+ ChangeList changes = visitor.getChangeList();
+ if (!changes.empty()) {
+ changes.apply();
+ }
}
}
diff --git a/dev/core/src/com/google/gwt/dev/jjs/impl/BuildTypeMap.java b/dev/core/src/com/google/gwt/dev/jjs/impl/BuildTypeMap.java
index a235ceb..abb4fe0 100644
--- a/dev/core/src/com/google/gwt/dev/jjs/impl/BuildTypeMap.java
+++ b/dev/core/src/com/google/gwt/dev/jjs/impl/BuildTypeMap.java
@@ -1,4 +1,18 @@
-// Copyright 2006 Google Inc. All Rights Reserved.
+/*
+ * Copyright 2006 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.impl;
import com.google.gwt.dev.jjs.ast.JClassType;
@@ -58,117 +72,6 @@
*/
public class BuildTypeMap {
- public static TypeDeclaration[] exec(TypeMap typeMap,
- CompilationUnitDeclaration[] unitDecls, JsProgram jsProgram) {
- createPeersForTypes(unitDecls, typeMap);
- return createPeersForNonTypeDecls(unitDecls, typeMap, jsProgram);
- }
-
- private static void createPeersForTypes(
- CompilationUnitDeclaration[] unitDecls, TypeMap typeMap) {
- // Traverse once to create our JNode peers for each type
- BuildTypeMapVisitor v1 = new BuildTypeMapVisitor(typeMap);
- for (int i = 0; i < unitDecls.length; ++i) {
- unitDecls[i].traverse(v1, unitDecls[i].scope);
- }
- }
-
- private static TypeDeclaration[] createPeersForNonTypeDecls(
- CompilationUnitDeclaration[] unitDecls, TypeMap typeMap,
- JsProgram jsProgram) {
- // Traverse again to create our JNode peers for each method, field,
- // parameter, and local
- BuildDeclMapVisitor v2 = new BuildDeclMapVisitor(typeMap, jsProgram);
- for (int i = 0; i < unitDecls.length; ++i) {
- unitDecls[i].traverse(v2, unitDecls[i].scope);
- }
- return v2.getTypeDeclarataions();
- }
-
- /**
- * Creates JNodes for every type and memorizes the mapping from the JDT
- * Binding to the corresponding JNode for each created type. Note that since
- * there could be forward references, it is not possible to set up supertypes;
- * it must be done is a subsequent pass.
- */
- private static class BuildTypeMapVisitor extends ASTVisitor {
-
- private final TypeMap fTypeMap;
- private final JProgram fProgram;
-
- public BuildTypeMapVisitor(TypeMap typeMap) {
- fTypeMap = typeMap;
- fProgram = fTypeMap.getProgram();
- }
-
- private boolean process(TypeDeclaration typeDeclaration) {
- char[][] name = typeDeclaration.binding.compoundName;
- SourceTypeBinding binding = typeDeclaration.binding;
- if (binding instanceof LocalTypeBinding) {
- char[] localName = binding.constantPoolName();
- if (localName == null) {
- /*
- * Weird case: if JDT determines that this local class is totally
- * uninstantiable, it won't bother allocating a local name.
- */
- return false;
- }
-
- for (int i = 0, c = localName.length; i < c; ++i) {
- if (localName[i] == '/') {
- localName[i] = '.';
- }
- }
- name = new char[1][0];
- name[0] = localName;
- }
-
- JReferenceType newType;
- if (binding.isClass()) {
- newType = fProgram.createClass(name, binding.isAbstract(),
- binding.isFinal());
- } else if (binding.isInterface()) {
- newType = fProgram.createInterface(name);
- } else {
- assert (false);
- return false;
- }
-
- /**
- * We emulate static initializers and intance initializers as methods. As
- * in other cases, this gives us: simpler AST, easier to optimize, more
- * like output JavaScript. Clinit is always in slot 0, init (if it exists)
- * is always in slot 1.
- */
- JMethod clinit = fProgram.createMethod("$clinit".toCharArray(), newType,
- fProgram.getTypeVoid(), false, true, true, true, false);
- clinit.freezeParamTypes();
-
- if (newType instanceof JClassType) {
- JMethod init = fProgram.createMethod("$init".toCharArray(), newType,
- fProgram.getTypeVoid(), false, false, true, true, false);
- init.freezeParamTypes();
- }
-
- fTypeMap.put(binding, newType);
- return true;
- }
-
- public boolean visit(TypeDeclaration localTypeDeclaration, BlockScope scope) {
- assert (localTypeDeclaration.kind() != IGenericType.INTERFACE_DECL);
- return process(localTypeDeclaration);
- }
-
- public boolean visit(TypeDeclaration memberTypeDeclaration, ClassScope scope) {
- return process(memberTypeDeclaration);
- }
-
- public boolean visit(TypeDeclaration typeDeclaration,
- CompilationUnitScope scope) {
- return process(typeDeclaration);
- }
- }
-
/**
* Creates JNodes for every method, field, initializer, parameter, and local
* and memorizes the mapping from the JDT Binding to the corresponding JNode
@@ -186,55 +89,33 @@
*/
private static class BuildDeclMapVisitor extends ASTVisitor {
- private ArrayList/* <TypeDeclaration> */fTypeDecls = new ArrayList/* <TypeDeclaration> */();
- private final TypeMap fTypeMap;
- private JProgram fProgram;
+ private ArrayList/* <TypeDeclaration> */typeDecls = new ArrayList/* <TypeDeclaration> */();
+ private final TypeMap typeMap;
+ private JProgram program;
private final JsProgram jsProgram;
private final JsParser jsParser = new JsParser();
public BuildDeclMapVisitor(TypeMap typeMap, JsProgram jsProgram) {
- fTypeMap = typeMap;
- fProgram = fTypeMap.getProgram();
+ this.typeMap = typeMap;
+ program = this.typeMap.getProgram();
this.jsProgram = jsProgram;
}
public TypeDeclaration[] getTypeDeclarataions() {
- return (TypeDeclaration[]) fTypeDecls.toArray(new TypeDeclaration[fTypeDecls.size()]);
- }
-
- private void mapParameters(JMethod method, AbstractMethodDeclaration x) {
- MethodBinding b = x.binding;
- int paramCount = (b.parameters != null ? b.parameters.length : 0);
- if (paramCount > 0) {
- for (int i = 0, n = x.arguments.length; i < n; ++i) {
- createParameter(x.arguments[i].binding, method);
- }
- }
- method.freezeParamTypes();
- }
-
- private void mapThrownExceptions(JMethod method, AbstractMethodDeclaration x) {
- MethodBinding b = x.binding;
- if (b.thrownExceptions != null) {
- for (int i = 0; i < b.thrownExceptions.length; ++i) {
- ReferenceBinding refBinding = b.thrownExceptions[i];
- JClassType thrownException = (JClassType) fTypeMap.get(refBinding);
- method.thrownExceptions.add(thrownException);
- }
- }
+ return (TypeDeclaration[]) typeDecls.toArray(new TypeDeclaration[typeDecls.size()]);
}
public boolean visit(Argument argument, BlockScope scope) {
if (scope == scope.methodScope()) {
return true;
}
-
+
LocalVariableBinding b = argument.binding;
- JType localType = (JType) fTypeMap.get(b.type);
+ JType localType = (JType) typeMap.get(b.type);
JMethod enclosingMethod = findEnclosingMethod(scope);
- JLocal newLocal = fProgram.createLocal(argument.name, localType,
- b.isFinal(), enclosingMethod);
- fTypeMap.put(b, newLocal);
+ JLocal newLocal = program.createLocal(argument.name, localType,
+ b.isFinal(), enclosingMethod);
+ typeMap.put(b, newLocal);
return true;
}
@@ -247,10 +128,11 @@
*/
public boolean visit(ConstructorDeclaration ctorDecl, ClassScope scope) {
MethodBinding b = ctorDecl.binding;
- JClassType enclosingType = (JClassType) fTypeMap.get(scope.enclosingSourceType());
+ JClassType enclosingType = (JClassType) typeMap.get(scope.enclosingSourceType());
String name = enclosingType.getShortName();
- JMethod newMethod = fProgram.createMethod(name.toCharArray(),
- enclosingType, enclosingType, false, false, true, b.isPrivate(), false);
+ JMethod newMethod = program.createMethod(name.toCharArray(),
+ enclosingType, enclosingType, false, false, true, b.isPrivate(),
+ false);
mapThrownExceptions(newMethod, ctorDecl);
int syntheticParamCount = 0;
@@ -271,7 +153,7 @@
alreadyNamedVariables.add(argName);
}
}
-
+
if (nestedBinding.outerLocalVariables != null) {
for (int i = 0; i < nestedBinding.outerLocalVariables.length; ++i) {
SyntheticArgumentBinding arg = nestedBinding.outerLocalVariables[i];
@@ -294,48 +176,65 @@
newMethod.getOriginalParamTypes().remove(0);
}
- fTypeMap.put(b, newMethod);
+ typeMap.put(b, newMethod);
+ return true;
+ }
+
+ public boolean visit(FieldDeclaration fieldDeclaration, MethodScope scope) {
+ FieldBinding b = fieldDeclaration.binding;
+ JReferenceType enclosingType = (JReferenceType) typeMap.get(scope.enclosingSourceType());
+ createField(b, enclosingType, fieldDeclaration.initialization != null);
+ return true;
+ }
+
+ public boolean visit(LocalDeclaration localDeclaration, BlockScope scope) {
+ LocalVariableBinding b = localDeclaration.binding;
+ JType localType = (JType) typeMap.get(localDeclaration.type.resolvedType);
+ JMethod enclosingMethod = findEnclosingMethod(scope);
+ JLocal newLocal = program.createLocal(localDeclaration.name, localType,
+ b.isFinal(), enclosingMethod);
+ typeMap.put(b, newLocal);
return true;
}
public boolean visit(MethodDeclaration methodDeclaration, ClassScope scope) {
MethodBinding b = methodDeclaration.binding;
- JType returnType = (JType) fTypeMap.get(methodDeclaration.returnType.resolvedType);
- JReferenceType enclosingType = (JReferenceType) fTypeMap.get(scope.enclosingSourceType());
- JMethod newMethod = fProgram.createMethod(methodDeclaration.selector,
- enclosingType, returnType, b.isAbstract(), b.isStatic(), b.isFinal(),
- b.isPrivate(), b.isNative());
+ JType returnType = (JType) typeMap.get(methodDeclaration.returnType.resolvedType);
+ JReferenceType enclosingType = (JReferenceType) typeMap.get(scope.enclosingSourceType());
+ JMethod newMethod = program.createMethod(methodDeclaration.selector,
+ enclosingType, returnType, b.isAbstract(), b.isStatic(), b.isFinal(),
+ b.isPrivate(), b.isNative());
mapThrownExceptions(newMethod, methodDeclaration);
mapParameters(newMethod, methodDeclaration);
- fTypeMap.put(b, newMethod);
+ typeMap.put(b, newMethod);
if (newMethod.isNative()) {
// Handle JSNI block
char[] source = methodDeclaration.compilationResult().getCompilationUnit().getContents();
String jsniCode = String.valueOf(source, methodDeclaration.bodyStart,
- methodDeclaration.bodyEnd - methodDeclaration.bodyStart + 1);
+ methodDeclaration.bodyEnd - methodDeclaration.bodyStart + 1);
int startPos = jsniCode.indexOf("/*-{");
int endPos = jsniCode.lastIndexOf("}-*/");
if (startPos < 0 && endPos < 0) {
GenerateJavaAST.reportJsniError(
- methodDeclaration,
- "Native methods require a JavaScript implementation enclosed with /*-{ and }-*/",
- 0);
+ methodDeclaration,
+ "Native methods require a JavaScript implementation enclosed with /*-{ and }-*/",
+ 0);
return true;
}
if (startPos < 0) {
GenerateJavaAST.reportJsniError(
- methodDeclaration,
- "Unable to find start of native block; begin your JavaScript block with: /*-{",
- 0);
+ methodDeclaration,
+ "Unable to find start of native block; begin your JavaScript block with: /*-{",
+ 0);
return true;
}
if (endPos < 0) {
GenerateJavaAST.reportJsniError(
- methodDeclaration,
- "Unable to find end of native block; terminate your JavaScript block with: }-*/",
- 0);
+ methodDeclaration,
+ "Unable to find end of native block; terminate your JavaScript block with: }-*/",
+ 0);
return true;
}
@@ -368,8 +267,8 @@
((JsniMethod) newMethod).setFunc(jsFunction);
} catch (IOException e) {
throw new InternalCompilerException(
- "Internal error parsing JSNI in method '" + newMethod
- + "' in type '" + enclosingType.getName() + "'", e);
+ "Internal error parsing JSNI in method '" + newMethod
+ + "' in type '" + enclosingType.getName() + "'", e);
} catch (JsParserException e) {
/*
@@ -387,10 +286,10 @@
if (i + 1 < n && chars[i + 1] == '\n') {
++i;
}
- // intentional fall-through
+ // intentional fall-through
case '\n':
--line;
- // intentional fall-through
+ // intentional fall-through
default:
++i;
}
@@ -406,21 +305,95 @@
return true;
}
- public boolean visit(FieldDeclaration fieldDeclaration, MethodScope scope) {
- FieldBinding b = fieldDeclaration.binding;
- JReferenceType enclosingType = (JReferenceType) fTypeMap.get(scope.enclosingSourceType());
- createField(b, enclosingType, fieldDeclaration.initialization != null);
- return true;
+ public boolean visit(TypeDeclaration localTypeDeclaration, BlockScope scope) {
+ return process(localTypeDeclaration);
}
- public boolean visit(LocalDeclaration localDeclaration, BlockScope scope) {
- LocalVariableBinding b = localDeclaration.binding;
- JType localType = (JType) fTypeMap.get(localDeclaration.type.resolvedType);
- JMethod enclosingMethod = findEnclosingMethod(scope);
- JLocal newLocal = fProgram.createLocal(localDeclaration.name, localType,
- b.isFinal(), enclosingMethod);
- fTypeMap.put(b, newLocal);
- return true;
+ public boolean visit(TypeDeclaration memberTypeDeclaration, ClassScope scope) {
+ return process(memberTypeDeclaration);
+ }
+
+ public boolean visit(TypeDeclaration typeDeclaration,
+ CompilationUnitScope scope) {
+ return process(typeDeclaration);
+ }
+
+ private JField createField(FieldBinding binding,
+ JReferenceType enclosingType, boolean hasInitializer) {
+ JType type = (JType) typeMap.get(binding.type);
+ JField field = program.createField(binding.name, enclosingType, type,
+ binding.isStatic(), binding.isFinal(), hasInitializer);
+ typeMap.put(binding, field);
+ return field;
+ }
+
+ private JField createField(SyntheticArgumentBinding binding,
+ JReferenceType enclosingType) {
+ JType type = (JType) typeMap.get(binding.type);
+ JField field = program.createField(binding.name, enclosingType, type,
+ false, true, true);
+ if (binding.matchingField != null) {
+ typeMap.put(binding.matchingField, field);
+ }
+ typeMap.put(binding, field);
+ return field;
+ }
+
+ private JParameter createParameter(LocalVariableBinding binding,
+ JMethod enclosingMethod) {
+ JType type = (JType) typeMap.get(binding.type);
+ JParameter param = program.createParameter(binding.name, type,
+ binding.isFinal(), enclosingMethod);
+ typeMap.put(binding, param);
+ return param;
+ }
+
+ private JParameter createParameter(SyntheticArgumentBinding arg,
+ String argName, JMethod enclosingMethod) {
+ JType type = (JType) typeMap.get(arg.type);
+ JParameter param = program.createParameter(argName.toCharArray(), type,
+ true, enclosingMethod);
+ return param;
+ }
+
+ private JMethod findEnclosingMethod(BlockScope scope) {
+ MethodScope methodScope = scope.methodScope();
+ if (methodScope.isInsideInitializer()) {
+ JReferenceType enclosingType = (JReferenceType) typeMap.get(scope.classScope().referenceContext.binding);
+ if (methodScope.isStatic) {
+ // clinit
+ return (JMethod) enclosingType.methods.get(0);
+ } else {
+ // init
+ assert (enclosingType instanceof JClassType);
+ return (JMethod) enclosingType.methods.get(1);
+ }
+ }
+
+ AbstractMethodDeclaration referenceMethod = methodScope.referenceMethod();
+ return (JMethod) typeMap.get(referenceMethod.binding);
+ }
+
+ private void mapParameters(JMethod method, AbstractMethodDeclaration x) {
+ MethodBinding b = x.binding;
+ int paramCount = (b.parameters != null ? b.parameters.length : 0);
+ if (paramCount > 0) {
+ for (int i = 0, n = x.arguments.length; i < n; ++i) {
+ createParameter(x.arguments[i].binding, method);
+ }
+ }
+ method.freezeParamTypes();
+ }
+
+ private void mapThrownExceptions(JMethod method, AbstractMethodDeclaration x) {
+ MethodBinding b = x.binding;
+ if (b.thrownExceptions != null) {
+ for (int i = 0; i < b.thrownExceptions.length; ++i) {
+ ReferenceBinding refBinding = b.thrownExceptions[i];
+ JClassType thrownException = (JClassType) typeMap.get(refBinding);
+ method.thrownExceptions.add(thrownException);
+ }
+ }
}
/**
@@ -442,7 +415,7 @@
*/
return false;
}
- JReferenceType type = (JReferenceType) fTypeMap.get(binding);
+ JReferenceType type = (JReferenceType) typeMap.get(binding);
if (binding.isNestedType() && !binding.isStatic()) {
// add synthentic fields for outer this and locals
@@ -456,7 +429,7 @@
}
}
}
-
+
if (nestedBinding.outerLocalVariables != null) {
for (int i = 0; i < nestedBinding.outerLocalVariables.length; ++i) {
SyntheticArgumentBinding arg = nestedBinding.outerLocalVariables[i];
@@ -468,7 +441,7 @@
ReferenceBinding superClassBinding = binding.superclass();
if (superClassBinding != null) {
assert (binding.superclass().isClass());
- JClassType superClass = (JClassType) fTypeMap.get(superClassBinding);
+ JClassType superClass = (JClassType) typeMap.get(superClassBinding);
type.extnds = superClass;
}
@@ -476,80 +449,122 @@
for (int i = 0; i < superInterfaces.length; ++i) {
ReferenceBinding superInterfaceBinding = superInterfaces[i];
assert (superInterfaceBinding.isInterface());
- JInterfaceType superInterface = (JInterfaceType) fTypeMap.get(superInterfaceBinding);
+ JInterfaceType superInterface = (JInterfaceType) typeMap.get(superInterfaceBinding);
type.implments.add(superInterface);
}
- fTypeDecls.add(typeDeclaration);
+ typeDecls.add(typeDeclaration);
return true;
}
+ }
- private JField createField(FieldBinding binding,
- JReferenceType enclosingType, boolean hasInitializer) {
- JType type = (JType) fTypeMap.get(binding.type);
- JField field = fProgram.createField(binding.name, enclosingType, type,
- binding.isStatic(), binding.isFinal(), hasInitializer);
- fTypeMap.put(binding, field);
- return field;
+ /**
+ * Creates JNodes for every type and memorizes the mapping from the JDT
+ * Binding to the corresponding JNode for each created type. Note that since
+ * there could be forward references, it is not possible to set up supertypes;
+ * it must be done is a subsequent pass.
+ */
+ private static class BuildTypeMapVisitor extends ASTVisitor {
+
+ private final TypeMap typeMap;
+ private final JProgram program;
+
+ public BuildTypeMapVisitor(TypeMap typeMap) {
+ this.typeMap = typeMap;
+ program = this.typeMap.getProgram();
}
- private JField createField(SyntheticArgumentBinding binding,
- JReferenceType enclosingType) {
- JType type = (JType) fTypeMap.get(binding.type);
- JField field = fProgram.createField(binding.name, enclosingType, type,
- false, true, true);
- if (binding.matchingField != null) {
- fTypeMap.put(binding.matchingField, field);
- }
- fTypeMap.put(binding, field);
- return field;
- }
-
- private JParameter createParameter(LocalVariableBinding binding,
- JMethod enclosingMethod) {
- JType type = (JType) fTypeMap.get(binding.type);
- JParameter param = fProgram.createParameter(binding.name, type,
- binding.isFinal(), enclosingMethod);
- fTypeMap.put(binding, param);
- return param;
- }
-
- private JParameter createParameter(SyntheticArgumentBinding arg,
- String argName, JMethod enclosingMethod) {
- JType type = (JType) fTypeMap.get(arg.type);
- JParameter param = fProgram.createParameter(argName.toCharArray(), type,
- true, enclosingMethod);
- return param;
- }
-
- private JMethod findEnclosingMethod(BlockScope scope) {
- MethodScope methodScope = scope.methodScope();
- if (methodScope.isInsideInitializer()) {
- JReferenceType enclosingType = (JReferenceType) fTypeMap.get(scope.classScope().referenceContext.binding);
- if (methodScope.isStatic) {
- // clinit
- return (JMethod) enclosingType.methods.get(0);
- } else {
- // init
- assert (enclosingType instanceof JClassType);
- return (JMethod) enclosingType.methods.get(1);
- }
- }
-
- AbstractMethodDeclaration referenceMethod = methodScope.referenceMethod();
- return (JMethod) fTypeMap.get(referenceMethod.binding);
+ public boolean visit(TypeDeclaration localTypeDeclaration, BlockScope scope) {
+ assert (localTypeDeclaration.kind() != IGenericType.INTERFACE_DECL);
+ return process(localTypeDeclaration);
}
public boolean visit(TypeDeclaration memberTypeDeclaration, ClassScope scope) {
return process(memberTypeDeclaration);
}
- public boolean visit(TypeDeclaration localTypeDeclaration, BlockScope scope) {
- return process(localTypeDeclaration);
- }
-
public boolean visit(TypeDeclaration typeDeclaration,
CompilationUnitScope scope) {
return process(typeDeclaration);
}
+
+ private boolean process(TypeDeclaration typeDeclaration) {
+ char[][] name = typeDeclaration.binding.compoundName;
+ SourceTypeBinding binding = typeDeclaration.binding;
+ if (binding instanceof LocalTypeBinding) {
+ char[] localName = binding.constantPoolName();
+ if (localName == null) {
+ /*
+ * Weird case: if JDT determines that this local class is totally
+ * uninstantiable, it won't bother allocating a local name.
+ */
+ return false;
+ }
+
+ for (int i = 0, c = localName.length; i < c; ++i) {
+ if (localName[i] == '/') {
+ localName[i] = '.';
+ }
+ }
+ name = new char[1][0];
+ name[0] = localName;
+ }
+
+ JReferenceType newType;
+ if (binding.isClass()) {
+ newType = program.createClass(name, binding.isAbstract(),
+ binding.isFinal());
+ } else if (binding.isInterface()) {
+ newType = program.createInterface(name);
+ } else {
+ assert (false);
+ return false;
+ }
+
+ /**
+ * We emulate static initializers and intance initializers as methods. As
+ * in other cases, this gives us: simpler AST, easier to optimize, more
+ * like output JavaScript. Clinit is always in slot 0, init (if it exists)
+ * is always in slot 1.
+ */
+ JMethod clinit = program.createMethod("$clinit".toCharArray(), newType,
+ program.getTypeVoid(), false, true, true, true, false);
+ clinit.freezeParamTypes();
+
+ if (newType instanceof JClassType) {
+ JMethod init = program.createMethod("$init".toCharArray(), newType,
+ program.getTypeVoid(), false, false, true, true, false);
+ init.freezeParamTypes();
+ }
+
+ typeMap.put(binding, newType);
+ return true;
+ }
+ }
+
+ public static TypeDeclaration[] exec(TypeMap typeMap,
+ CompilationUnitDeclaration[] unitDecls, JsProgram jsProgram) {
+ createPeersForTypes(unitDecls, typeMap);
+ return createPeersForNonTypeDecls(unitDecls, typeMap, jsProgram);
+ }
+
+ private static TypeDeclaration[] createPeersForNonTypeDecls(
+ CompilationUnitDeclaration[] unitDecls, TypeMap typeMap,
+ JsProgram jsProgram) {
+ // Traverse again to create our JNode peers for each method, field,
+ // parameter, and local
+ BuildDeclMapVisitor v2 = new BuildDeclMapVisitor(typeMap, jsProgram);
+ for (int i = 0; i < unitDecls.length; ++i) {
+ unitDecls[i].traverse(v2, unitDecls[i].scope);
+ }
+ return v2.getTypeDeclarataions();
+ }
+
+ private static void createPeersForTypes(
+ CompilationUnitDeclaration[] unitDecls, TypeMap typeMap) {
+ // Traverse once to create our JNode peers for each type
+ BuildTypeMapVisitor v1 = new BuildTypeMapVisitor(typeMap);
+ for (int i = 0; i < unitDecls.length; ++i) {
+ unitDecls[i].traverse(v1, unitDecls[i].scope);
+ }
}
}
diff --git a/dev/core/src/com/google/gwt/dev/jjs/impl/CastNormalizer.java b/dev/core/src/com/google/gwt/dev/jjs/impl/CastNormalizer.java
index 1f4e4ad..2102401 100644
--- a/dev/core/src/com/google/gwt/dev/jjs/impl/CastNormalizer.java
+++ b/dev/core/src/com/google/gwt/dev/jjs/impl/CastNormalizer.java
@@ -1,4 +1,18 @@
-// Copyright 2006 Google Inc. All Rights Reserved.
+/*
+ * Copyright 2006 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.impl;
import com.google.gwt.dev.jjs.ast.JArrayRef;
@@ -43,92 +57,18 @@
*/
public class CastNormalizer {
- private Map/* <JReferenceType, Integer> */queryIds = new IdentityHashMap();
-
- /**
- * Explicitly convert any char-typed expressions within a concat operation
- * into strings.
- */
- private class ConcatVisitor extends JVisitor {
-
- private final ChangeList changeList = new ChangeList(
- "Convert chars to Strings inside of concat operations.");
-
- private JMethod fStringValueOfChar = null;
-
- public ChangeList getChangeList() {
- return changeList;
- }
-
- // @Override
- public void endVisit(JBinaryOperation x, Mutator m) {
- if (x.getType() != program.getTypeJavaLangString()) {
- return;
- }
-
- if (x.op == JBinaryOperator.ADD) {
- convertCharString(x.lhs);
- convertCharString(x.rhs);
- } else if (x.op == JBinaryOperator.ASG_ADD) {
- convertCharString(x.rhs);
- }
- }
-
- private void convertCharString(Mutator m) {
- JPrimitiveType charType = program.getTypePrimitiveChar();
- JExpression expr = m.get();
- if (expr.getType() == charType) {
- if (fStringValueOfChar == null) {
- fStringValueOfChar = program.getSpecialMethod("Cast.charToString");
- assert (fStringValueOfChar != null);
- }
- JMethodCall call = new JMethodCall(program, null, fStringValueOfChar);
- ChangeList myChangeList = new ChangeList("Replace '" + expr
- + "' with a call to Cast.charToString()");
- myChangeList.addExpression(m, call.args);
- myChangeList.replaceExpression(m, call);
- changeList.add(myChangeList);
- }
- }
- }
-
- /**
- * Explicitly cast all integral divide operations to trigger replacements with
- * narrowing calls in the next pass.
- */
- private class DivVisitor extends JVisitor {
-
- private final ChangeList changeList = new ChangeList(
- "Explicitly cast all integral division operations.");
-
- public ChangeList getChangeList() {
- return changeList;
- }
-
- // @Override
- public void endVisit(JBinaryOperation x, Mutator m) {
- JType type = x.getType();
- if (x.op == JBinaryOperator.DIV
- && type != program.getTypePrimitiveFloat()
- && type != program.getTypePrimitiveDouble()) {
- JCastOperation cast = new JCastOperation(program, type,
- program.getLiteralNull());
- ChangeList myChangeList = new ChangeList("Cast '" + x + "' to type '"
- + type + "'");
- myChangeList.changeType(x, program.getTypePrimitiveDouble());
- myChangeList.replaceExpression(cast.expr, m);
- myChangeList.replaceExpression(m, cast);
- changeList.add(myChangeList);
- }
- }
- }
-
private class AssignTypeIdsVisitor extends JVisitor {
+ Set/* <JClassType> */alreadyRan = new HashSet/* <JClassType> */();
private Map/* <JReferenceType, Set<JReferenceType>> */queriedTypes = new IdentityHashMap();
private int nextQueryId = 1; // 0 is reserved
+
private final List/* <JArrayType> */instantiatedArrayTypes = new ArrayList/* <JArrayType> */();
+ private List/* <JClassType> */classes = new ArrayList/* <JClassType> */();
+
+ private List/* <JsonObject> */jsonObjects = new ArrayList/* <JsonObject> */();
+
{
JTypeOracle typeOracle = program.typeOracle;
for (Iterator it = program.getAllArrayTypes().iterator(); it.hasNext();) {
@@ -139,6 +79,34 @@
}
}
+ public void computeTypeIds() {
+
+ // the 0th entry is the "always false" entry
+ classes.add(null);
+ jsonObjects.add(new JsonObject(program));
+
+ /*
+ * Compute the list of classes than can successfully satisfy cast
+ * requests, along with the set of types they can be successfully cast to.
+ * Do it in super type order.
+ */
+ for (Iterator it = program.getDeclaredTypes().iterator(); it.hasNext();) {
+ JReferenceType type = (JReferenceType) it.next();
+ if (type instanceof JClassType) {
+ computeSourceClass((JClassType) type);
+ }
+ }
+
+ for (Iterator it = program.getAllArrayTypes().iterator(); it.hasNext();) {
+ JArrayType type = (JArrayType) it.next();
+ computeSourceClass(type);
+ }
+
+ // pass our info to JProgram
+ program.initTypeInfo(classes, jsonObjects);
+ program.recordQueryIds(queryIds);
+ }
+
/*
* If this expression could possibly generate an ArrayStoreException, we
* must record a query on the element type being assigned to.
@@ -198,66 +166,6 @@
recordCast(x.testType, x.getExpression());
}
- private void recordCast(JType targetType, JExpression rhs) {
- if (targetType instanceof JReferenceType) {
- // unconditional cast b/c it would've been a semantic error earlier
- JReferenceType rhsType = (JReferenceType) rhs.getType();
- // don't record a type for trivial casts that won't generate code
- if (rhsType instanceof JClassType) {
- if (program.typeOracle.canTriviallyCast(rhsType,
- (JReferenceType) targetType)) {
- return;
- }
- }
-
- recordCastInternal((JReferenceType) targetType, rhsType);
- }
- }
-
- private void recordCastInternal(JReferenceType targetType,
- JReferenceType rhsType) {
- JReferenceType toType = targetType;
- Set/* <JReferenceType> */querySet = (Set) queriedTypes.get(toType);
- if (querySet == null) {
- queryIds.put(toType, new Integer(nextQueryId++));
- querySet = new HashSet/* <JReferenceType> */();
- queriedTypes.put(toType, querySet);
- }
- querySet.add(rhsType);
- }
-
- Set/* <JClassType> */alreadyRan = new HashSet/* <JClassType> */();
- private List/* <JClassType> */classes = new ArrayList/* <JClassType> */();
- private List/* <JsonObject> */jsonObjects = new ArrayList/* <JsonObject> */();
-
- public void computeTypeIds() {
-
- // the 0th entry is the "always false" entry
- classes.add(null);
- jsonObjects.add(new JsonObject(program));
-
- /*
- * Compute the list of classes than can successfully satisfy cast
- * requests, along with the set of types they can be successfully cast to.
- * Do it in super type order.
- */
- for (Iterator it = program.getDeclaredTypes().iterator(); it.hasNext();) {
- JReferenceType type = (JReferenceType) it.next();
- if (type instanceof JClassType) {
- computeSourceClass((JClassType) type);
- }
- }
-
- for (Iterator it = program.getAllArrayTypes().iterator(); it.hasNext();) {
- JArrayType type = (JArrayType) it.next();
- computeSourceClass(type);
- }
-
- // pass our info to JProgram
- program.initTypeInfo(classes, jsonObjects);
- program.recordQueryIds(queryIds);
- }
-
/**
* Create the data for JSON table to capture the mapping from a class to its
* query types.
@@ -325,7 +233,7 @@
JIntLiteral labelExpr = program.getLiteralInt(i);
JIntLiteral valueExpr = program.getLiteralInt(1);
jsonObject.propInits.add(new JsonPropInit(program, labelExpr,
- valueExpr));
+ valueExpr));
}
}
@@ -333,16 +241,118 @@
classes.add(type);
jsonObjects.add(jsonObject);
}
+
+ private void recordCast(JType targetType, JExpression rhs) {
+ if (targetType instanceof JReferenceType) {
+ // unconditional cast b/c it would've been a semantic error earlier
+ JReferenceType rhsType = (JReferenceType) rhs.getType();
+ // don't record a type for trivial casts that won't generate code
+ if (rhsType instanceof JClassType) {
+ if (program.typeOracle.canTriviallyCast(rhsType,
+ (JReferenceType) targetType)) {
+ return;
+ }
+ }
+
+ recordCastInternal((JReferenceType) targetType, rhsType);
+ }
+ }
+
+ private void recordCastInternal(JReferenceType targetType,
+ JReferenceType rhsType) {
+ JReferenceType toType = targetType;
+ Set/* <JReferenceType> */querySet = (Set) queriedTypes.get(toType);
+ if (querySet == null) {
+ queryIds.put(toType, new Integer(nextQueryId++));
+ querySet = new HashSet/* <JReferenceType> */();
+ queriedTypes.put(toType, querySet);
+ }
+ querySet.add(rhsType);
+ }
+ }
+
+ /**
+ * Explicitly convert any char-typed expressions within a concat operation
+ * into strings.
+ */
+ private class ConcatVisitor extends JVisitor {
+
+ private final ChangeList changeList = new ChangeList(
+ "Convert chars to Strings inside of concat operations.");
+
+ private JMethod stringValueOfChar = null;
+
+ // @Override
+ public void endVisit(JBinaryOperation x, Mutator m) {
+ if (x.getType() != program.getTypeJavaLangString()) {
+ return;
+ }
+
+ if (x.op == JBinaryOperator.ADD) {
+ convertCharString(x.lhs);
+ convertCharString(x.rhs);
+ } else if (x.op == JBinaryOperator.ASG_ADD) {
+ convertCharString(x.rhs);
+ }
+ }
+
+ public ChangeList getChangeList() {
+ return changeList;
+ }
+
+ private void convertCharString(Mutator m) {
+ JPrimitiveType charType = program.getTypePrimitiveChar();
+ JExpression expr = m.get();
+ if (expr.getType() == charType) {
+ if (stringValueOfChar == null) {
+ stringValueOfChar = program.getSpecialMethod("Cast.charToString");
+ assert (stringValueOfChar != null);
+ }
+ JMethodCall call = new JMethodCall(program, null, stringValueOfChar);
+ ChangeList myChangeList = new ChangeList("Replace '" + expr
+ + "' with a call to Cast.charToString()");
+ myChangeList.addExpression(m, call.args);
+ myChangeList.replaceExpression(m, call);
+ changeList.add(myChangeList);
+ }
+ }
+ }
+
+ /**
+ * Explicitly cast all integral divide operations to trigger replacements with
+ * narrowing calls in the next pass.
+ */
+ private class DivVisitor extends JVisitor {
+
+ private final ChangeList changeList = new ChangeList(
+ "Explicitly cast all integral division operations.");
+
+ // @Override
+ public void endVisit(JBinaryOperation x, Mutator m) {
+ JType type = x.getType();
+ if (x.op == JBinaryOperator.DIV
+ && type != program.getTypePrimitiveFloat()
+ && type != program.getTypePrimitiveDouble()) {
+ JCastOperation cast = new JCastOperation(program, type,
+ program.getLiteralNull());
+ ChangeList myChangeList = new ChangeList("Cast '" + x + "' to type '"
+ + type + "'");
+ myChangeList.changeType(x, program.getTypePrimitiveDouble());
+ myChangeList.replaceExpression(cast.expr, m);
+ myChangeList.replaceExpression(m, cast);
+ changeList.add(myChangeList);
+ }
+ }
+
+ public ChangeList getChangeList() {
+ return changeList;
+ }
}
private class ReplaceTypeChecksVisitor extends JVisitor {
private final ChangeList changeList = new ChangeList(
- "Replace all casts and instanceof operations.");
-
- public ChangeList getChangeList() {
- return changeList;
- }
+ "Replace all casts and instanceof operations.");
// @Override
public void endVisit(JCastOperation x, Mutator m) {
@@ -369,7 +379,8 @@
changeList.add(myChangeList);
}
if (argType instanceof JClassType
- && program.typeOracle.canTriviallyCast((JClassType) argType, refType)) {
+ && program.typeOracle.canTriviallyCast((JClassType) argType,
+ refType)) {
// just remove the cast
changeList.replaceExpression(m, x.expr);
} else {
@@ -411,12 +422,12 @@
}
} else if (tLong == fromType) {
if (tByte == toType || tShort == toType || tChar == toType
- || tInt == toType) {
+ || tInt == toType) {
narrow = true;
}
} else if (tFloat == fromType || tDouble == fromType) {
if (tByte == toType || tShort == toType || tChar == toType
- || tInt == toType || tLong == toType) {
+ || tInt == toType || tLong == toType) {
round = true;
}
}
@@ -424,9 +435,9 @@
ChangeList myChangeList;
if (narrow || round) {
String methodName = "Cast." + (narrow ? "narrow_" : "round_")
- + toType.getName();
+ + toType.getName();
myChangeList = new ChangeList("Replace '" + x + "' with a call to "
- + methodName);
+ + methodName);
JMethod castMethod = program.getSpecialMethod(methodName);
JMethodCall call = new JMethodCall(program, null, castMethod);
myChangeList.addExpression(x.expr, call.args);
@@ -443,14 +454,15 @@
public void endVisit(JInstanceOf x, Mutator m) {
JType argType = x.getExpression().getType();
if (argType instanceof JClassType
- && program.typeOracle.canTriviallyCast((JClassType) argType, x.testType)) {
+ && program.typeOracle.canTriviallyCast((JClassType) argType,
+ x.testType)) {
// trivially true if non-null
JNullLiteral nullLit = program.getLiteralNull();
JBinaryOperation eq = new JBinaryOperation(program,
- program.getTypePrimitiveBoolean(), JBinaryOperator.NEQ, nullLit,
- nullLit);
+ program.getTypePrimitiveBoolean(), JBinaryOperator.NEQ, nullLit,
+ nullLit);
ChangeList myChangeList = new ChangeList("Replace '" + x
- + "' with a simple null test.");
+ + "' with a simple null test.");
myChangeList.replaceExpression(eq.lhs, x.expr);
myChangeList.replaceExpression(m, eq);
changeList.add(myChangeList);
@@ -461,12 +473,16 @@
}
}
+ public ChangeList getChangeList() {
+ return changeList;
+ }
+
private void replaceCast(JMethodCall call, JReferenceType type,
Mutator dest, Mutator arg) {
Integer boxedInt = (Integer) queryIds.get(type);
JIntLiteral qId = program.getLiteralInt(boxedInt.intValue());
ChangeList myChangeList = new ChangeList("Replace '" + dest.get()
- + " with a call to " + call.getTarget().getName());
+ + " with a call to " + call.getTarget().getName());
myChangeList.addExpression(arg, call.args);
myChangeList.addExpression(qId, call.args);
myChangeList.replaceExpression(dest, call);
@@ -474,6 +490,18 @@
}
}
+ public static void exec(JProgram program) {
+ new CastNormalizer(program).execImpl();
+ }
+
+ private Map/* <JReferenceType, Integer> */queryIds = new IdentityHashMap();
+
+ private final JProgram program;
+
+ private CastNormalizer(JProgram program) {
+ this.program = program;
+ }
+
private void execImpl() {
{
ConcatVisitor visitor = new ConcatVisitor();
@@ -506,14 +534,4 @@
}
}
- private final JProgram program;
-
- private CastNormalizer(JProgram program) {
- this.program = program;
- }
-
- public static void exec(JProgram program) {
- new CastNormalizer(program).execImpl();
- }
-
}
diff --git a/dev/core/src/com/google/gwt/dev/jjs/impl/CastOptimizer.java b/dev/core/src/com/google/gwt/dev/jjs/impl/CastOptimizer.java
index 90eaf97..36ae6e1 100644
--- a/dev/core/src/com/google/gwt/dev/jjs/impl/CastOptimizer.java
+++ b/dev/core/src/com/google/gwt/dev/jjs/impl/CastOptimizer.java
@@ -1,4 +1,18 @@
-// Copyright 2006 Google Inc. All Rights Reserved.
+/*
+ * Copyright 2006 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.impl;
import com.google.gwt.dev.jjs.ast.JBinaryOperation;
@@ -17,7 +31,7 @@
import com.google.gwt.dev.jjs.ast.change.ChangeList;
/**
- * Optimizer that will remove all trivially computable casts and instanceof
+ * Optimizer that will remove all trivially computable casts and instanceof
* operations.
*/
public class CastOptimizer {
@@ -25,17 +39,13 @@
private class ReplaceTrivialCastsVisitor extends JVisitor {
private final ChangeList changeList = new ChangeList(
- "Replace all trivially computable casts and instanceof operations.");
-
- public ChangeList getChangeList() {
- return changeList;
- }
+ "Replace all trivially computable casts and instanceof operations.");
// @Override
public void endVisit(JCastOperation x, Mutator m) {
JType argType = x.getExpression().getType();
if (!(x.castType instanceof JReferenceType)
- || !(argType instanceof JReferenceType)) {
+ || !(argType instanceof JReferenceType)) {
return;
}
@@ -66,9 +76,9 @@
* call completes normally it will return null.
*/
JMethodCall call = new JMethodCall(program, null, method,
- program.getTypeNull());
+ program.getTypeNull());
ChangeList myChangeList = new ChangeList("Replace '" + x
- + "' with a call to throwClassCastExceptionUnlessNull().");
+ + "' with a call to throwClassCastExceptionUnlessNull().");
myChangeList.addExpression(x.expr, call.args);
myChangeList.replaceExpression(m, call);
changeList.add(myChangeList);
@@ -105,10 +115,10 @@
// replace with a simple null test
JNullLiteral nullLit = program.getLiteralNull();
JBinaryOperation eq = new JBinaryOperation(program,
- program.getTypePrimitiveBoolean(), JBinaryOperator.NEQ, nullLit,
- nullLit);
+ program.getTypePrimitiveBoolean(), JBinaryOperator.NEQ, nullLit,
+ nullLit);
ChangeList myChangeList = new ChangeList("Replace '" + x
- + "' with a simple null test.");
+ + "' with a simple null test.");
myChangeList.replaceExpression(eq.lhs, x.expr);
myChangeList.replaceExpression(m, eq);
changeList.add(myChangeList);
@@ -118,6 +128,20 @@
changeList.replaceExpression(m, program.getLiteralBoolean(false));
}
}
+
+ public ChangeList getChangeList() {
+ return changeList;
+ }
+ }
+
+ public static boolean exec(JProgram program) {
+ return new CastOptimizer(program).execImpl();
+ }
+
+ private final JProgram program;
+
+ private CastOptimizer(JProgram program) {
+ this.program = program;
}
private boolean execImpl() {
@@ -130,14 +154,4 @@
changes.apply();
return true;
}
-
- private final JProgram program;
-
- private CastOptimizer(JProgram program) {
- this.program = program;
- }
-
- public static boolean exec(JProgram program) {
- return new CastOptimizer(program).execImpl();
- }
}
diff --git a/dev/core/src/com/google/gwt/dev/jjs/impl/CatchBlockNormalizer.java b/dev/core/src/com/google/gwt/dev/jjs/impl/CatchBlockNormalizer.java
index 6f3ddc8..aadfdbd 100644
--- a/dev/core/src/com/google/gwt/dev/jjs/impl/CatchBlockNormalizer.java
+++ b/dev/core/src/com/google/gwt/dev/jjs/impl/CatchBlockNormalizer.java
@@ -1,4 +1,18 @@
-// Copyright 2006 Google Inc. All Rights Reserved.
+/*
+ * Copyright 2006 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.impl;
import com.google.gwt.dev.jjs.ast.JBlock;
@@ -27,35 +41,15 @@
*/
public class CatchBlockNormalizer {
- private JMethod fCurrentMethod;
- private final List/*<JLocal>*/ fTempLocals = new ArrayList/*<JLocal>*/();
- private int fLocalIndex;
-
- private void clearLocals() {
- fTempLocals.clear();
- fLocalIndex = 0;
- }
-
- private void pushTempLocal() {
- if (fLocalIndex == fTempLocals.size()) {
- JLocal newTemp = program.createLocal(("$e" + fLocalIndex).toCharArray(),
- program.getTypeJavaLangObject(), false, fCurrentMethod);
- fTempLocals.add(newTemp);
- }
- ++fLocalIndex;
- }
-
- private JLocal popTempLocal() {
- return (JLocal) fTempLocals.get(--fLocalIndex);
- }
-
private class CollapseCatchBlocks extends JVisitor {
private final ChangeList changeList = new ChangeList(
- "Collapse all multi-catch blocks into a single catch block.");
+ "Collapse all multi-catch blocks into a single catch block.");
- public ChangeList getChangeList() {
- return changeList;
+ // @Override
+ public void endVisit(JMethod x) {
+ clearLocals();
+ currentMethod = null;
}
// @Override
@@ -65,7 +59,7 @@
}
ChangeList myChangeList = new ChangeList("Merge " + x.catchBlocks.size()
- + " catch blocks.");
+ + " catch blocks.");
JLocal exObj = popTempLocal();
JLocalRef exRef = new JLocalRef(program, exObj);
JBlock newCatchBlock = new JBlock(program);
@@ -104,6 +98,17 @@
changeList.add(myChangeList);
}
+ public ChangeList getChangeList() {
+ return changeList;
+ }
+
+ // @Override
+ public boolean visit(JMethod x) {
+ currentMethod = x;
+ clearLocals();
+ return true;
+ }
+
// @Override
public boolean visit(JTryStatement x) {
if (!x.catchBlocks.isEmpty()) {
@@ -111,19 +116,27 @@
}
return true;
}
+ }
- // @Override
- public void endVisit(JMethod x) {
- clearLocals();
- fCurrentMethod = null;
- }
+ public static void exec(JProgram program) {
+ new CatchBlockNormalizer(program).execImpl();
+ }
- // @Override
- public boolean visit(JMethod x) {
- fCurrentMethod = x;
- clearLocals();
- return true;
- }
+ private JMethod currentMethod;
+
+ private final List/* <JLocal> */tempLocals = new ArrayList/* <JLocal> */();
+
+ private int localIndex;
+
+ private final JProgram program;
+
+ private CatchBlockNormalizer(JProgram program) {
+ this.program = program;
+ }
+
+ private void clearLocals() {
+ tempLocals.clear();
+ localIndex = 0;
}
private void execImpl() {
@@ -137,14 +150,17 @@
}
}
- private final JProgram program;
-
- private CatchBlockNormalizer(JProgram program) {
- this.program = program;
+ private JLocal popTempLocal() {
+ return (JLocal) tempLocals.get(--localIndex);
}
- public static void exec(JProgram program) {
- new CatchBlockNormalizer(program).execImpl();
+ private void pushTempLocal() {
+ if (localIndex == tempLocals.size()) {
+ JLocal newTemp = program.createLocal(("$e" + localIndex).toCharArray(),
+ program.getTypeJavaLangObject(), false, currentMethod);
+ tempLocals.add(newTemp);
+ }
+ ++localIndex;
}
}
diff --git a/dev/core/src/com/google/gwt/dev/jjs/impl/CompoundAssignmentNormalizer.java b/dev/core/src/com/google/gwt/dev/jjs/impl/CompoundAssignmentNormalizer.java
index 8bd50d1..c2fcc16 100644
--- a/dev/core/src/com/google/gwt/dev/jjs/impl/CompoundAssignmentNormalizer.java
+++ b/dev/core/src/com/google/gwt/dev/jjs/impl/CompoundAssignmentNormalizer.java
@@ -1,4 +1,18 @@
-// Copyright 2006 Google Inc. All Rights Reserved.
+/*
+ * Copyright 2006 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.impl;
import com.google.gwt.dev.jjs.ast.Holder;
@@ -28,39 +42,91 @@
*/
public class CompoundAssignmentNormalizer {
- private JMethod fCurrentMethod;
- private final List/*<JLocal>*/ fTempLocals = new ArrayList/*<JLocal>*/();
- private int fLocalIndex;
-
- private void clearLocals() {
- fTempLocals.clear();
- fLocalIndex = 0;
- }
-
- private JLocal getTempLocal() {
- if (fLocalIndex < fTempLocals.size()) {
- return (JLocal) fTempLocals.get(fLocalIndex++);
- }
- JLocal newTemp = program.createLocal(("$t" + fLocalIndex++).toCharArray(),
- program.getTypeVoid(), false, fCurrentMethod);
- fTempLocals.add(newTemp);
- return newTemp;
- }
-
- private class ReplaceSideEffectsInLvalue extends JVisitor {
+ private class BreakupAssignOpsVisitor extends JVisitor {
private final ChangeList changeList = new ChangeList(
- "Replace side effects in lvalue.");
+ "Break apart certain complex assignments.");
+
+ // @Override
+ public void endVisit(JBinaryOperation x, Mutator m) {
+ /*
+ * Convert to a normal divide operation so we can cast the result. Since
+ * the left hand size must be computed twice, we have to replace any
+ * left-hand side expressions that could have side effects with
+ * temporaries, so that they are only run once.
+ */
+ if (x.op == JBinaryOperator.ASG_DIV
+ && x.getType() != program.getTypePrimitiveFloat()
+ && x.getType() != program.getTypePrimitiveDouble()) {
+
+ /*
+ * Convert to a normal divide operation so we can cast the result. Since
+ * the left hand size must be computed twice, we have to replace any
+ * left-hand side expressions that could have side effects with
+ * temporaries, so that they are only run once.
+ */
+ final int pushUsedLocals = localIndex;
+ JMultiExpression multi = new JMultiExpression(program);
+ ReplaceSideEffectsInLvalue replacer = new ReplaceSideEffectsInLvalue(
+ multi);
+ x.lhs.traverse(replacer);
+ localIndex = pushUsedLocals;
+
+ JNullLiteral litNull = program.getLiteralNull();
+ JBinaryOperation operation = new JBinaryOperation(program,
+ x.getLhs().getType(), JBinaryOperator.DIV, litNull, litNull);
+ JBinaryOperation asg = new JBinaryOperation(program,
+ x.getLhs().getType(), JBinaryOperator.ASG, litNull, operation);
+
+ ChangeList myChangeList = new ChangeList("Break '" + x
+ + "' into two operations.");
+
+ myChangeList.replaceExpression(operation.lhs, x.lhs);
+ myChangeList.replaceExpression(operation.rhs, x.rhs);
+ myChangeList.replaceExpression(asg.lhs, x.lhs);
+
+ if (replacer.getChangeList().empty()) {
+ myChangeList.replaceExpression(m, asg);
+ } else {
+ myChangeList.add(replacer.getChangeList());
+ myChangeList.addExpression(asg, multi.exprs);
+ myChangeList.replaceExpression(m, multi);
+ }
+
+ changeList.add(myChangeList);
+ }
+ }
+
+ // @Override
+ public void endVisit(JMethod x) {
+ clearLocals();
+ currentMethod = null;
+ }
public ChangeList getChangeList() {
return changeList;
}
+ // @Override
+ public boolean visit(JMethod x) {
+ currentMethod = x;
+ clearLocals();
+ return true;
+ }
+ }
+ private class ReplaceSideEffectsInLvalue extends JVisitor {
+ private final ChangeList changeList = new ChangeList(
+ "Replace side effects in lvalue.");
+
private final JMultiExpression multi;
ReplaceSideEffectsInLvalue(JMultiExpression multi) {
this.multi = multi;
}
+ public ChangeList getChangeList() {
+ return changeList;
+ }
+
// @Override
public boolean visit(JArrayRef x, Mutator m) {
possiblyReplace(x.instance);
@@ -102,7 +168,7 @@
// Create an assignment for this temp and add it to multi.
JLocalRef tempRef = new JLocalRef(program, tempLocal);
JBinaryOperation asg = new JBinaryOperation(program, x.get().getType(),
- JBinaryOperator.ASG, tempRef, program.getLiteralNull());
+ JBinaryOperator.ASG, tempRef, program.getLiteralNull());
changeList.replaceExpression(asg.rhs, x);
changeList.addExpression(asg, multi.exprs);
// Update me with the temp
@@ -110,76 +176,25 @@
}
}
- private class BreakupAssignOpsVisitor extends JVisitor {
- private final ChangeList changeList = new ChangeList(
- "Break apart certain complex assignments.");
+ public static void exec(JProgram program) {
+ new CompoundAssignmentNormalizer(program).execImpl();
+ }
- public ChangeList getChangeList() {
- return changeList;
- }
+ private JMethod currentMethod;
- // @Override
- public void endVisit(JBinaryOperation x, Mutator m) {
- /*
- * Convert to a normal divide operation so we can cast the result. Since
- * the left hand size must be computed twice, we have to replace any
- * left-hand side expressions that could have side effects with
- * temporaries, so that they are only run once.
- */
- if (x.op == JBinaryOperator.ASG_DIV
- && x.getType() != program.getTypePrimitiveFloat()
- && x.getType() != program.getTypePrimitiveDouble()) {
+ private final List/* <JLocal> */tempLocals = new ArrayList/* <JLocal> */();
- /*
- * Convert to a normal divide operation so we can cast the result. Since
- * the left hand size must be computed twice, we have to replace any
- * left-hand side expressions that could have side effects with
- * temporaries, so that they are only run once.
- */
- final int pushUsedLocals = fLocalIndex;
- JMultiExpression multi = new JMultiExpression(program);
- ReplaceSideEffectsInLvalue replacer = new ReplaceSideEffectsInLvalue(
- multi);
- x.lhs.traverse(replacer);
- fLocalIndex = pushUsedLocals;
+ private int localIndex;
- JNullLiteral litNull = program.getLiteralNull();
- JBinaryOperation operation = new JBinaryOperation(program, x.getLhs()
- .getType(), JBinaryOperator.DIV, litNull, litNull);
- JBinaryOperation asg = new JBinaryOperation(program, x.getLhs()
- .getType(), JBinaryOperator.ASG, litNull, operation);
+ private final JProgram program;
- ChangeList myChangeList = new ChangeList("Break '" + x
- + "' into two operations.");
+ private CompoundAssignmentNormalizer(JProgram program) {
+ this.program = program;
+ }
- myChangeList.replaceExpression(operation.lhs, x.lhs);
- myChangeList.replaceExpression(operation.rhs, x.rhs);
- myChangeList.replaceExpression(asg.lhs, x.lhs);
-
- if (replacer.getChangeList().empty()) {
- myChangeList.replaceExpression(m, asg);
- } else {
- myChangeList.add(replacer.getChangeList());
- myChangeList.addExpression(asg, multi.exprs);
- myChangeList.replaceExpression(m, multi);
- }
-
- changeList.add(myChangeList);
- }
- }
-
- // @Override
- public void endVisit(JMethod x) {
- clearLocals();
- fCurrentMethod = null;
- }
-
- // @Override
- public boolean visit(JMethod x) {
- fCurrentMethod = x;
- clearLocals();
- return true;
- }
+ private void clearLocals() {
+ tempLocals.clear();
+ localIndex = 0;
}
private void execImpl() {
@@ -191,14 +206,14 @@
}
}
- private final JProgram program;
-
- private CompoundAssignmentNormalizer(JProgram program) {
- this.program = program;
- }
-
- public static void exec(JProgram program) {
- new CompoundAssignmentNormalizer(program).execImpl();
+ private JLocal getTempLocal() {
+ if (localIndex < tempLocals.size()) {
+ return (JLocal) tempLocals.get(localIndex++);
+ }
+ JLocal newTemp = program.createLocal(("$t" + localIndex++).toCharArray(),
+ program.getTypeVoid(), false, currentMethod);
+ tempLocals.add(newTemp);
+ return newTemp;
}
}
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 c94b399..b12495a 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
@@ -1,4 +1,18 @@
-// Copyright 2006 Google Inc. All Rights Reserved.
+/*
+ * Copyright 2006 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.impl;
import com.google.gwt.dev.jjs.ast.CanBeStatic;
@@ -167,7 +181,7 @@
public class GenerateJavaAST {
/**
- * Comparator for <code>HasName</code> instances.
+ * Comparator for <code>HasName</code> instances.
*/
public static class HasNameSort implements Comparator/* <HasName> */ {
public int compare(Object o1, Object o2) {
@@ -204,9 +218,27 @@
return sb.toString();
}
+ private Object[] args = new Object[1];
+
+ private JReferenceType currentClass;
+
+ private ClassScope currentClassScope;
+
+ private JMethod currentMethod;
+
+ private MethodScope currentMethodScope;
+
+ private final Map/* <JMethod, Map<String, JLabel>> */labelMap = new IdentityHashMap();
+
+ private Class[] params = new Class[1];
+
+ private final TypeMap typeMap;
+
+ private final JProgram program;
+
public JavaASTGenerationVisitor(TypeMap typeMap) {
- fTypeMap = typeMap;
- program = fTypeMap.getProgram();
+ this.typeMap = typeMap;
+ program = this.typeMap.getProgram();
}
/**
@@ -215,8 +247,8 @@
* output JavaScript.
*/
public void processType(TypeDeclaration x) {
- fCurrentClass = (JReferenceType) fTypeMap.get(x.binding);
- fCurrentClassScope = x.scope;
+ currentClass = (JReferenceType) typeMap.get(x.binding);
+ currentClassScope = x.scope;
if (x.fields != null) {
// Process fields
@@ -224,16 +256,16 @@
FieldDeclaration fieldDeclaration = x.fields[i];
if (fieldDeclaration.isStatic()) {
// clinit
- fCurrentMethod = (JMethod) fCurrentClass.methods.get(0);
- fCurrentMethodScope = x.staticInitializerScope;
+ currentMethod = (JMethod) currentClass.methods.get(0);
+ currentMethodScope = x.staticInitializerScope;
} else {
// init
- fCurrentMethod = (JMethod) fCurrentClass.methods.get(1);
- fCurrentMethodScope = x.initializerScope;
+ currentMethod = (JMethod) currentClass.methods.get(1);
+ currentMethodScope = x.initializerScope;
}
if (fieldDeclaration instanceof Initializer) {
- assert (fCurrentClass instanceof JClassType);
+ assert (currentClass instanceof JClassType);
processInitializer((Initializer) fieldDeclaration);
} else {
processField(fieldDeclaration);
@@ -241,14 +273,14 @@
}
}
- fCurrentMethodScope = null;
- fCurrentMethod = null;
+ currentMethodScope = null;
+ currentMethod = null;
if (x.methods != null) {
// Process methods
for (int i = 0, n = x.methods.length; i < n; ++i) {
if (x.methods[i].isConstructor()) {
- assert (fCurrentClass instanceof JClassType);
+ assert (currentClass instanceof JClassType);
processConstructor((ConstructorDeclaration) x.methods[i]);
} else if (x.methods[i].isClinit()) {
// nothing to do
@@ -258,8 +290,8 @@
}
}
- fCurrentClassScope = null;
- fCurrentClass = null;
+ currentClassScope = null;
+ currentClass = null;
}
/**
@@ -270,16 +302,16 @@
if (child == null) {
return null;
}
-
+
try {
- fParams[0] = child.getClass();
- Method method = getClass().getDeclaredMethod(name, fParams);
- fArgs[0] = child;
- return (JNode) method.invoke(this, fArgs);
+ params[0] = child.getClass();
+ Method method = getClass().getDeclaredMethod(name, params);
+ args[0] = child;
+ return (JNode) method.invoke(this, args);
} catch (SecurityException e) {
throw new InternalCompilerException("Error during dispatch", e);
} catch (NoSuchMethodException e) {
- String s = fParams[0].getName();
+ String s = params[0].getName();
throw new InternalCompilerException("Expecting: private void " + name
+ "(" + s.substring(s.lastIndexOf('.') + 1) + " x) { }", e);
} catch (IllegalArgumentException e) {
@@ -389,10 +421,10 @@
* initializer emulation method - run user code - return this
*/
void processConstructor(ConstructorDeclaration x) {
- JMethod ctor = (JMethod) fTypeMap.get(x.binding);
+ JMethod ctor = (JMethod) typeMap.get(x.binding);
- fCurrentMethod = ctor;
- fCurrentMethodScope = x.scope;
+ currentMethod = ctor;
+ currentMethodScope = x.scope;
JMethodCall call = null;
ExplicitConstructorCall ctorCall = x.constructorCall;
@@ -429,18 +461,18 @@
SyntheticArgumentBinding arg = nestedBinding.enclosingInstances[i];
JParameter param = (JParameter) paramIt.next();
if (arg.matchingField != null) {
- JField field = (JField) fTypeMap.get(arg);
+ JField field = (JField) typeMap.get(arg);
ctor.body.statements.add(program.createAssignmentStmt(
createVariableRef(field), createVariableRef(param)));
}
}
}
-
+
if (nestedBinding.outerLocalVariables != null) {
for (int i = 0; i < nestedBinding.outerLocalVariables.length; ++i) {
SyntheticArgumentBinding arg = nestedBinding.outerLocalVariables[i];
JParameter param = (JParameter) paramIt.next();
- JField field = (JField) fTypeMap.get(arg);
+ JField field = (JField) typeMap.get(arg);
ctor.body.statements.add(program.createAssignmentStmt(
createVariableRef(field), createVariableRef(param)));
}
@@ -477,8 +509,8 @@
}
}
- fCurrentMethodScope = null;
- fCurrentMethod = null;
+ currentMethodScope = null;
+ currentMethod = null;
// synthesize a return statement to emulate returning the new object
ctor.body.statements.add(new JReturnStatement(program, thisRef));
@@ -493,9 +525,9 @@
*/
return program.getLiteralNull();
}
- JClassType newType = (JClassType) fTypeMap.get(typeBinding);
+ JClassType newType = (JClassType) typeMap.get(typeBinding);
MethodBinding b = x.binding;
- JMethod ctor = (JMethod) fTypeMap.get(b);
+ JMethod ctor = (JMethod) typeMap.get(b);
JMethodCall call;
JClassType javaLangString = program.getTypeJavaLangString();
if (newType == javaLangString) {
@@ -540,7 +572,7 @@
if (nestedBinding.enclosingInstances != null) {
for (int i = 0; i < nestedBinding.enclosingInstances.length; ++i) {
SyntheticArgumentBinding arg = nestedBinding.enclosingInstances[i];
- JClassType syntheticThisType = (JClassType) fTypeMap.get(arg.type);
+ JClassType syntheticThisType = (JClassType) typeMap.get(arg.type);
call.args.add(createThisRef(syntheticThisType));
}
}
@@ -548,7 +580,7 @@
if (nestedBinding.outerLocalVariables != null) {
for (int i = 0; i < nestedBinding.outerLocalVariables.length; ++i) {
SyntheticArgumentBinding arg = nestedBinding.outerLocalVariables[i];
- JVariable variable = (JVariable) fTypeMap.get(arg.actualOuterLocalVariable);
+ JVariable variable = (JVariable) typeMap.get(arg.actualOuterLocalVariable);
call.args.add(createVariableRef(variable,
arg.actualOuterLocalVariable));
}
@@ -566,12 +598,12 @@
}
JExpression processExpression(AND_AND_Expression x) {
- JType type = (JType) fTypeMap.get(x.resolvedType);
+ JType type = (JType) typeMap.get(x.resolvedType);
return processBinaryOperation(JBinaryOperator.AND, type, x.left, x.right);
}
JExpression processExpression(ArrayAllocationExpression x) {
- JArrayType type = (JArrayType) fTypeMap.get(x.resolvedType);
+ JArrayType type = (JArrayType) typeMap.get(x.resolvedType);
JNewArray newArray = new JNewArray(program, type);
if (x.initializer != null) {
@@ -599,7 +631,7 @@
}
JExpression processExpression(ArrayInitializer x) {
- JArrayType type = (JArrayType) fTypeMap.get(x.resolvedType);
+ JArrayType type = (JArrayType) typeMap.get(x.resolvedType);
JNewArray newArray = new JNewArray(program, type);
newArray.initializers = new HolderList();
@@ -620,7 +652,7 @@
}
JExpression processExpression(Assignment x) {
- JType type = (JType) fTypeMap.get(x.resolvedType);
+ JType type = (JType) typeMap.get(x.resolvedType);
return processBinaryOperation(JBinaryOperator.ASG, type, x.lhs,
x.expression);
}
@@ -680,19 +712,19 @@
"Unexpected operator for BinaryExpression");
}
- JType type = (JType) fTypeMap.get(x.resolvedType);
+ JType type = (JType) typeMap.get(x.resolvedType);
return processBinaryOperation(op, type, x.left, x.right);
}
JExpression processExpression(CastExpression x) {
- JType type = (JType) fTypeMap.get(x.resolvedType);
+ JType type = (JType) typeMap.get(x.resolvedType);
JCastOperation cast = new JCastOperation(program, type,
dispProcessExpression(x.expression));
return cast;
}
JExpression processExpression(ClassLiteralAccess x) {
- JType type = (JType) fTypeMap.get(x.targetType);
+ JType type = (JType) typeMap.get(x.targetType);
return program.getLiteralClass(type);
}
@@ -738,12 +770,12 @@
"Unexpected operator for CompoundAssignment");
}
- JType type = (JType) fTypeMap.get(x.resolvedType);
+ JType type = (JType) typeMap.get(x.resolvedType);
return processBinaryOperation(op, type, x.lhs, x.expression);
}
JExpression processExpression(ConditionalExpression x) {
- JType type = (JType) fTypeMap.get(x.resolvedType);
+ JType type = (JType) typeMap.get(x.resolvedType);
JExpression ifTest = dispProcessExpression(x.condition);
JExpression thenExpr = dispProcessExpression(x.valueIfTrue);
JExpression elseExpr = dispProcessExpression(x.valueIfFalse);
@@ -766,7 +798,7 @@
"Unexpected operator for EqualExpression");
}
- JType type = (JType) fTypeMap.get(x.resolvedType);
+ JType type = (JType) typeMap.get(x.resolvedType);
return processBinaryOperation(op, type, x.left, x.right);
}
@@ -792,23 +824,23 @@
throw new InternalCompilerException("Error matching fieldBinding.");
}
} else {
- field = (JField) fTypeMap.get(fieldBinding);
+ field = (JField) typeMap.get(fieldBinding);
}
JExpression instance = dispProcessExpression(x.receiver);
JExpression fieldRef = new JFieldRef(program, instance, field,
- fCurrentClass);
+ currentClass);
return fieldRef;
}
JExpression processExpression(InstanceOfExpression x) {
JExpression expr = dispProcessExpression(x.expression);
- JReferenceType testType = (JReferenceType) fTypeMap.get(x.type.resolvedType);
+ JReferenceType testType = (JReferenceType) typeMap.get(x.type.resolvedType);
return new JInstanceOf(program, testType, expr);
}
JExpression processExpression(MessageSend x) {
- JType type = (JType) fTypeMap.get(x.resolvedType);
- JMethod method = (JMethod) fTypeMap.get(x.binding);
+ JType type = (JType) typeMap.get(x.resolvedType);
+ JMethod method = (JMethod) typeMap.get(x.binding);
assert (type == method.getType());
JExpression qualifier = dispProcessExpression(x.receiver);
@@ -848,7 +880,7 @@
}
JExpression processExpression(OR_OR_Expression x) {
- JType type = (JType) fTypeMap.get(x.resolvedType);
+ JType type = (JType) typeMap.get(x.resolvedType);
return processBinaryOperation(JBinaryOperator.OR, type, x.left, x.right);
}
@@ -907,9 +939,9 @@
if (x.enclosingInstance() == null) {
return processExpression((AllocationExpression) x);
}
-
+
MethodBinding b = x.binding;
- JMethod ctor = (JMethod) fTypeMap.get(b);
+ JMethod ctor = (JMethod) typeMap.get(b);
JClassType enclosingType = (JClassType) ctor.getEnclosingType();
JNewInstance newInstance = new JNewInstance(program, enclosingType);
JMethodCall call = new JMethodCall(program, newInstance, ctor);
@@ -923,7 +955,7 @@
if (nestedBinding.enclosingInstances != null) {
for (int i = 0; i < nestedBinding.enclosingInstances.length; ++i) {
SyntheticArgumentBinding arg = nestedBinding.enclosingInstances[i];
- JClassType syntheticThisType = (JClassType) fTypeMap.get(arg.type);
+ JClassType syntheticThisType = (JClassType) typeMap.get(arg.type);
call.args.add(createThisRef(syntheticThisType, qualifier));
}
}
@@ -931,7 +963,7 @@
if (nestedBinding.outerLocalVariables != null) {
for (int i = 0; i < nestedBinding.outerLocalVariables.length; ++i) {
SyntheticArgumentBinding arg = nestedBinding.outerLocalVariables[i];
- JVariable variable = (JVariable) fTypeMap.get(arg.actualOuterLocalVariable);
+ JVariable variable = (JVariable) typeMap.get(arg.actualOuterLocalVariable);
call.args.add(createVariableRef(variable,
arg.actualOuterLocalVariable));
}
@@ -950,7 +982,7 @@
JExpression processExpression(QualifiedNameReference x) {
Binding binding = x.binding;
- JNode node = fTypeMap.get(binding);
+ JNode node = typeMap.get(binding);
if (!(node instanceof JVariable)) {
return null;
}
@@ -975,9 +1007,9 @@
"Error matching fieldBinding.");
}
} else {
- field = (JField) fTypeMap.get(fieldBinding);
+ field = (JField) typeMap.get(fieldBinding);
}
- curRef = new JFieldRef(program, curRef, field, fCurrentClass);
+ curRef = new JFieldRef(program, curRef, field, currentClass);
}
}
@@ -985,7 +1017,7 @@
}
JExpression processExpression(QualifiedSuperReference x) {
- JClassType type = (JClassType) fTypeMap.get(x.resolvedType);
+ JClassType type = (JClassType) typeMap.get(x.resolvedType);
/*
* WEIRD: If a superref is qualified with the EXACT type of the innermost
* type (in other words, a needless qualifier), it must refer to that
@@ -996,7 +1028,7 @@
* the innermost type (even if the innermost type could be cast to a
* compatible type), so we must create a reference to some outer type.
*/
- if (type == fCurrentClass) {
+ if (type == currentClass) {
return createSuperRef(type);
} else {
return createQualifiedSuperRef(type);
@@ -1004,7 +1036,7 @@
}
JExpression processExpression(QualifiedThisReference x) {
- JClassType type = (JClassType) fTypeMap.get(x.resolvedType);
+ JClassType type = (JClassType) typeMap.get(x.resolvedType);
/*
* WEIRD: If a thisref is qualified with the EXACT type of the innermost
* type (in other words, a needless qualifier), it must refer to that
@@ -1015,7 +1047,7 @@
* innermost type (even if the innermost type could be cast to a
* compatible type), so we must create a reference to some outer type.
*/
- if (type == fCurrentClass) {
+ if (type == currentClass) {
return createThisRef(type);
} else {
return createQualifiedThisRef(type);
@@ -1024,7 +1056,7 @@
JExpression processExpression(SingleNameReference x) {
Binding binding = x.binding;
- Object target = fTypeMap.get(binding);
+ Object target = typeMap.get(binding);
if (!(target instanceof JVariable)) {
return null;
}
@@ -1040,7 +1072,7 @@
JField field = (JField) variable;
if (!field.isStatic()) {
JExpression instance = createThisRef(field.getEnclosingType());
- return new JFieldRef(program, instance, field, fCurrentClass);
+ return new JFieldRef(program, instance, field, currentClass);
}
}
@@ -1048,15 +1080,15 @@
}
JExpression processExpression(SuperReference x) {
- JClassType type = (JClassType) fTypeMap.get(x.resolvedType);
- assert (type == fCurrentClass.extnds);
+ JClassType type = (JClassType) typeMap.get(x.resolvedType);
+ assert (type == currentClass.extnds);
JExpression superRef = createSuperRef(type);
return superRef;
}
JExpression processExpression(ThisReference x) {
- JClassType type = (JClassType) fTypeMap.get(x.resolvedType);
- assert (type == fCurrentClass);
+ JClassType type = (JClassType) typeMap.get(x.resolvedType);
+ assert (type == currentClass);
JExpression thisRef = createThisRef(type);
return thisRef;
}
@@ -1093,7 +1125,7 @@
}
void processField(FieldDeclaration declaration) {
- JField field = (JField) fTypeMap.tryGet(declaration.binding);
+ JField field = (JField) typeMap.tryGet(declaration.binding);
if (field == null) {
/*
* When anonymous classes declare constant fields, the field declaration
@@ -1114,19 +1146,24 @@
createVariableRef(field), initializer);
// will either be init or clinit
- fCurrentMethod.body.statements.add(assignStmt);
+ currentMethod.body.statements.add(assignStmt);
}
}
void processInitializer(Initializer initializer) {
JBlock block = processStatement(initializer.block);
// will either be init or clinit
- fCurrentMethod.body.statements.add(block);
+ currentMethod.body.statements.add(block);
}
+ // // 5.0
+ // JStatement processStatement(ForeachStatement x) {
+ // return null;
+ // }
+
void processMethod(AbstractMethodDeclaration x) {
MethodBinding b = x.binding;
- JMethod method = (JMethod) fTypeMap.get(b);
+ JMethod method = (JMethod) typeMap.get(b);
if (b.isImplementing() || b.isOverriding()) {
tryFindUpRefs(method, b);
@@ -1137,8 +1174,8 @@
return;
}
- fCurrentMethod = method;
- fCurrentMethodScope = x.scope;
+ currentMethod = method;
+ currentMethodScope = x.scope;
if (x.statements != null) {
for (int i = 0, n = x.statements.length; i < n; ++i) {
@@ -1149,8 +1186,8 @@
}
}
}
- fCurrentMethodScope = null;
- fCurrentMethod = null;
+ currentMethodScope = null;
+ currentMethod = null;
}
void processNativeMethod(AbstractMethodDeclaration x,
@@ -1160,7 +1197,7 @@
if (func == null) {
return;
}
-
+
// resolve jsni refs
final List/* <JsNameRef> */nameRefs = new ArrayList/* <JsNameRef> */();
func.traverse(new JsAbstractVisitorWithAllVisits() {
@@ -1204,8 +1241,7 @@
* from JSNI with the literal value of the field.
*/
JField field = (JField) node;
- JsniFieldRef fieldRef = new JsniFieldRef(program, field,
- fCurrentClass);
+ JsniFieldRef fieldRef = new JsniFieldRef(program, field, currentClass);
nativeMethod.jsniFieldRefs.add(fieldRef);
} else {
JMethod method = (JMethod) node;
@@ -1239,7 +1275,7 @@
}
JStatement processStatement(BreakStatement x) {
- return new JBreakStatement(program, getOrCreateLabel(fCurrentMethod,
+ return new JBreakStatement(program, getOrCreateLabel(currentMethod,
x.label));
}
@@ -1249,7 +1285,7 @@
}
JStatement processStatement(ContinueStatement x) {
- return new JContinueStatement(program, getOrCreateLabel(fCurrentMethod,
+ return new JContinueStatement(program, getOrCreateLabel(currentMethod,
x.label));
}
@@ -1272,11 +1308,6 @@
return null;
}
- // // 5.0
- // JStatement processStatement(ForeachStatement x) {
- // return null;
- // }
-
JStatement processStatement(ForStatement x) {
// If false, just return the initializers
// for (init; false; inc) { x } => { init }
@@ -1325,25 +1356,25 @@
if (body == null) {
return null;
}
- return new JLabeledStatement(program, getOrCreateLabel(fCurrentMethod,
+ return new JLabeledStatement(program, getOrCreateLabel(currentMethod,
x.label), body);
}
JStatement processStatement(LocalDeclaration x) {
- JLocal local = (JLocal) fTypeMap.get(x.binding);
+ JLocal local = (JLocal) typeMap.get(x.binding);
JLocalRef localRef = new JLocalRef(program, local);
JExpression initializer = dispProcessExpression(x.initialization);
return new JLocalDeclarationStatement(program, localRef, initializer);
}
JStatement processStatement(ReturnStatement x) {
- if (fCurrentMethodScope.referenceContext instanceof ConstructorDeclaration) {
+ if (currentMethodScope.referenceContext instanceof ConstructorDeclaration) {
/*
* Special: constructors are implemented as instance methods that return
* their this object, so any embedded return statements have to be fixed
* up.
*/
- JClassType enclosingType = (JClassType) fCurrentMethod.getEnclosingType();
+ JClassType enclosingType = (JClassType) currentMethod.getEnclosingType();
assert (x.expression == null);
return new JReturnStatement(program, createThisRef(enclosingType));
} else {
@@ -1377,7 +1408,7 @@
List/* <JBlock> */catchBlocks = new ArrayList/* <JBlock> */();
if (x.catchBlocks != null) {
for (int i = 0, c = x.catchArguments.length; i < c; ++i) {
- JLocal local = (JLocal) fTypeMap.get(x.catchArguments[i].binding);
+ JLocal local = (JLocal) typeMap.get(x.catchArguments[i].binding);
catchArgs.add(createVariableRef(local));
}
for (int i = 0, c = x.catchBlocks.length; i < c; ++i) {
@@ -1423,14 +1454,14 @@
}
JMethodCall processSuperConstructorCall(ExplicitConstructorCall x) {
- JMethod ctor = (JMethod) fTypeMap.get(x.binding);
- JExpression trueQualifier = createThisRef(fCurrentClass);
+ JMethod ctor = (JMethod) typeMap.get(x.binding);
+ JExpression trueQualifier = createThisRef(currentClass);
JMethodCall call = new JMethodCall(program, trueQualifier, ctor);
// We have to find and pass through any synthetics our supertype needs
ReferenceBinding superClass = x.binding.declaringClass;
if (superClass instanceof NestedTypeBinding && !superClass.isStatic()) {
- NestedTypeBinding myBinding = (NestedTypeBinding) fCurrentClassScope.referenceType().binding;
+ NestedTypeBinding myBinding = (NestedTypeBinding) currentClassScope.referenceType().binding;
NestedTypeBinding superBinding = (NestedTypeBinding) superClass;
// enclosing types
@@ -1438,7 +1469,7 @@
JExpression qualifier = dispProcessExpression(x.qualification);
for (int j = 0; j < superBinding.enclosingInstances.length; ++j) {
SyntheticArgumentBinding arg = superBinding.enclosingInstances[j];
- JClassType classType = (JClassType) fTypeMap.get(arg.type);
+ JClassType classType = (JClassType) typeMap.get(arg.type);
if (qualifier == null) {
/*
* Got to be one of my params; it would be illegal to use a this
@@ -1449,7 +1480,7 @@
* check each one to see if any will make a suitable this ref.
*/
List/* <JExpression> */workList = new ArrayList/* <JExpression> */();
- Iterator/* <JParameter> */paramIt = fCurrentMethod.params.iterator();
+ Iterator/* <JParameter> */paramIt = currentMethod.params.iterator();
for (int i = 0; i < myBinding.enclosingInstances.length; ++i) {
workList.add(createVariableRef((JParameter) paramIt.next()));
}
@@ -1465,11 +1496,11 @@
for (int j = 0; j < superBinding.outerLocalVariables.length; ++j) {
SyntheticArgumentBinding arg = superBinding.outerLocalVariables[j];
// Got to be one of my params
- JType varType = (JType) fTypeMap.get(arg.type);
+ JType varType = (JType) typeMap.get(arg.type);
String varName = String.valueOf(arg.name);
JParameter param = null;
- for (int i = 0; i < fCurrentMethod.params.size(); ++i) {
- JParameter paramIt = (JParameter) fCurrentMethod.params.get(i);
+ for (int i = 0; i < currentMethod.params.size(); ++i) {
+ JParameter paramIt = (JParameter) currentMethod.params.get(i);
if (varType == paramIt.getType()
&& varName.equals(paramIt.getName())) {
param = paramIt;
@@ -1494,14 +1525,14 @@
}
JMethodCall processThisConstructorCall(ExplicitConstructorCall x) {
- JMethod ctor = (JMethod) fTypeMap.get(x.binding);
- JExpression trueQualifier = createThisRef(fCurrentClass);
+ JMethod ctor = (JMethod) typeMap.get(x.binding);
+ JExpression trueQualifier = createThisRef(currentClass);
JMethodCall call = new JMethodCall(program, trueQualifier, ctor);
// All synthetics must be passed through to the target ctor
ReferenceBinding declaringClass = x.binding.declaringClass;
if (declaringClass instanceof NestedTypeBinding) {
- Iterator/* <JParameter> */paramIt = fCurrentMethod.params.iterator();
+ Iterator/* <JParameter> */paramIt = currentMethod.params.iterator();
NestedTypeBinding nestedBinding = (NestedTypeBinding) declaringClass;
if (nestedBinding.enclosingInstances != null) {
for (int i = 0; i < nestedBinding.enclosingInstances.length; ++i) {
@@ -1530,7 +1561,7 @@
if (classType.fields.size() > 0) {
JField field = (JField) classType.fields.get(0);
if (field.getName().startsWith("this$")) {
- list.add(new JFieldRef(program, expr, field, fCurrentClass));
+ list.add(new JFieldRef(program, expr, field, currentClass));
}
}
}
@@ -1564,10 +1595,10 @@
* creating a naked JThisRef or you won't get the synthetic accesses right.
*/
private JExpression createQualifiedSuperRef(JClassType targetType) {
- assert (fCurrentClass instanceof JClassType);
- JExpression expr = program.getExpressionThisRef((JClassType) fCurrentClass);
+ assert (currentClass instanceof JClassType);
+ JExpression expr = program.getExpressionThisRef((JClassType) currentClass);
List/* <JExpression> */list = new ArrayList();
- addAllOuterThisRefsPlusSuperChain(list, expr, (JClassType) fCurrentClass);
+ addAllOuterThisRefsPlusSuperChain(list, expr, (JClassType) currentClass);
return createSuperRef(targetType, list);
}
@@ -1577,10 +1608,10 @@
* creating a naked JThisRef or you won't get the synthetic accesses right.
*/
private JExpression createQualifiedThisRef(JClassType targetType) {
- assert (fCurrentClass instanceof JClassType);
- JExpression expr = program.getExpressionThisRef((JClassType) fCurrentClass);
+ assert (currentClass instanceof JClassType);
+ JExpression expr = program.getExpressionThisRef((JClassType) currentClass);
List/* <JExpression> */list = new ArrayList();
- addAllOuterThisRefsPlusSuperChain(list, expr, (JClassType) fCurrentClass);
+ addAllOuterThisRefsPlusSuperChain(list, expr, (JClassType) currentClass);
return createThisRef(targetType, list);
}
@@ -1590,8 +1621,8 @@
* creating a naked JThisRef or you won't get the synthetic accesses right.
*/
private JExpression createSuperRef(JClassType targetType) {
- assert (fCurrentClass instanceof JClassType);
- JExpression expr = program.getExpressionThisRef((JClassType) fCurrentClass);
+ assert (currentClass instanceof JClassType);
+ JExpression expr = program.getExpressionThisRef((JClassType) currentClass);
List/* <JExpression> */list = new ArrayList();
list.add(expr);
return createSuperRef(targetType, list);
@@ -1604,7 +1635,7 @@
*/
private JExpression createSuperRef(JClassType targetType,
List/* <JExpression> */list) {
- assert (fCurrentClass instanceof JClassType);
+ assert (currentClass instanceof JClassType);
LinkedList/* <JExpression> */workList = new LinkedList/* <JExpression> */();
workList.addAll(list);
@@ -1627,9 +1658,9 @@
* JThisRef or you won't get the synthetic accesses right.
*/
private JExpression createThisRef(JReferenceType targetType) {
- assert (fCurrentClass instanceof JClassType);
+ assert (currentClass instanceof JClassType);
return createThisRef(targetType,
- program.getExpressionThisRef((JClassType) fCurrentClass));
+ program.getExpressionThisRef((JClassType) currentClass));
}
/**
@@ -1692,14 +1723,14 @@
private JVariableRef createVariableRef(JVariable variable) {
if (variable instanceof JLocal) {
JLocal local = (JLocal) variable;
- if (local.getEnclosingMethod() != fCurrentMethod) {
+ if (local.getEnclosingMethod() != currentMethod) {
throw new InternalCompilerException(
"LocalRef referencing local in a different method.");
}
return new JLocalRef(program, local);
} else if (variable instanceof JParameter) {
JParameter parameter = (JParameter) variable;
- if (parameter.getEnclosingMethod() != fCurrentMethod) {
+ if (parameter.getEnclosingMethod() != currentMethod) {
throw new InternalCompilerException(
"ParameterRef referencing param in a different method.");
}
@@ -1716,7 +1747,7 @@
"FieldRef referencing field in a different type.");
}
}
- return new JFieldRef(program, instance, field, fCurrentClass);
+ return new JFieldRef(program, instance, field, currentClass);
}
throw new InternalCompilerException("Unknown JVariable subclass.");
}
@@ -1749,10 +1780,10 @@
return null;
}
String sname = String.valueOf(name);
- Map/* <String, JLabel> */labelMap = (Map) fLabelMap.get(enclosingMethod);
+ Map/* <String, JLabel> */labelMap = (Map) this.labelMap.get(enclosingMethod);
if (labelMap == null) {
labelMap = new HashMap();
- fLabelMap.put(enclosingMethod, labelMap);
+ this.labelMap.put(enclosingMethod, labelMap);
}
JLabel jlabel = (JLabel) labelMap.get(sname);
if (jlabel == null) {
@@ -1831,9 +1862,9 @@
if (variable instanceof JLocal || variable instanceof JParameter) {
LocalVariableBinding localBinding = (LocalVariableBinding) binding;
- if (localBinding.declaringScope.methodScope() != fCurrentMethodScope) {
+ if (localBinding.declaringScope.methodScope() != currentMethodScope) {
variable = null;
- VariableBinding[] vars = fCurrentMethodScope.getEmulationPath(localBinding);
+ VariableBinding[] vars = currentMethodScope.getEmulationPath(localBinding);
if (vars == null) {
return null;
}
@@ -1842,10 +1873,10 @@
// See if there's an available parameter
if (varBinding instanceof SyntheticArgumentBinding) {
- JType type = (JType) fTypeMap.get(varBinding.type);
+ JType type = (JType) typeMap.get(varBinding.type);
String name = String.valueOf(varBinding.name);
- for (int i = 0; i < fCurrentMethod.params.size(); ++i) {
- JParameter param = (JParameter) fCurrentMethod.params.get(i);
+ for (int i = 0; i < currentMethod.params.size(); ++i) {
+ JParameter param = (JParameter) currentMethod.params.get(i);
if (type == param.getType() && name.equals(param.getName())) {
variable = param;
break;
@@ -1855,7 +1886,7 @@
// just use the field
if (variable == null) {
- variable = (JField) fTypeMap.get(varBinding);
+ variable = (JField) typeMap.get(varBinding);
}
// now we have an updated variable that we can create our ref from
@@ -1904,7 +1935,7 @@
if (result != null) {
if (areParametersIdentical(binding, result)) {
- JMethod upRef = (JMethod) fTypeMap.get(result);
+ JMethod upRef = (JMethod) typeMap.get(result);
if (!method.overrides.contains(upRef)) {
method.overrides.add(upRef);
}
@@ -1925,16 +1956,6 @@
}
}
}
-
- private Object[] fArgs = new Object[1];
- private JReferenceType fCurrentClass;
- private ClassScope fCurrentClassScope;
- private JMethod fCurrentMethod;
- private MethodScope fCurrentMethodScope;
- private final Map/* <JMethod, Map<String, JLabel>> */fLabelMap = new IdentityHashMap();
- private Class[] fParams = new Class[1];
- private final TypeMap fTypeMap;
- private final JProgram program;
}
/**
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 b2baf00..88ee143 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
@@ -1,4 +1,18 @@
-// Copyright 2006 Google Inc. All Rights Reserved.
+/*
+ * Copyright 2006 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.impl;
import com.google.gwt.dev.jjs.ast.HasEnclosingType;
@@ -126,12 +140,14 @@
import java.util.Stack;
/**
- * Creates a JavaScript AST from a <code>JProgram</code> node.
+ * Creates a JavaScript AST from a <code>JProgram</code> node.
*/
public class GenerateJavaScriptAST {
private class CreateNamesAndScopesVisitor extends JVisitor {
+ private final Stack/* <JsScope> */scopeStack = new Stack();
+
// @Override
public void endVisit(JClassType x) {
pop();
@@ -142,7 +158,7 @@
String name = x.getName();
String mangleName = mangleName(x);
if (x.isStatic()) {
- names.put(x, fRootScope.createUniqueObfuscatableName(mangleName, name));
+ names.put(x, rootScope.createUniqueObfuscatableName(mangleName, name));
} else {
names.put(x, peek().createUniqueObfuscatableName(mangleName, name));
}
@@ -183,16 +199,16 @@
public void endVisit(JProgram x) {
// visit special things that may have been culled
JField field = x.getSpecialField("Object.typeId");
- names.put(field, fObjectScope.getOrCreateObfuscatableName(
- mangleName(field), field.getName()));
+ names.put(field, objectScope.getOrCreateObfuscatableName(
+ mangleName(field), field.getName()));
field = x.getSpecialField("Object.typeName");
names.put(field,
- fObjectScope.getOrCreateObfuscatableName(mangleName(field)));
+ objectScope.getOrCreateObfuscatableName(mangleName(field)));
field = x.getSpecialField("Cast.typeIdArray");
- names.put(field, fRootScope.getOrCreateObfuscatableName(
- mangleName(field), field.getName()));
+ names.put(field, rootScope.getOrCreateObfuscatableName(mangleName(field),
+ field.getName()));
/*
* put the null method and field into fObjectScope since they can be
@@ -200,17 +216,17 @@
*/
JMethod nullMethod = x.getNullMethod();
polymorphicNames.put(nullMethod,
- fObjectScope.createUniqueObfuscatableName(nullMethod.getName()));
+ objectScope.createUniqueObfuscatableName(nullMethod.getName()));
JField nullField = x.getNullField();
- JsName nullFieldName = fObjectScope.createUniqueObfuscatableName(nullField.getName());
+ JsName nullFieldName = objectScope.createUniqueObfuscatableName(nullField.getName());
polymorphicNames.put(nullField, nullFieldName);
names.put(nullField, nullFieldName);
/*
* put nullMethod in the global scope, too; it's the replacer for clinits
*/
- fNullMethodName = fRootScope.createUniqueObfuscatableName(nullMethod.getName());
- names.put(nullMethod, fNullMethodName);
+ nullMethodName = rootScope.createUniqueObfuscatableName(nullMethod.getName());
+ names.put(nullMethod, nullMethodName);
}
// @Override
@@ -228,12 +244,12 @@
}
// My seed function name
- names.put(x, fRootScope.createUniqueObfuscatableName(getNameString(x),
- x.getShortName()));
+ names.put(x, rootScope.createUniqueObfuscatableName(getNameString(x),
+ x.getShortName()));
// My class scope
if (x.extnds == null) {
- myScope = fObjectScope;
+ myScope = objectScope;
} else {
JsScope parentScope = (JsScope) classScopes.get(x.extnds);
// Run my superclass first!
@@ -247,8 +263,8 @@
* of its subclasses; this ensures that interface method names trump all
* (except Object methods names)
*/
- if (parentScope == fObjectScope) {
- parentScope = fInterfaceScope;
+ if (parentScope == objectScope) {
+ parentScope = interfaceScope;
}
myScope = new JsScope(parentScope);
myScope.setDescription("class " + x.getShortName());
@@ -262,7 +278,7 @@
// @Override
public boolean visit(JInterfaceType x) {
// interfaces have no name at run time
- push(fInterfaceScope);
+ push(interfaceScope);
return true;
}
@@ -274,8 +290,8 @@
if (!x.isStatic()) {
if (getPolyName(x) == null) {
String mangleName = mangleNameForPoly(x);
- JsName polyName = fInterfaceScope.getOrCreateObfuscatableName(
- mangleName, name);
+ JsName polyName = interfaceScope.getOrCreateObfuscatableName(
+ mangleName, name);
polymorphicNames.put(x, polyName);
}
}
@@ -289,15 +305,15 @@
// my global name
JsName globalName;
if (x.getEnclosingType() == null) {
- globalName = fRootScope.createUniqueObfuscatableName(name);
+ globalName = rootScope.createUniqueObfuscatableName(name);
} else {
String mangleName = mangleNameForGlobal(x);
- globalName = fRootScope.createUniqueObfuscatableName(mangleName, name);
+ globalName = rootScope.createUniqueObfuscatableName(mangleName, name);
}
names.put(x, globalName);
// create my peer JsFunction
- JsFunction jsFunction = new JsFunction(fRootScope, globalName);
+ JsFunction jsFunction = new JsFunction(rootScope, globalName);
methodMap.put(x, jsFunction);
push(jsFunction.getScope());
@@ -311,15 +327,15 @@
if (!x.isStatic()) {
if (getPolyName(x) == null) {
String mangleName = mangleNameForPoly(x);
- JsName polyName = fInterfaceScope.getOrCreateObfuscatableName(
- mangleName, name);
+ JsName polyName = interfaceScope.getOrCreateObfuscatableName(
+ mangleName, name);
polymorphicNames.put(x, polyName);
}
}
// set my global name now that we have a name allocator
String fnName = mangleNameForGlobal(x);
- JsName globalName = fRootScope.createUniqueObfuscatableName(fnName, name);
+ JsName globalName = rootScope.createUniqueObfuscatableName(fnName, name);
x.getFunc().setName(globalName);
names.put(x, globalName);
@@ -337,12 +353,22 @@
private void push(JsScope scope) {
scopeStack.push(scope);
}
-
- private final Stack/* <JsScope> */scopeStack = new Stack();
}
-
+
private class GenerateJavaScriptVisitor extends JVisitor {
+ private final Set/* <JClassType> */alreadyRan = new HashSet/* <JClassType> */();
+
+ private JMethod currentMethod = null;
+
+ private final JsName globalTemp = rootScope.getOrCreateUnobfuscatableName("_");
+
+ private final JsName prototype = objectScope.getOrCreateUnobfuscatableName("prototype");
+
+ private final JsName window = rootScope.getOrCreateUnobfuscatableName("window");
+
+ private final Stack/* <JsNode> */nodeStack = new Stack/* <JsNode> */();
+
// @Override
public void endVisit(JAbsentArrayDimension x, Mutator m) {
throw new InternalCompilerException("Should not get here.");
@@ -377,12 +403,12 @@
* when Object.toString() == 'some string'.
*/
if (myOp == JsBinaryOperator.EQ
- && x.getLhs().getType() instanceof JReferenceType
- && x.getRhs().getType() instanceof JReferenceType) {
+ && x.getLhs().getType() instanceof JReferenceType
+ && x.getRhs().getType() instanceof JReferenceType) {
myOp = JsBinaryOperator.REF_EQ;
} else if (myOp == JsBinaryOperator.NEQ
- && x.getLhs().getType() instanceof JReferenceType
- && x.getRhs().getType() instanceof JReferenceType) {
+ && x.getLhs().getType() instanceof JReferenceType
+ && x.getRhs().getType() instanceof JReferenceType) {
myOp = JsBinaryOperator.REF_NEQ;
}
JsBinaryOperation binOp = new JsBinaryOperation(myOp, lhs, rhs);
@@ -444,7 +470,7 @@
public void endVisit(JClassLiteral x, Mutator m) {
// My seed function name
String nameString = x.refType.getJavahSignatureName() + "_classlit";
- JsName classLit = fRootScope.getOrCreateObfuscatableName(nameString);
+ JsName classLit = rootScope.getOrCreateObfuscatableName(nameString);
classLits.put(x.refType, classLit);
push(classLit.makeRef());
}
@@ -456,11 +482,11 @@
// @Override
public void endVisit(JClassType x) {
- if (fAlreadyRan.contains(x)) {
+ if (alreadyRan.contains(x)) {
return;
}
- fAlreadyRan.add(x);
+ alreadyRan.add(x);
List/* <JsFunction> */jsFuncs = popList(x.methods.size()); // methods
List/* <JsStatement> */jsFields = popList(x.fields.size()); // fields
@@ -486,13 +512,13 @@
JsName seedFuncName = getName(x);
// seed function
- JsFunction seedFunc = new JsFunction(fRootScope, seedFuncName);
+ JsFunction seedFunc = new JsFunction(rootScope, seedFuncName);
JsBlock body = new JsBlock();
seedFunc.setBody(body);
globalStmts.add(seedFunc.makeStmt());
// prototype
- JsNameRef lhs = fPrototype.makeRef();
+ JsNameRef lhs = prototype.makeRef();
lhs.setQualifier(seedFuncName.makeRef());
JsExpression rhs;
if (x.extnds != null) {
@@ -503,17 +529,16 @@
rhs = new JsObjectLiteral();
}
JsExpression protoAsg = createAssignment(lhs, rhs);
- JsExpression tmpAsg = createAssignment(fGlobalTemp.makeRef(),
- protoAsg);
+ JsExpression tmpAsg = createAssignment(globalTemp.makeRef(), protoAsg);
globalStmts.add(tmpAsg.makeStmt());
} else {
/*
* MAGIC: java.lang.String is implemented as a JavaScript String
* primitive with a modified prototype.
*/
- JsNameRef rhs = fPrototype.makeRef();
- rhs.setQualifier(fRootScope.getOrCreateUnobfuscatableName("String").makeRef());
- JsExpression tmpAsg = createAssignment(fGlobalTemp.makeRef(), rhs);
+ JsNameRef rhs = prototype.makeRef();
+ rhs.setQualifier(rootScope.getOrCreateUnobfuscatableName("String").makeRef());
+ JsExpression tmpAsg = createAssignment(globalTemp.makeRef(), rhs);
globalStmts.add(tmpAsg.makeStmt());
}
@@ -522,7 +547,7 @@
JMethod method = (JMethod) x.methods.get(i);
if (!method.isStatic() && !method.isAbstract()) {
JsNameRef lhs = getPolyName(method).makeRef();
- lhs.setQualifier(fGlobalTemp.makeRef());
+ lhs.setQualifier(globalTemp.makeRef());
JsNameRef rhs = getName(method).makeRef();
JsExpression asg = createAssignment(lhs, rhs);
globalStmts.add(new JsExprStmt(asg));
@@ -536,9 +561,9 @@
// _.toString = function(){return this.java_lang_Object_toString();}
// lhs
- JsName lhsName = fRootScope.getOrCreateUnobfuscatableName("toString");
+ JsName lhsName = rootScope.getOrCreateUnobfuscatableName("toString");
JsNameRef lhs = lhsName.makeRef();
- lhs.setQualifier(fGlobalTemp.makeRef());
+ lhs.setQualifier(globalTemp.makeRef());
// rhs
JsInvocation call = new JsInvocation();
@@ -546,7 +571,7 @@
toStringRef.setQualifier(new JsThisRef());
call.setQualifier(toStringRef);
JsReturn jsReturn = new JsReturn(call);
- JsFunction rhs = new JsFunction(fRootScope);
+ JsFunction rhs = new JsFunction(rootScope);
JsBlock body = new JsBlock();
body.getStatements().add(jsReturn);
rhs.setBody(body);
@@ -561,7 +586,7 @@
{
JField typeIdField = program.getSpecialField("Object.typeName");
JsNameRef lhs = getName(typeIdField).makeRef();
- lhs.setQualifier(fGlobalTemp.makeRef());
+ lhs.setQualifier(globalTemp.makeRef());
JsStringLiteral rhs = jsProgram.getStringLiteral(x.getName());
JsExpression asg = createAssignment(lhs, rhs);
globalStmts.add(new JsExprStmt(asg));
@@ -572,7 +597,7 @@
if (typeId >= 0) {
JField typeIdField = program.getSpecialField("Object.typeId");
JsNameRef fieldRef = getName(typeIdField).makeRef();
- fieldRef.setQualifier(fGlobalTemp.makeRef());
+ fieldRef.setQualifier(globalTemp.makeRef());
JsIntegralLiteral typeIdLit = jsProgram.getIntegralLiteral(BigInteger.valueOf(typeId));
JsExpression asg = createAssignment(fieldRef, typeIdLit);
globalStmts.add(new JsExprStmt(asg));
@@ -645,10 +670,10 @@
} else {
x.getType().getDefaultValue().traverse(this);
}
-
+
JsNameRef fieldRef = getName(x).makeRef();
if (!x.isStatic()) {
- fieldRef.setQualifier(fGlobalTemp.makeRef());
+ fieldRef.setQualifier(globalTemp.makeRef());
}
JsExpression asg = createAssignment(fieldRef, (JsExpression) pop());
push(new JsExprStmt(asg));
@@ -663,13 +688,13 @@
if (x.getInstance() != null) {
qualifier = (JsExpression) pop();
}
-
+
JField field = x.getField();
JsInvocation jsInvocation = maybeCreateClinitCall(field);
if (jsInvocation != null) {
qualifier = createCommaExpression(qualifier, jsInvocation);
}
-
+
nameRef.setQualifier(qualifier); // instance
push(nameRef);
}
@@ -705,7 +730,7 @@
if (x.getTestExpr() != null) {
jsFor.setCondition((JsExpression) pop());
}
-
+
// initializers
JsExpression initExpr = null;
List/* <JsExprStmt> */initStmts = popList(x.getInitializers().size());
@@ -803,7 +828,7 @@
JsNameRef localRef = (JsNameRef) pop(); // localRef
JsBinaryOperation binOp = new JsBinaryOperation(JsBinaryOperator.ASG,
- localRef, initializer);
+ localRef, initializer);
push(binOp.makeStmt());
}
@@ -855,7 +880,7 @@
}
push(jsFunc);
- fCurrentMethod = null;
+ currentMethod = null;
}
// @Override
@@ -922,13 +947,13 @@
// @Override
public void endVisit(JPostfixOperation x, Mutator m) {
push(new JsPostfixOperation(JavaToJsOperatorMap.get(x.op),
- (JsExpression) pop())); // arg
+ (JsExpression) pop())); // arg
}
// @Override
public void endVisit(JPrefixOperation x, Mutator m) {
push(new JsPrefixOperation(JavaToJsOperatorMap.get(x.op),
- (JsExpression) pop())); // arg
+ (JsExpression) pop())); // arg
}
// @Override
@@ -960,9 +985,9 @@
* }
* </pre>
*/
- JsFunction gwtOnLoad = new JsFunction(fRootScope);
+ JsFunction gwtOnLoad = new JsFunction(rootScope);
globalStmts.add(gwtOnLoad.makeStmt());
- gwtOnLoad.setName(fRootScope.getOrCreateUnobfuscatableName("gwtOnLoad"));
+ gwtOnLoad.setName(rootScope.getOrCreateUnobfuscatableName("gwtOnLoad"));
JsBlock body = new JsBlock();
gwtOnLoad.setBody(body);
JsScope fnScope = gwtOnLoad.getScope();
@@ -1071,7 +1096,7 @@
if (jsName == null) {
// this can occur when JSNI references an instance method on a
// type that was never actually instantiated.
- jsName = fNullMethodName;
+ jsName = nullMethodName;
}
x.setName(jsName);
}
@@ -1086,7 +1111,7 @@
}
push(jsFunc);
- fCurrentMethod = null;
+ currentMethod = null;
}
// @Override
@@ -1162,13 +1187,13 @@
// @Override
public boolean visit(JClassType x) {
- if (fAlreadyRan.contains(x)) {
+ if (alreadyRan.contains(x)) {
return false;
}
// force supertype to generate code first, this is required for prototype
// chaining to work properly
- if (x.extnds != null && !fAlreadyRan.contains(x)) {
+ if (x.extnds != null && !alreadyRan.contains(x)) {
x.extnds.traverse(this);
}
@@ -1177,7 +1202,7 @@
// @Override
public boolean visit(JMethod x) {
- fCurrentMethod = x;
+ currentMethod = x;
return true;
}
@@ -1185,10 +1210,10 @@
public boolean visit(JProgram x) {
// handle null method
// return 'window' so that fields can be referenced
- JsReturn jsReturn = new JsReturn(fWindow.makeRef());
+ JsReturn jsReturn = new JsReturn(window.makeRef());
JsBlock body = new JsBlock();
body.getStatements().add(jsReturn);
- JsFunction nullFunc = new JsFunction(fRootScope, fNullMethodName);
+ JsFunction nullFunc = new JsFunction(rootScope, nullMethodName);
nullFunc.setBody(body);
jsProgram.getGlobalBlock().getStatements().add(nullFunc.makeStmt());
return true;
@@ -1196,7 +1221,7 @@
// @Override
public boolean visit(JsniMethod x) {
- fCurrentMethod = x;
+ currentMethod = x;
return false;
}
@@ -1253,11 +1278,11 @@
private void handleClinit(JsFunction clinitFunc) {
// self-assign to the null func immediately (to prevent reentrancy)
JsExpression asg = createAssignment(clinitFunc.getName().makeRef(),
- fNullMethodName.makeRef());
+ nullMethodName.makeRef());
clinitFunc.getBody().getStatements().add(0, asg.makeStmt());
// return 'window' so that fields can be referenced
- JsReturn jsReturn = new JsReturn(fWindow.makeRef());
+ JsReturn jsReturn = new JsReturn(window.makeRef());
clinitFunc.getBody().getStatements().add(jsReturn);
}
@@ -1265,13 +1290,13 @@
if (!x.isStatic()) {
return null;
}
-
+
JReferenceType enclosingType = x.getEnclosingType();
if (!typeOracle.hasClinit(enclosingType)) {
return null;
}
// don't need to clinit on my own static fields
- if (enclosingType == fCurrentMethod.getEnclosingType()) {
+ if (enclosingType == currentMethod.getEnclosingType()) {
return null;
}
JMethod clinitMethod = (JMethod) enclosingType.methods.get(0);
@@ -1284,17 +1309,17 @@
if (!x.isStatic()) {
return null;
}
-
+
JReferenceType enclosingType = x.getEnclosingType();
if (!typeOracle.hasClinit(enclosingType)) {
return null;
}
-
+
// avoid recursion sickness
if (x == enclosingType.methods.get(0)) {
return null;
}
-
+
if (program.isStaticImpl(x)) {
return null;
}
@@ -1314,7 +1339,7 @@
while (count > 0) {
array[--count] = pop();
}
-
+
List/* <T> */list = new ArrayList/* <T> */();
for (int i = 0; i < array.length; i++) {
JsNode item = array[i];
@@ -1330,7 +1355,7 @@
while (count > 0) {
array[--count] = pop();
}
-
+
for (int i = 0; i < array.length; i++) {
JsNode item = array[i];
if (item != null) {
@@ -1342,32 +1367,12 @@
private void push(JsNode node) {
nodeStack.push(node);
}
-
- private final Set/* <JClassType> */fAlreadyRan = new HashSet/* <JClassType> */();
-
- private JMethod fCurrentMethod = null;
-
- private final JsName fGlobalTemp = fRootScope.getOrCreateUnobfuscatableName("_");
-
- private final JsName fPrototype = fObjectScope.getOrCreateUnobfuscatableName("prototype");
-
- private final JsName fWindow = fRootScope.getOrCreateUnobfuscatableName("window");
-
- private final Stack/* <JsNode> */nodeStack = new Stack/* <JsNode> */();
}
-
+
private static class JavaToJsOperatorMap {
private static final Map/* <JBinaryOperator, JsBinaryOperator> */bOpMap = new IdentityHashMap();
private static final Map/* <JUnaryOperator, JsUnaryOperator> */uOpMap = new IdentityHashMap();
- public static JsBinaryOperator get(JBinaryOperator op) {
- return (JsBinaryOperator) bOpMap.get(op);
- }
-
- public static JsUnaryOperator get(JUnaryOperator op) {
- return (JsUnaryOperator) uOpMap.get(op);
- }
-
static {
bOpMap.put(JBinaryOperator.MUL, JsBinaryOperator.MUL);
bOpMap.put(JBinaryOperator.DIV, JsBinaryOperator.DIV);
@@ -1407,23 +1412,52 @@
uOpMap.put(JUnaryOperator.NOT, JsUnaryOperator.NOT);
uOpMap.put(JUnaryOperator.BIT_NOT, JsUnaryOperator.BIT_NOT);
}
+
+ public static JsBinaryOperator get(JBinaryOperator op) {
+ return (JsBinaryOperator) bOpMap.get(op);
+ }
+
+ public static JsUnaryOperator get(JUnaryOperator op) {
+ return (JsUnaryOperator) uOpMap.get(op);
+ }
}
public static void exec(JProgram program, JsProgram jsProgram) {
GenerateJavaScriptAST generateJavaScriptAST = new GenerateJavaScriptAST(
- program, jsProgram);
+ program, jsProgram);
generateJavaScriptAST.execImpl();
}
+ private final Map/* <JType, JsName> */classLits = new IdentityHashMap();
+
+ private final Map/* <JClassType, JsScope> */classScopes = new IdentityHashMap();
+
+ private final JsScope interfaceScope;
+
+ private JsName nullMethodName;
+
+ private final JsScope objectScope;
+
+ private final JsScope rootScope;
+
+ private final JsProgram jsProgram;
+
+ private final Map/* <JMethod, JsFunction> */methodMap = new IdentityHashMap();
+
+ private final Map/* <HasName, JsName> */names = new IdentityHashMap();
+ private final Map/* <JMethod, JsName> */polymorphicNames = new IdentityHashMap();
+ private final JProgram program;
+ private final JTypeOracle typeOracle;
+
private GenerateJavaScriptAST(JProgram program, JsProgram jsProgram) {
this.program = program;
typeOracle = program.typeOracle;
this.jsProgram = jsProgram;
- fRootScope = jsProgram.getScope();
- fObjectScope = new JsScope(fRootScope);
- fObjectScope.setDescription("Object scope");
- fInterfaceScope = new JsScope(fObjectScope);
- fInterfaceScope.setDescription("Interfaces");
+ rootScope = jsProgram.getScope();
+ objectScope = new JsScope(rootScope);
+ objectScope.setDescription("Object scope");
+ interfaceScope = new JsScope(objectScope);
+ interfaceScope.setDescription("Interfaces");
}
String getNameString(HasName hasName) {
@@ -1438,7 +1472,7 @@
String mangleNameForGlobal(JMethod x) {
String s = getNameString(x.getEnclosingType()) + '_' + getNameString(x)
- + "__";
+ + "__";
for (int i = 0; i < x.getOriginalParamTypes().size(); ++i) {
JType type = (JType) x.getOriginalParamTypes().get(i);
s += type.getJavahSignatureName();
@@ -1470,17 +1504,4 @@
return (JsName) polymorphicNames.get(x);
}
- private final Map/* <JType, JsName> */classLits = new IdentityHashMap();
- private final Map/* <JClassType, JsScope> */classScopes = new IdentityHashMap();
- private final JsScope fInterfaceScope;
- private JsName fNullMethodName;
- private final JsScope fObjectScope;
- private final JsScope fRootScope;
- private final JsProgram jsProgram;
- private final Map/* <JMethod, JsFunction> */methodMap = new IdentityHashMap();
- private final Map/* <HasName, JsName> */names = new IdentityHashMap();
- private final Map/* <JMethod, JsName> */polymorphicNames = new IdentityHashMap();
- private final JProgram program;
- private final JTypeOracle typeOracle;
-
}
diff --git a/dev/core/src/com/google/gwt/dev/jjs/impl/InternalCompilerException.java b/dev/core/src/com/google/gwt/dev/jjs/impl/InternalCompilerException.java
index 90fc366..d7bd231 100644
--- a/dev/core/src/com/google/gwt/dev/jjs/impl/InternalCompilerException.java
+++ b/dev/core/src/com/google/gwt/dev/jjs/impl/InternalCompilerException.java
@@ -1,4 +1,18 @@
-// Copyright 2006 Google Inc. All Rights Reserved.
+/*
+ * Copyright 2006 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.impl;
public class InternalCompilerException extends RuntimeException {
diff --git a/dev/core/src/com/google/gwt/dev/jjs/impl/JavaPrecedenceVisitor.java b/dev/core/src/com/google/gwt/dev/jjs/impl/JavaPrecedenceVisitor.java
index ea6ba8e..ad86e58 100644
--- a/dev/core/src/com/google/gwt/dev/jjs/impl/JavaPrecedenceVisitor.java
+++ b/dev/core/src/com/google/gwt/dev/jjs/impl/JavaPrecedenceVisitor.java
@@ -1,4 +1,18 @@
-// Copyright 2006 Google Inc. All Rights Reserved.
+/*
+ * Copyright 2006 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.impl;
import com.google.gwt.dev.jjs.ast.JAbsentArrayDimension;
diff --git a/dev/core/src/com/google/gwt/dev/jjs/impl/JavaScriptObjectCaster.java b/dev/core/src/com/google/gwt/dev/jjs/impl/JavaScriptObjectCaster.java
index 0ba542b..f34e52c 100644
--- a/dev/core/src/com/google/gwt/dev/jjs/impl/JavaScriptObjectCaster.java
+++ b/dev/core/src/com/google/gwt/dev/jjs/impl/JavaScriptObjectCaster.java
@@ -1,4 +1,18 @@
-// Copyright 2006 Google Inc. All Rights Reserved.
+/*
+ * Copyright 2006 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.impl;
import com.google.gwt.dev.jjs.ast.JBinaryOperation;
@@ -25,35 +39,9 @@
private class AssignmentVisitor extends JVisitor {
private final ChangeList changeList = new ChangeList(
- "Synthesize casts from JavaScriptObjects to trigger wrapping.");
+ "Synthesize casts from JavaScriptObjects to trigger wrapping.");
- public ChangeList getChangeList() {
- return changeList;
- }
-
- private void checkAndReplaceJso(Mutator arg, JType targetType) {
- JType argType = arg.get().getType();
- if (argType == targetType) {
- return;
- }
-
- if (!(targetType instanceof JReferenceType)) {
- return;
- }
-
- if (!program.isJavaScriptObject(argType)) {
- return;
- }
- JCastOperation cast = new JCastOperation(program, targetType, program
- .getLiteralNull());
- ChangeList myChangeList = new ChangeList("Synthesize a cast from '"
- + argType + "' to '" + targetType + "'.");
- myChangeList.replaceExpression(cast.expr, arg);
- myChangeList.replaceExpression(arg, cast);
- changeList.add(myChangeList);
- }
-
- private JMethod fCurrentMethod;
+ private JMethod currentMethod;
// @Override
public void endVisit(JBinaryOperation x, Mutator m) {
@@ -78,7 +66,7 @@
// @Override
public void endVisit(JMethod x) {
- fCurrentMethod = null;
+ currentMethod = null;
}
// @Override
@@ -96,15 +84,51 @@
// @Override
public void endVisit(JReturnStatement x) {
if (x.getExpression() != null) {
- checkAndReplaceJso(x.expr, fCurrentMethod.getType());
+ checkAndReplaceJso(x.expr, currentMethod.getType());
}
}
+ public ChangeList getChangeList() {
+ return changeList;
+ }
+
// @Override
public boolean visit(JMethod x) {
- fCurrentMethod = x;
+ currentMethod = x;
return true;
}
+
+ private void checkAndReplaceJso(Mutator arg, JType targetType) {
+ JType argType = arg.get().getType();
+ if (argType == targetType) {
+ return;
+ }
+
+ if (!(targetType instanceof JReferenceType)) {
+ return;
+ }
+
+ if (!program.isJavaScriptObject(argType)) {
+ return;
+ }
+ JCastOperation cast = new JCastOperation(program, targetType,
+ program.getLiteralNull());
+ ChangeList myChangeList = new ChangeList("Synthesize a cast from '"
+ + argType + "' to '" + targetType + "'.");
+ myChangeList.replaceExpression(cast.expr, arg);
+ myChangeList.replaceExpression(arg, cast);
+ changeList.add(myChangeList);
+ }
+ }
+
+ public static void exec(JProgram program) {
+ new JavaScriptObjectCaster(program).execImpl();
+ }
+
+ private final JProgram program;
+
+ private JavaScriptObjectCaster(JProgram program) {
+ this.program = program;
}
private void execImpl() {
@@ -118,14 +142,4 @@
}
}
- private final JProgram program;
-
- private JavaScriptObjectCaster(JProgram program) {
- this.program = program;
- }
-
- public static void exec(JProgram program) {
- new JavaScriptObjectCaster(program).execImpl();
- }
-
}
diff --git a/dev/core/src/com/google/gwt/dev/jjs/impl/MakeCallsStatic.java b/dev/core/src/com/google/gwt/dev/jjs/impl/MakeCallsStatic.java
index 83aa78d..40c8071 100644
--- a/dev/core/src/com/google/gwt/dev/jjs/impl/MakeCallsStatic.java
+++ b/dev/core/src/com/google/gwt/dev/jjs/impl/MakeCallsStatic.java
@@ -1,4 +1,18 @@
-// Copyright 2006 Google Inc. All Rights Reserved.
+/*
+ * Copyright 2006 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.impl;
import com.google.gwt.dev.jjs.ast.JClassType;
@@ -37,8 +51,6 @@
*/
public class MakeCallsStatic {
- private final JProgram program;
-
/**
* For any instance methods that are called in a non-polymorphic manner, move
* the contents of the method to a static method, and have the instance method
@@ -48,11 +60,7 @@
private class CreateStaticMethodVisitor extends JVisitor {
private final ChangeList changeList = new ChangeList(
- "Create static impls for instance methods");
-
- public ChangeList getChangeList() {
- return changeList;
- }
+ "Create static impls for instance methods");
// @Override
public void endVisit(JMethodCall x, Mutator m) {
@@ -92,36 +100,37 @@
* its enclosing class, which will break iteration.
*/
JMethod newMethod = new JMethod(program, newName, enclosingType,
- oldReturnType, false, true, true, oldMethod.isPrivate());
+ oldReturnType, false, true, true, oldMethod.isPrivate());
// Setup all params and locals; map from the old method to the new method
- JParameter thisParam = program.createParameter("this$static"
- .toCharArray(), enclosingType, true, newMethod);
+ JParameter thisParam = program.createParameter(
+ "this$static".toCharArray(), enclosingType, true, newMethod);
Map/* <JVariable, JVariable> */varMap = new IdentityHashMap();
for (int i = 0; i < oldMethod.params.size(); ++i) {
JParameter oldVar = (JParameter) oldMethod.params.get(i);
- JParameter newVar = program.createParameter(oldVar.getName()
- .toCharArray(), oldVar.getType(), oldVar.isFinal(), newMethod);
+ JParameter newVar = program.createParameter(
+ oldVar.getName().toCharArray(), oldVar.getType(), oldVar.isFinal(),
+ newMethod);
varMap.put(oldVar, newVar);
}
-
+
newMethod.freezeParamTypes();
for (int i = 0; i < oldMethod.locals.size(); ++i) {
JLocal oldVar = (JLocal) oldMethod.locals.get(i);
JLocal newVar = program.createLocal(oldVar.getName().toCharArray(),
- oldVar.getType(), oldVar.isFinal(), newMethod);
+ oldVar.getType(), oldVar.isFinal(), newMethod);
varMap.put(oldVar, newVar);
}
ChangeList myChangeList = new ChangeList("Create a new static method '"
- + newMethod + "' for instance method '" + oldMethod + "'");
+ + newMethod + "' for instance method '" + oldMethod + "'");
myChangeList.addMethod(newMethod);
program.putStaticImpl(oldMethod, newMethod);
// rewrite the method body to update all thisRefs to instance refs
ChangeList subChangeList = new ChangeList(
- "Update thisrefs as paramrefs; update paramrefs and localrefs to target this method.");
+ "Update thisrefs as paramrefs; update paramrefs and localrefs to target this method.");
RewriteMethodBody rewriter = new RewriteMethodBody(thisParam, varMap,
- subChangeList);
+ subChangeList);
oldMethod.traverse(rewriter);
myChangeList.add(subChangeList);
@@ -145,6 +154,56 @@
myChangeList.addStatement(statement, oldMethod.body);
changeList.add(myChangeList);
}
+
+ public ChangeList getChangeList() {
+ return changeList;
+ }
+ }
+
+ /**
+ * For any method calls to methods we updated during
+ * CreateStaticMethodVisitor, go and rewrite the call sites to call the static
+ * method instead.
+ */
+ private class RewriteCallSites extends JVisitor {
+
+ private final ChangeList changeList = new ChangeList(
+ "Rewrite calls to final instance methods as calls to static impl methods.");
+
+ /*
+ * In cases where callers are directly referencing (effectively) final
+ * instance methods, rewrite the call site to reference the newly-generated
+ * static method instead.
+ */
+ // @Override
+ public void endVisit(JMethodCall x, Mutator m) {
+ JMethod oldMethod = x.getTarget();
+ JMethod newMethod = program.getStaticImpl(oldMethod);
+ if (newMethod == null || x.canBePolymorphic()) {
+ return;
+ }
+
+ ChangeList changes = new ChangeList("Replace '" + x
+ + "' with a static call");
+
+ // Update the call site
+ JMethodCall newCall = new JMethodCall(program, null, newMethod);
+ changes.replaceExpression(m, newCall);
+
+ // The qualifier becomes the first arg
+ changes.addExpression(x.instance, newCall.args);
+ // Copy the rest of the args
+ for (int i = 0; i < x.args.size(); ++i) {
+ Mutator arg = x.args.getMutator(i);
+ changes.addExpression(arg, newCall.args);
+ }
+
+ changeList.add(changes);
+ }
+
+ public ChangeList getChangeList() {
+ return changeList;
+ }
}
/**
@@ -185,50 +244,14 @@
}
}
- /**
- * For any method calls to methods we updated during
- * CreateStaticMethodVisitor, go and rewrite the call sites to call the static
- * method instead.
- */
- private class RewriteCallSites extends JVisitor {
+ public static boolean exec(JProgram program) {
+ return new MakeCallsStatic(program).execImpl();
+ }
- private final ChangeList changeList = new ChangeList(
- "Rewrite calls to final instance methods as calls to static impl methods.");
+ private final JProgram program;
- public ChangeList getChangeList() {
- return changeList;
- }
-
- /*
- * In cases where callers are directly referencing (effectively) final
- * instance methods, rewrite the call site to reference the newly-generated
- * static method instead.
- */
- // @Override
- public void endVisit(JMethodCall x, Mutator m) {
- JMethod oldMethod = x.getTarget();
- JMethod newMethod = program.getStaticImpl(oldMethod);
- if (newMethod == null || x.canBePolymorphic()) {
- return;
- }
-
- ChangeList changes = new ChangeList("Replace '" + x
- + "' with a static call");
-
- // Update the call site
- JMethodCall newCall = new JMethodCall(program, null, newMethod);
- changes.replaceExpression(m, newCall);
-
- // The qualifier becomes the first arg
- changes.addExpression(x.instance, newCall.args);
- // Copy the rest of the args
- for (int i = 0; i < x.args.size(); ++i) {
- Mutator arg = x.args.getMutator(i);
- changes.addExpression(arg, newCall.args);
- }
-
- changeList.add(changes);
- }
+ private MakeCallsStatic(JProgram program) {
+ this.program = program;
}
private boolean execImpl() {
@@ -253,12 +276,4 @@
return true;
}
- private MakeCallsStatic(JProgram program) {
- this.program = program;
- }
-
- public static boolean exec(JProgram program) {
- return new MakeCallsStatic(program).execImpl();
- }
-
}
diff --git a/dev/core/src/com/google/gwt/dev/jjs/impl/MethodAndClassFinalizer.java b/dev/core/src/com/google/gwt/dev/jjs/impl/MethodAndClassFinalizer.java
index 5820330..a2ded14 100644
--- a/dev/core/src/com/google/gwt/dev/jjs/impl/MethodAndClassFinalizer.java
+++ b/dev/core/src/com/google/gwt/dev/jjs/impl/MethodAndClassFinalizer.java
@@ -1,4 +1,18 @@
-// Copyright 2006 Google Inc. All Rights Reserved.
+/*
+ * Copyright 2006 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.impl;
import com.google.gwt.dev.jjs.ast.JClassType;
@@ -20,60 +34,6 @@
*/
public class MethodAndClassFinalizer {
- private final Set/* <JClassType> */isSubclassed = new HashSet/* <JClassType> */();
- private final Set/* <JMethod> */isOverriden = new HashSet/* <JMethod> */();
-
- /**
- * Find all methods and classes that ARE overriden/subclassed.
- */
- private class MarkVisitor extends JVisitor {
-
- // @Override
- public boolean visit(JClassType x) {
- if (x.extnds != null) {
- isSubclassed.add(x.extnds);
- }
-
- for (int i = 0; i < x.methods.size(); ++i) {
- JMethod method = (JMethod) x.methods.get(i);
- method.traverse(this);
- }
- return false;
- }
-
- // @Override
- public boolean visit(JInterfaceType x) {
- for (int i = 0; i < x.methods.size(); ++i) {
- JMethod method = (JMethod) x.methods.get(i);
- method.traverse(this);
- }
- return false;
- }
-
- // @Override
- public boolean visit(JMethod x) {
- for (int i = 0; i < x.overrides.size(); ++i) {
- JMethod it = (JMethod) x.overrides.get(i);
- isOverriden.add(it);
- }
- return false;
- }
-
- // @Override
- public boolean visit(JsniMethod x) {
- return visit((JMethod) x);
- }
-
- // @Override
- public boolean visit(JProgram x) {
- for (int i = 0; i < x.getDeclaredTypes().size(); ++i) {
- JReferenceType type = (JReferenceType) x.getDeclaredTypes().get(i);
- type.traverse(this);
- }
- return false;
- }
- }
-
/**
* Any method and classes that weren't marked during MarkVisitor can be set
* final.
@@ -87,7 +47,7 @@
private class FinalizeVisitor extends JVisitor {
private final ChangeList changeList = new ChangeList(
- "Finalize effectively final methods and types.");
+ "Finalize effectively final methods and types.");
public ChangeList getChangeList() {
return changeList;
@@ -127,6 +87,67 @@
return visit((JMethod) x);
}
}
+ /**
+ * Find all methods and classes that ARE overriden/subclassed.
+ */
+ private class MarkVisitor extends JVisitor {
+
+ // @Override
+ public boolean visit(JClassType x) {
+ if (x.extnds != null) {
+ isSubclassed.add(x.extnds);
+ }
+
+ for (int i = 0; i < x.methods.size(); ++i) {
+ JMethod method = (JMethod) x.methods.get(i);
+ method.traverse(this);
+ }
+ return false;
+ }
+
+ // @Override
+ public boolean visit(JInterfaceType x) {
+ for (int i = 0; i < x.methods.size(); ++i) {
+ JMethod method = (JMethod) x.methods.get(i);
+ method.traverse(this);
+ }
+ return false;
+ }
+
+ // @Override
+ public boolean visit(JMethod x) {
+ for (int i = 0; i < x.overrides.size(); ++i) {
+ JMethod it = (JMethod) x.overrides.get(i);
+ isOverriden.add(it);
+ }
+ return false;
+ }
+
+ // @Override
+ public boolean visit(JProgram x) {
+ for (int i = 0; i < x.getDeclaredTypes().size(); ++i) {
+ JReferenceType type = (JReferenceType) x.getDeclaredTypes().get(i);
+ type.traverse(this);
+ }
+ return false;
+ }
+
+ // @Override
+ public boolean visit(JsniMethod x) {
+ return visit((JMethod) x);
+ }
+ }
+
+ public static boolean exec(JProgram program) {
+ return new MethodAndClassFinalizer().execImpl(program);
+ }
+
+ private final Set/* <JClassType> */isSubclassed = new HashSet/* <JClassType> */();
+
+ private final Set/* <JMethod> */isOverriden = new HashSet/* <JMethod> */();
+
+ private MethodAndClassFinalizer() {
+ }
private boolean execImpl(JProgram program) {
MarkVisitor marker = new MarkVisitor();
@@ -141,11 +162,4 @@
return true;
}
- private MethodAndClassFinalizer() {
- }
-
- public static boolean exec(JProgram program) {
- return new MethodAndClassFinalizer().execImpl(program);
- }
-
}
diff --git a/dev/core/src/com/google/gwt/dev/jjs/impl/MethodCallTightener.java b/dev/core/src/com/google/gwt/dev/jjs/impl/MethodCallTightener.java
index 721c41c..9269611 100644
--- a/dev/core/src/com/google/gwt/dev/jjs/impl/MethodCallTightener.java
+++ b/dev/core/src/com/google/gwt/dev/jjs/impl/MethodCallTightener.java
@@ -1,4 +1,18 @@
-// Copyright 2006 Google Inc. All Rights Reserved.
+/*
+ * Copyright 2006 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.impl;
import com.google.gwt.dev.jjs.ast.JArrayType;
@@ -25,19 +39,13 @@
*/
public class MethodCallTightener {
- private final JProgram program;
-
/**
- * Updates polymorphic method calls to tighter bindings based on the type of
+ * Updates polymorphic method calls to tighter bindings based on the type of
* the qualifier.
*/
public class MethodCallTighteningVisitor extends JVisitor {
private final ChangeList changeList = new ChangeList(
- "Update polymorphic method calls to tighter bindings based on the type of the qualifier.");
-
- public ChangeList getChangeList() {
- return changeList;
- }
+ "Update polymorphic method calls to tighter bindings based on the type of the qualifier.");
// @Override
public void endVisit(JMethodCall x, Mutator m) {
@@ -53,7 +61,7 @@
JReferenceType enclosingType = method.getEnclosingType();
if (instanceType == enclosingType
- || instanceType instanceof JInterfaceType) {
+ || instanceType instanceof JInterfaceType) {
// This method call is as tight as it can be for the type of the
// qualifier
return;
@@ -78,7 +86,7 @@
JMethod foundMethod = null;
JClassType type;
outer : for (type = (JClassType) instanceType; type != null
- && type != enclosingType; type = type.extnds) {
+ && type != enclosingType; type = type.extnds) {
for (int i = 0; i < type.methods.size(); ++i) {
JMethod methodIt = (JMethod) type.methods.get(i);
if (JProgram.methodsDoMatch(method, methodIt)) {
@@ -93,8 +101,8 @@
}
ChangeList changes = new ChangeList("Replace call '" + x + "' to type '"
- + enclosingType + "' with a call to type '"
- + foundMethod.getEnclosingType() + "'");
+ + enclosingType + "' with a call to type '"
+ + foundMethod.getEnclosingType() + "'");
// Update the call site
JMethodCall call = new JMethodCall(program, null, foundMethod);
@@ -114,8 +122,18 @@
return;
}
+
+ public ChangeList getChangeList() {
+ return changeList;
+ }
}
+ public static boolean exec(JProgram program) {
+ return new MethodCallTightener(program).execImpl();
+ }
+
+ private final JProgram program;
+
private MethodCallTightener(JProgram program) {
this.program = program;
}
@@ -127,13 +145,9 @@
if (changes.empty()) {
return false;
}
-
+
changes.apply();
return true;
}
- public static boolean exec(JProgram program) {
- return new MethodCallTightener(program).execImpl();
- }
-
}
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 a33ddef..78d45ec 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
@@ -1,4 +1,18 @@
-// Copyright 2006 Google Inc. All Rights Reserved.
+/*
+ * Copyright 2006 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.impl;
import com.google.gwt.dev.jjs.ast.Holder;
@@ -31,32 +45,53 @@
*/
public class MethodInliner {
- private final JProgram program;
- private JMethod fCurrentMethod;
-
/**
- * Method inlining visitor.
+ * Flattens <code>JMultiExpressions</code> where possible.
*/
- public class InliningVisitor extends JVisitor {
- private final ChangeList changeList = new ChangeList("Inline methods.");
+ public class FlattenMultiVisitor extends JVisitor {
+ private final ChangeList changeList = new ChangeList(
+ "Flatten multis where possible.");
+
+ // @Override
+ public void endVisit(JMultiExpression x, Mutator m) {
+ HolderList exprs = x.exprs;
+
+ // do all adds FIRST or the indices will be wrong
+ for (int i = 0; i < exprs.size(); ++i) {
+ JExpression expr = exprs.getExpr(i);
+ if (expr instanceof JMultiExpression) {
+ JMultiExpression sub = (JMultiExpression) expr;
+ changeList.addAll(sub.exprs, i, exprs);
+ }
+ }
+
+ // now remove the old multi
+ for (int i = 0; i < exprs.size(); ++i) {
+ JExpression expr = exprs.getExpr(i);
+ if (expr instanceof JMultiExpression) {
+ changeList.removeNode(exprs.getMutator(i), exprs);
+ }
+ }
+ }
public ChangeList getChangeList() {
return changeList;
}
-
+ }
+ /**
+ * Method inlining visitor.
+ */
+ public class InliningVisitor extends JVisitor {
/**
* Resets with each new visitor, which is good since things that couldn't be
* inlined before might become inlineable.
*/
Set/* <JMethod> */cannotInline = new HashSet/* <JMethod> */();
- public boolean visit(JMethod x) {
- fCurrentMethod = x;
- return true;
- }
+ private final ChangeList changeList = new ChangeList("Inline methods.");
public void endVisit(JMethod x) {
- fCurrentMethod = null;
+ currentMethod = null;
}
// @Override
@@ -80,7 +115,7 @@
JStatement stmt = (JStatement) stmts.get(0);
if (stmt instanceof JReturnStatement) {
didInline = tryInlineSimpleMethodCall(x, m, method,
- (JReturnStatement) stmt);
+ (JReturnStatement) stmt);
}
}
@@ -89,13 +124,100 @@
}
}
+ public ChangeList getChangeList() {
+ return changeList;
+ }
+
+ public boolean visit(JMethod x) {
+ currentMethod = x;
+ return true;
+ }
+
+ /**
+ * This complicated method has a simple purpose: see if the expression part
+ * of a return statement is inlinable. The trickiness comes from the fact
+ * that we'd like to be able to do this recursively in certain cases. For
+ * example, the accessor method
+ *
+ * <pre>
+ * $getFoo(this$static) {
+ * return this$static.foo
+ * }
+ * </pre>
+ *
+ * should be inlinable, but we have to first examine the field reference and
+ * then recursively determine that the qualifier is inlinable.
+ */
+ private Mutator canInlineResultExpression(JExpression targetReturnExpr,
+ List/* <JParameter> */params, HolderList args, int[] magicArg,
+ ChangeList changes) {
+ if (targetReturnExpr instanceof JLiteral) {
+ // just reference the same JLiteral
+ /*
+ * hackish: pretend there is an arg that is returned which comes after
+ * all the real args; this allows the evaluation order check below to
+ * succeed
+ */
+ magicArg[0] = args.size();
+ return new Holder(targetReturnExpr);
+ } else if (targetReturnExpr instanceof JParameterRef) {
+ // translate the param ref into the appropriate arg
+ int i = params.indexOf(((JParameterRef) targetReturnExpr).getTarget());
+ assert (i >= 0);
+ magicArg[0] = i;
+ return args.getMutator(i);
+ } else if (targetReturnExpr instanceof JFieldRef) {
+ JFieldRef oldFieldRef = (JFieldRef) targetReturnExpr;
+ JField field = oldFieldRef.getField();
+ JExpression instance = oldFieldRef.getInstance();
+ JFieldRef newFieldRef = new JFieldRef(program, null, field,
+ currentMethod.getEnclosingType());
+ if (instance != null) {
+ // If an instance field, we have to be able to inline the qualifier
+ Mutator instanceMutator = canInlineResultExpression(instance, params,
+ args, magicArg, changes);
+ if (instanceMutator == null) {
+ return null;
+ }
+ changes.replaceExpression(newFieldRef.instance, instanceMutator);
+ }
+ return new Holder(newFieldRef);
+ } else {
+ /*
+ * For now, only inline REALLY trivial stuff since we have no way of
+ * cloning arbitrary expressions.
+ */
+ return null;
+ }
+ }
+
+ private boolean inlineEmptyMethodCall(JMethodCall x, Mutator m,
+ JMethod method) {
+ ChangeList changes = new ChangeList("Inline a call to empty method '"
+ + method + "'");
+ JMultiExpression multi = new JMultiExpression(program);
+ JExpression instance = x.getInstance();
+ if (instance != null && instance.hasSideEffects()) {
+ changes.addExpression(x.instance, multi.exprs);
+ }
+ for (int i = 0, c = x.args.size(); i < c; ++i) {
+ if (x.args.getExpr(i).hasSideEffects()) {
+ changes.addExpression(x.args.getMutator(i), multi.exprs);
+ }
+ }
+
+ changes.replaceExpression(m, multi);
+ changeList.add(changes);
+ return true;
+ }
+
private boolean tryInlineSimpleMethodCall(JMethodCall x, Mutator m,
JMethod method, JReturnStatement returnStmt) {
List/* <JParameter> */params = method.params;
HolderList args = x.args;
ChangeList changes = new ChangeList("Inline a call to simple method '"
- + method + "'");
+ + method + "'");
// the expression returned by the inlined method, if any
Mutator resultExpression;
@@ -104,7 +226,7 @@
JExpression targetReturnExpr = returnStmt.getExpression();
resultExpression = canInlineResultExpression(targetReturnExpr, params,
- args, magicArg, changes);
+ args, magicArg, changes);
if (resultExpression == null) {
return false; // cannot inline
@@ -148,118 +270,6 @@
changeList.add(changes);
return true;
}
-
- /**
- * This complicated method has a simple purpose: see if the expression part
- * of a return statement is inlinable. The trickiness comes from the fact
- * that we'd like to be able to do this recursively in certain cases. For
- * example, the accessor method
- *
- * <pre>
- * $getFoo(this$static) {
- * return this$static.foo
- * }
- * </pre>
- *
- * should be inlinable, but we have to first examine the field reference and
- * then recursively determine that the qualifier is inlinable.
- */
- private Mutator canInlineResultExpression(JExpression targetReturnExpr,
- List/* <JParameter> */params, HolderList args, int[] magicArg,
- ChangeList changes) {
- if (targetReturnExpr instanceof JLiteral) {
- // just reference the same JLiteral
- /*
- * hackish: pretend there is an arg that is returned which comes after
- * all the real args; this allows the evaluation order check below to
- * succeed
- */
- magicArg[0] = args.size();
- return new Holder(targetReturnExpr);
- } else if (targetReturnExpr instanceof JParameterRef) {
- // translate the param ref into the appropriate arg
- int i = params.indexOf(((JParameterRef) targetReturnExpr).getTarget());
- assert (i >= 0);
- magicArg[0] = i;
- return args.getMutator(i);
- } else if (targetReturnExpr instanceof JFieldRef) {
- JFieldRef oldFieldRef = (JFieldRef) targetReturnExpr;
- JField field = oldFieldRef.getField();
- JExpression instance = oldFieldRef.getInstance();
- JFieldRef newFieldRef = new JFieldRef(program, null, field,
- fCurrentMethod.getEnclosingType());
- if (instance != null) {
- // If an instance field, we have to be able to inline the qualifier
- Mutator instanceMutator = canInlineResultExpression(instance, params,
- args, magicArg, changes);
- if (instanceMutator == null) {
- return null;
- }
- changes.replaceExpression(newFieldRef.instance, instanceMutator);
- }
- return new Holder(newFieldRef);
- } else {
- /*
- * For now, only inline REALLY trivial stuff since we have no way of
- * cloning arbitrary expressions.
- */
- return null;
- }
- }
-
- private boolean inlineEmptyMethodCall(JMethodCall x, Mutator m,
- JMethod method) {
- ChangeList changes = new ChangeList("Inline a call to empty method '"
- + method + "'");
- JMultiExpression multi = new JMultiExpression(program);
- JExpression instance = x.getInstance();
- if (instance != null && instance.hasSideEffects()) {
- changes.addExpression(x.instance, multi.exprs);
- }
- for (int i = 0, c = x.args.size(); i < c; ++i) {
- if (x.args.getExpr(i).hasSideEffects()) {
- changes.addExpression(x.args.getMutator(i), multi.exprs);
- }
- }
-
- changes.replaceExpression(m, multi);
- changeList.add(changes);
- return true;
- }
- }
-
- /**
- * Flattens <code>JMultiExpressions</code> where possible.
- */
- public class FlattenMultiVisitor extends JVisitor {
- private final ChangeList changeList = new ChangeList(
- "Flatten multis where possible.");
-
- public ChangeList getChangeList() {
- return changeList;
- }
-
- // @Override
- public void endVisit(JMultiExpression x, Mutator m) {
- HolderList exprs = x.exprs;
-
- // do all adds FIRST or the indices will be wrong
- for (int i = 0; i < exprs.size(); ++i) {
- JExpression expr = exprs.getExpr(i);
- if (expr instanceof JMultiExpression) {
- JMultiExpression sub = (JMultiExpression) expr;
- changeList.addAll(sub.exprs, i, exprs);
- }
- }
-
- // now remove the old multi
- for (int i = 0; i < exprs.size(); ++i) {
- JExpression expr = exprs.getExpr(i);
- if (expr instanceof JMultiExpression) {
- changeList.removeNode(exprs.getMutator(i), exprs);
- }
- }
- }
}
/**
@@ -267,11 +277,7 @@
*/
public class ReduceMultiVisitor extends JVisitor {
private final ChangeList changeList = new ChangeList(
- "Reduce multis where possible.");
-
- public ChangeList getChangeList() {
- return changeList;
- }
+ "Reduce multis where possible.");
// @Override
public void endVisit(JMultiExpression x, Mutator m) {
@@ -281,7 +287,7 @@
if (c == 0) {
return;
}
-
+
int countSideEffectsBeforeLast = 0;
for (int i = 0; i < c - 1; ++i) {
JExpression expr = exprs.getExpr(i);
@@ -302,6 +308,10 @@
}
}
+ public ChangeList getChangeList() {
+ return changeList;
+ }
+
// @Override
public boolean visit(JBlock x) {
for (int i = 0; i < x.statements.size(); ++i) {
@@ -319,6 +329,14 @@
}
}
+ public static boolean exec(JProgram program) {
+ return new MethodInliner(program).execImpl();
+ }
+
+ private final JProgram program;
+
+ private JMethod currentMethod;
+
private MethodInliner(JProgram program) {
this.program = program;
}
@@ -358,8 +376,4 @@
return madeChanges;
}
- public static boolean exec(JProgram program) {
- return new MethodInliner(program).execImpl();
- }
-
}
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 d436652..288fe33 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
@@ -1,4 +1,18 @@
-// Copyright 2006 Google Inc. All Rights Reserved.
+/*
+ * Copyright 2006 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.impl;
import com.google.gwt.dev.jjs.ast.JAbsentArrayDimension;
@@ -52,14 +66,90 @@
*/
public class Pruner {
- private final JProgram program;
- private final boolean noSpecialTypes;
+ /**
+ * Remove any unreferenced classes and interfaces from JProgram. Remove any
+ * unreferenced methods and fields from their containing classes.
+ */
+ private class PruneVisitor extends JVisitor {
- private final Set/* <JReferenceType> */referencedTypes = new HashSet/* <JReferenceType> */();
- private final Set/* <JNode> */referencedNonTypes = new HashSet/* <JNode> */();
+ private final ChangeList changeList = new ChangeList(
+ "Prune unreferenced methods, fields, and types.");
- private JMethod fStringValueOfChar = null;
+ public ChangeList getChangeList() {
+ return changeList;
+ }
+ // @Override
+ public boolean visit(JClassType type) {
+
+ assert (referencedTypes.contains(type));
+ boolean isInstantiated = program.typeOracle.isInstantiatedType(type);
+
+ for (int i = 0; i < type.fields.size(); ++i) {
+ JField it = (JField) type.fields.get(i);
+ if (!referencedNonTypes.contains(it)
+ || pruneViaNoninstantiability(isInstantiated, it)) {
+ changeList.removeField(it);
+ }
+ }
+ for (int i = 0; i < type.methods.size(); ++i) {
+ JMethod it = (JMethod) type.methods.get(i);
+ if (!referencedNonTypes.contains(it)
+ || pruneViaNoninstantiability(isInstantiated, it)) {
+ changeList.removeMethod(it);
+ }
+ }
+
+ return false;
+ }
+
+ // @Override
+ public boolean visit(JInterfaceType type) {
+ boolean isReferenced = referencedTypes.contains(type);
+ boolean isInstantiated = program.typeOracle.isInstantiatedType(type);
+
+ for (int i = 0; i < type.fields.size(); ++i) {
+ JField it = (JField) type.fields.get(i);
+ // all interface fields are static and final
+ if (!isReferenced || !referencedNonTypes.contains(it)) {
+ changeList.removeField(it);
+ }
+ }
+ // start at index 1; never prune clinit directly out of the interface
+ for (int i = 1; i < type.methods.size(); ++i) {
+ JMethod it = (JMethod) type.methods.get(i);
+ // all other interface methods are instance and abstract
+ if (!isInstantiated || !referencedNonTypes.contains(it)) {
+ changeList.removeMethod(it);
+ }
+ }
+
+ return false;
+ }
+
+ // @Override
+ public boolean visit(JProgram program) {
+ for (int i = 0; i < program.getDeclaredTypes().size(); ++i) {
+ JReferenceType type = (JReferenceType) program.getDeclaredTypes().get(i);
+ if (referencedTypes.contains(type)
+ || program.typeOracle.isInstantiatedType(type)) {
+ type.traverse(this);
+ } else {
+ changeList.removeType(type);
+ }
+ }
+ return false;
+ }
+
+ private boolean pruneViaNoninstantiability(boolean isInstantiated, JField it) {
+ return (!isInstantiated && !it.isStatic());
+ }
+
+ private boolean pruneViaNoninstantiability(boolean isInstantiated,
+ JMethod it) {
+ return (!isInstantiated && (!it.isStatic() || program.isStaticImpl(it)));
+ }
+ }
/**
* Marks as "referenced" any types, methods, and fields that are reachable.
* Also marks as "instantiable" any the classes and interfaces that can
@@ -73,118 +163,6 @@
program.typeOracle.setInstantiatedTypes(instantiatedTypes);
}
- /**
- * Subclasses of JavaScriptObject are never instantiated directly. They are
- * created "magically" when a JSNI method passes a reference to an existing
- * JS object into Java code. The point at which a subclass of JSO is passed
- * into Java code constitutes "instantiation". We must identify these points
- * and trigger a rescue and instantiation of that particular JSO subclass.
- *
- * @param type The type of the value passing from Java to JavaScript.
- * @see com.google.gwt.core.client.JavaScriptObject
- */
- private void maybeRescueJavaScriptObjectPassingIntoJava(JType type) {
- if (type instanceof JReferenceType) {
- JReferenceType refType = (JReferenceType) type;
- if (program.typeOracle.canTriviallyCast(refType,
- program.getSpecialJavaScriptObject())) {
- rescue(refType, true, true);
- }
- }
- }
-
- private boolean rescue(JReferenceType type, boolean isReferenced,
- boolean isInstantiated) {
- if (type == null) {
- return false;
- }
-
- boolean doVisit = false;
- if (isInstantiated && !instantiatedTypes.contains(type)) {
- instantiatedTypes.add(type);
- doVisit = true;
- }
-
- if (isReferenced && !referencedTypes.contains(type)) {
- referencedTypes.add(type);
- doVisit = true;
- }
-
- if (doVisit) {
- type.traverse(this);
- }
-
- return doVisit;
- }
-
- private boolean rescue(JMethod method) {
- if (method == null) {
- return false;
- }
-
- if (!referencedNonTypes.contains(method)) {
- referencedNonTypes.add(method);
- method.traverse(this);
- if (method instanceof JsniMethod) {
- /*
- * SPECIAL: returning from this method passes a value from JavaScript
- * into Java.
- */
- maybeRescueJavaScriptObjectPassingIntoJava(method.getType());
- }
- return true;
- }
- return false;
- }
-
- private boolean rescue(JField field) {
- if (field == null) {
- return false;
- }
-
- if (!referencedNonTypes.contains(field)) {
- referencedNonTypes.add(field);
- return true;
- }
- return true;
- }
-
- /**
- * Handle special rescues needed implicitly to support concat.
- */
- private void rescueByConcat(JType type) {
- JClassType stringType = program.getTypeJavaLangString();
- JPrimitiveType charType = program.getTypePrimitiveChar();
- if (type instanceof JReferenceType && type != stringType) {
- /*
- * Any reference types (except String, which works by default) that take
- * part in a concat must rescue java.lang.Object.toString().
- */
- JMethod toStringMethod = program.getSpecialMethod("Object.toString");
- rescue(toStringMethod);
- } else if (type == charType) {
- /*
- * Characters must rescue String.valueOf(char)
- */
- if (fStringValueOfChar == null) {
- for (int i = 0; i < stringType.methods.size(); ++i) {
- JMethod meth = (JMethod) stringType.methods.get(i);
- if (meth.getName().equals("valueOf")) {
- List params = meth.getOriginalParamTypes();
- if (params.size() == 1) {
- if (params.get(0) == charType) {
- fStringValueOfChar = meth;
- break;
- }
- }
- }
- }
- assert (fStringValueOfChar != null);
- }
- rescue(fStringValueOfChar);
- }
- }
-
// @Override
public void endVisit(JBinaryOperation x, Mutator m) {
// special string concat handling
@@ -348,13 +326,6 @@
}
// @Override
- public boolean visit(JStringLiteral literal, Mutator mutator) {
- // rescue and instantiate java.lang.String
- rescue(program.getTypeJavaLangString(), true, true);
- return true;
- }
-
- // @Override
public boolean visit(JsniFieldRef x) {
/*
* SPECIAL: this could be an assignment that passes a value from
@@ -382,6 +353,125 @@
// JsniMethodRef rescues as JMethodCall
return visit(/* (JMethodCall) */x, null);
}
+
+ // @Override
+ public boolean visit(JStringLiteral literal, Mutator mutator) {
+ // rescue and instantiate java.lang.String
+ rescue(program.getTypeJavaLangString(), true, true);
+ return true;
+ }
+
+ /**
+ * Subclasses of JavaScriptObject are never instantiated directly. They are
+ * created "magically" when a JSNI method passes a reference to an existing
+ * JS object into Java code. The point at which a subclass of JSO is passed
+ * into Java code constitutes "instantiation". We must identify these points
+ * and trigger a rescue and instantiation of that particular JSO subclass.
+ *
+ * @param type The type of the value passing from Java to JavaScript.
+ * @see com.google.gwt.core.client.JavaScriptObject
+ */
+ private void maybeRescueJavaScriptObjectPassingIntoJava(JType type) {
+ if (type instanceof JReferenceType) {
+ JReferenceType refType = (JReferenceType) type;
+ if (program.typeOracle.canTriviallyCast(refType,
+ program.getSpecialJavaScriptObject())) {
+ rescue(refType, true, true);
+ }
+ }
+ }
+
+ private boolean rescue(JField field) {
+ if (field == null) {
+ return false;
+ }
+
+ if (!referencedNonTypes.contains(field)) {
+ referencedNonTypes.add(field);
+ return true;
+ }
+ return true;
+ }
+
+ private boolean rescue(JMethod method) {
+ if (method == null) {
+ return false;
+ }
+
+ if (!referencedNonTypes.contains(method)) {
+ referencedNonTypes.add(method);
+ method.traverse(this);
+ if (method instanceof JsniMethod) {
+ /*
+ * SPECIAL: returning from this method passes a value from JavaScript
+ * into Java.
+ */
+ maybeRescueJavaScriptObjectPassingIntoJava(method.getType());
+ }
+ return true;
+ }
+ return false;
+ }
+
+ private boolean rescue(JReferenceType type, boolean isReferenced,
+ boolean isInstantiated) {
+ if (type == null) {
+ return false;
+ }
+
+ boolean doVisit = false;
+ if (isInstantiated && !instantiatedTypes.contains(type)) {
+ instantiatedTypes.add(type);
+ doVisit = true;
+ }
+
+ if (isReferenced && !referencedTypes.contains(type)) {
+ referencedTypes.add(type);
+ doVisit = true;
+ }
+
+ if (doVisit) {
+ type.traverse(this);
+ }
+
+ return doVisit;
+ }
+
+ /**
+ * Handle special rescues needed implicitly to support concat.
+ */
+ private void rescueByConcat(JType type) {
+ JClassType stringType = program.getTypeJavaLangString();
+ JPrimitiveType charType = program.getTypePrimitiveChar();
+ if (type instanceof JReferenceType && type != stringType) {
+ /*
+ * Any reference types (except String, which works by default) that take
+ * part in a concat must rescue java.lang.Object.toString().
+ */
+ JMethod toStringMethod = program.getSpecialMethod("Object.toString");
+ rescue(toStringMethod);
+ } else if (type == charType) {
+ /*
+ * Characters must rescue String.valueOf(char)
+ */
+ if (stringValueOfChar == null) {
+ for (int i = 0; i < stringType.methods.size(); ++i) {
+ JMethod meth = (JMethod) stringType.methods.get(i);
+ if (meth.getName().equals("valueOf")) {
+ List params = meth.getOriginalParamTypes();
+ if (params.size() == 1) {
+ if (params.get(0) == charType) {
+ stringValueOfChar = meth;
+ break;
+ }
+ }
+ }
+ }
+ assert (stringValueOfChar != null);
+ }
+ rescue(stringValueOfChar);
+ }
+ }
}
/**
@@ -406,7 +496,7 @@
if (referencedNonTypes.contains(x)) {
return false;
}
-
+
for (int i = 0; i < x.overrides.size(); ++i) {
JMethod ref = (JMethod) x.overrides.get(i);
if (referencedNonTypes.contains(ref)) {
@@ -424,100 +514,34 @@
}
// @Override
- public boolean visit(JsniMethod x) {
- return visit((JMethod) x);
- }
-
- // @Override
public boolean visit(JProgram x) {
didRescue = false;
return true;
}
+
+ // @Override
+ public boolean visit(JsniMethod x) {
+ return visit((JMethod) x);
+ }
}
- /**
- * Remove any unreferenced classes and interfaces from JProgram. Remove any
- * unreferenced methods and fields from their containing classes.
- */
- private class PruneVisitor extends JVisitor {
+ public static boolean exec(JProgram program, boolean noSpecialTypes) {
+ return new Pruner(program, noSpecialTypes).execImpl();
+ }
- private final ChangeList changeList = new ChangeList(
- "Prune unreferenced methods, fields, and types.");
+ private final JProgram program;
- public ChangeList getChangeList() {
- return changeList;
- }
+ private final boolean noSpecialTypes;
- // @Override
- public boolean visit(JClassType type) {
+ private final Set/* <JReferenceType> */referencedTypes = new HashSet/* <JReferenceType> */();
- assert (referencedTypes.contains(type));
- boolean isInstantiated = program.typeOracle.isInstantiatedType(type);
+ private final Set/* <JNode> */referencedNonTypes = new HashSet/* <JNode> */();
- for (int i = 0; i < type.fields.size(); ++i) {
- JField it = (JField) type.fields.get(i);
- if (!referencedNonTypes.contains(it)
- || pruneViaNoninstantiability(isInstantiated, it)) {
- changeList.removeField(it);
- }
- }
- for (int i = 0; i < type.methods.size(); ++i) {
- JMethod it = (JMethod) type.methods.get(i);
- if (!referencedNonTypes.contains(it)
- || pruneViaNoninstantiability(isInstantiated, it)) {
- changeList.removeMethod(it);
- }
- }
+ private JMethod stringValueOfChar = null;
- return false;
- }
-
- private boolean pruneViaNoninstantiability(boolean isInstantiated,
- JMethod it) {
- return (!isInstantiated && (!it.isStatic() || program.isStaticImpl(it)));
- }
-
- private boolean pruneViaNoninstantiability(boolean isInstantiated, JField it) {
- return (!isInstantiated && !it.isStatic());
- }
-
- // @Override
- public boolean visit(JInterfaceType type) {
- boolean isReferenced = referencedTypes.contains(type);
- boolean isInstantiated = program.typeOracle.isInstantiatedType(type);
-
- for (int i = 0; i < type.fields.size(); ++i) {
- JField it = (JField) type.fields.get(i);
- // all interface fields are static and final
- if (!isReferenced || !referencedNonTypes.contains(it)) {
- changeList.removeField(it);
- }
- }
- // start at index 1; never prune clinit directly out of the interface
- for (int i = 1; i < type.methods.size(); ++i) {
- JMethod it = (JMethod) type.methods.get(i);
- // all other interface methods are instance and abstract
- if (!isInstantiated || !referencedNonTypes.contains(it)) {
- changeList.removeMethod(it);
- }
- }
-
- return false;
- }
-
- // @Override
- public boolean visit(JProgram program) {
- for (int i = 0; i < program.getDeclaredTypes().size(); ++i) {
- JReferenceType type = (JReferenceType) program.getDeclaredTypes().get(i);
- if (referencedTypes.contains(type)
- || program.typeOracle.isInstantiatedType(type)) {
- type.traverse(this);
- } else {
- changeList.removeType(type);
- }
- }
- return false;
- }
+ private Pruner(JProgram program, boolean noSpecialTypes) {
+ this.program = program;
+ this.noSpecialTypes = noSpecialTypes;
}
private boolean execImpl() {
@@ -557,13 +581,4 @@
return madeChanges;
}
- private Pruner(JProgram program, boolean noSpecialTypes) {
- this.program = program;
- this.noSpecialTypes = noSpecialTypes;
- }
-
- public static boolean exec(JProgram program, boolean noSpecialTypes) {
- return new Pruner(program, noSpecialTypes).execImpl();
- }
-
}
diff --git a/dev/core/src/com/google/gwt/dev/jjs/impl/ReplaceRebinds.java b/dev/core/src/com/google/gwt/dev/jjs/impl/ReplaceRebinds.java
index ba7a5e3..e54a836 100644
--- a/dev/core/src/com/google/gwt/dev/jjs/impl/ReplaceRebinds.java
+++ b/dev/core/src/com/google/gwt/dev/jjs/impl/ReplaceRebinds.java
@@ -1,4 +1,18 @@
-// Copyright 2006 Google Inc. All Rights Reserved.
+/*
+ * Copyright 2006 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.impl;
import com.google.gwt.dev.jjs.ast.Holder;
@@ -14,17 +28,15 @@
import com.google.gwt.dev.jjs.ast.change.ChangeList;
/**
- * Replaces any "GWT.create()" calls with a new expression for the actual
- * result of the deferred binding decision.
+ * Replaces any "GWT.create()" calls with a new expression for the actual result
+ * of the deferred binding decision.
*/
public class ReplaceRebinds {
- private final JProgram program;
-
private class RebindVisitor extends JVisitor {
private final ChangeList changeList = new ChangeList(
- "Replace GWT.create() with new expressions.");
+ "Replace GWT.create() with new expressions.");
// @Override
public void endVisit(JMethodCall x, Mutator mutator) {
@@ -63,6 +75,16 @@
}
}
+ public static boolean exec(JProgram program) {
+ return new ReplaceRebinds(program).execImpl();
+ }
+
+ private final JProgram program;
+
+ private ReplaceRebinds(JProgram program) {
+ this.program = program;
+ }
+
private boolean execImpl() {
RebindVisitor rebinder = new RebindVisitor();
program.traverse(rebinder);
@@ -74,12 +96,4 @@
return true;
}
- private ReplaceRebinds(JProgram program) {
- this.program = program;
- }
-
- public static boolean exec(JProgram program) {
- return new ReplaceRebinds(program).execImpl();
- }
-
}
diff --git a/dev/core/src/com/google/gwt/dev/jjs/impl/SourceGenerationVisitor.java b/dev/core/src/com/google/gwt/dev/jjs/impl/SourceGenerationVisitor.java
index 55f4ccb..4d07ac4 100644
--- a/dev/core/src/com/google/gwt/dev/jjs/impl/SourceGenerationVisitor.java
+++ b/dev/core/src/com/google/gwt/dev/jjs/impl/SourceGenerationVisitor.java
@@ -1,4 +1,18 @@
-// Copyright 2006 Google Inc. All Rights Reserved.
+/*
+ * Copyright 2006 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.impl;
import com.google.gwt.dev.jjs.ast.CanBeFinal;
@@ -121,6 +135,23 @@
}
// @Override
+ public boolean visit(JProgram x) {
+ for (int i = 0; i < x.entryMethods.size(); ++i) {
+ JMethod method = (JMethod) x.entryMethods.get(i);
+ method.traverse(this);
+ newline();
+ newline();
+ }
+ for (int i = 0; i < x.getDeclaredTypes().size(); ++i) {
+ JReferenceType type = (JReferenceType) x.getDeclaredTypes().get(i);
+ type.traverse(this);
+ newline();
+ newline();
+ }
+ return false;
+ }
+
+ // @Override
public boolean visit(JsniMethod x) {
super.visit(x);
space();
@@ -140,20 +171,8 @@
}
// @Override
- public boolean visit(JProgram x) {
- for (int i = 0; i < x.entryMethods.size(); ++i) {
- JMethod method = (JMethod) x.entryMethods.get(i);
- method.traverse(this);
- newline();
- newline();
- }
- for (int i = 0; i < x.getDeclaredTypes().size(); ++i) {
- JReferenceType type = (JReferenceType) x.getDeclaredTypes().get(i);
- type.traverse(this);
- newline();
- newline();
- }
- return false;
+ protected void printMemberFinalFlag(CanBeFinal x) {
+ // suppress final flags
}
// @Override
@@ -165,17 +184,12 @@
}
}
- // @Override
- protected void printMemberFinalFlag(CanBeFinal x) {
- // suppress final flags
+ private boolean isEmptyInitializer(JMethod x) {
+ return isInitializer(x) && (x.body.statements.size() == 0);
}
private boolean isInitializer(JMethod x) {
return x.getName().equals("$clinit") || x.getName().equals("$init");
}
- private boolean isEmptyInitializer(JMethod x) {
- return isInitializer(x) && (x.body.statements.size() == 0);
- }
-
}
diff --git a/dev/core/src/com/google/gwt/dev/jjs/impl/TextOutputVisitor.java b/dev/core/src/com/google/gwt/dev/jjs/impl/TextOutputVisitor.java
index 34b393c..68a5a56 100644
--- a/dev/core/src/com/google/gwt/dev/jjs/impl/TextOutputVisitor.java
+++ b/dev/core/src/com/google/gwt/dev/jjs/impl/TextOutputVisitor.java
@@ -1,4 +1,18 @@
-// Copyright 2006 Google Inc. All Rights Reserved.
+/*
+ * Copyright 2006 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.impl;
import com.google.gwt.dev.jjs.ast.JVisitor;
@@ -6,49 +20,49 @@
public class TextOutputVisitor extends JVisitor implements TextOutput {
- private final TextOutput fTextOutput;
+ private final TextOutput textOutput;
- public TextOutputVisitor(TextOutput textOutput) {
- fTextOutput = textOutput;
- }
+ public TextOutputVisitor(TextOutput textOutput) {
+ this.textOutput = textOutput;
+ }
- public void indentIn() {
- fTextOutput.indentIn();
- }
+ public void indentIn() {
+ textOutput.indentIn();
+ }
- public void indentOut() {
- fTextOutput.indentOut();
- }
+ public void indentOut() {
+ textOutput.indentOut();
+ }
- public void newline() {
- fTextOutput.newline();
- }
+ public void newline() {
+ textOutput.newline();
+ }
- public void newlineOpt() {
- fTextOutput.newlineOpt();
- }
+ public void newlineOpt() {
+ textOutput.newlineOpt();
+ }
- public void print(char c) {
- fTextOutput.print(c);
- }
+ public void print(char c) {
+ textOutput.print(c);
+ }
- public void print(char[] s) {
- fTextOutput.print(s);
- }
+ public void print(char[] s) {
+ textOutput.print(s);
+ }
- public void print(String s) {
- fTextOutput.print(s);
- }
+ public void print(String s) {
+ textOutput.print(s);
+ }
- public void printOpt(char c) {
- fTextOutput.printOpt(c);
- }
+ public void printOpt(char c) {
+ textOutput.printOpt(c);
+ }
- public void printOpt(char[] s) {
- fTextOutput.printOpt(s);
- }
+ public void printOpt(char[] s) {
+ textOutput.printOpt(s);
+ }
- public void printOpt(String s) {
- fTextOutput.printOpt(s);
- }
+ public void printOpt(String s) {
+ textOutput.printOpt(s);
+ }
}
diff --git a/dev/core/src/com/google/gwt/dev/jjs/impl/ToStringGenerationVisitor.java b/dev/core/src/com/google/gwt/dev/jjs/impl/ToStringGenerationVisitor.java
index 70c2265..dd3028d 100644
--- a/dev/core/src/com/google/gwt/dev/jjs/impl/ToStringGenerationVisitor.java
+++ b/dev/core/src/com/google/gwt/dev/jjs/impl/ToStringGenerationVisitor.java
@@ -1,4 +1,18 @@
-// Copyright 2006 Google Inc. All Rights Reserved.
+/*
+ * Copyright 2006 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.impl;
import com.google.gwt.dev.jjs.ast.CanBeAbstract;
@@ -124,6 +138,10 @@
protected static final char[] CHARS_TRY = "try ".toCharArray();
protected static final char[] CHARS_WHILE = "while ".toCharArray();
+ private boolean needSemi = true;
+
+ private boolean suppressType = false;
+
public ToStringGenerationVisitor(TextOutput textOutput) {
super(textOutput);
}
@@ -191,15 +209,15 @@
openBlock();
for (int i = 0; i < x.statements.size(); ++i) {
JStatement statement = (JStatement) x.statements.get(i);
- fNeedSemi = true;
+ needSemi = true;
statement.traverse(this);
- if (fNeedSemi) {
+ if (needSemi) {
semi();
}
newline();
}
closeBlock();
- fNeedSemi = false;
+ needSemi = false;
return false;
}
@@ -229,7 +247,7 @@
}
print(':');
space();
- fNeedSemi = false;
+ needSemi = false;
return false;
}
@@ -330,12 +348,12 @@
x.body.traverse(this);
nestedStatementPop(x.body);
}
- if (fNeedSemi) {
+ if (needSemi) {
semi();
newline();
} else {
space();
- fNeedSemi = true;
+ needSemi = true;
}
print(CHARS_WHILE);
lparen();
@@ -357,11 +375,6 @@
}
// @Override
- public boolean visit(JsniFieldRef x) {
- return visit(x.getField());
- }
-
- // @Override
public boolean visit(JField x) {
// Due to our wacky construction model, only constant fields may be final
// when generating source
@@ -370,7 +383,7 @@
} else {
printMemberFinalFlag(x);
}
-
+
printStaticFlag(x);
printType(x);
space();
@@ -409,20 +422,20 @@
JStatement stmt = (JStatement) iter.next();
stmt.traverse(this);
}
- fSuppressType = true;
+ suppressType = true;
while (iter.hasNext()) {
print(CHARS_COMMA);
JStatement stmt = (JStatement) iter.next();
stmt.traverse(this);
}
- fSuppressType = false;
+ suppressType = false;
semi();
space();
if (x.getTestExpr() != null) {
x.getTestExpr().traverse(this);
}
-
+
semi();
space();
visitCollectionWithCommas(x.getIncrements().iterator());
@@ -450,12 +463,12 @@
}
if (x.elseStmt != null) {
- if (fNeedSemi) {
+ if (needSemi) {
semi();
newline();
} else {
space();
- fNeedSemi = true;
+ needSemi = true;
}
print(CHARS_ELSE);
boolean elseIf = x.elseStmt instanceof JIfStatement;
@@ -535,7 +548,7 @@
// @Override
public boolean visit(JLocalDeclarationStatement x) {
- if (!fSuppressType) {
+ if (!suppressType) {
x.getLocalRef().getTarget().traverse(this);
} else {
x.getLocalRef().traverse(this);
@@ -597,16 +610,6 @@
}
// @Override
- public boolean visit(JsniMethod x) {
- return printMethodHeader(x);
- }
-
- // @Override
- public boolean visit(JsniMethodRef x) {
- return printMethodHeader(x.getTarget());
- }
-
- // @Override
public boolean visit(JNewArray x, Mutator h) {
print(CHARS_NEW);
printTypeName(x.getArrayType().leafType);
@@ -705,6 +708,21 @@
}
// @Override
+ public boolean visit(JsniFieldRef x) {
+ return visit(x.getField());
+ }
+
+ // @Override
+ public boolean visit(JsniMethod x) {
+ return printMethodHeader(x);
+ }
+
+ // @Override
+ public boolean visit(JsniMethodRef x) {
+ return printMethodHeader(x.getTarget());
+ }
+
+ // @Override
public boolean visit(JsonArray x, Mutator m) {
print('[');
visitCollectionWithCommas(x.exprs.iterator());
@@ -902,11 +920,11 @@
if (c < 0x1000) {
print('0');
}
-
+
if (c < 0x100) {
print('0');
}
-
+
if (c < 0x10) {
print('0');
}
@@ -933,6 +951,16 @@
}
}
+ protected void printFloatLiteral(float value) {
+ print(Float.toString(value));
+ print('f');
+ }
+
+ protected void printLongLiteral(long value) {
+ print(Long.toString(value));
+ print('L');
+ }
+
protected void printMemberFinalFlag(CanBeFinal x) {
if (x.isFinal()) {
print(CHARS_FINAL);
@@ -957,7 +985,7 @@
} else {
printName(x);
}
-
+
// Parameters
printParameterList(x);
@@ -975,16 +1003,6 @@
return false;
}
- protected void printFloatLiteral(float value) {
- print(Float.toString(value));
- print('f');
- }
-
- protected void printLongLiteral(long value) {
- print(Long.toString(value));
- print('L');
- }
-
protected void printName(HasName x) {
print(x.getName());
}
@@ -1020,6 +1038,14 @@
printTypeName(hasType.getType());
}
+ protected void printTypeName(JType type) {
+ if (type instanceof JReferenceType) {
+ print(((JReferenceType) type).getShortName());
+ } else {
+ print(type.getName());
+ }
+ }
+
protected void rparen() {
print(')');
}
@@ -1044,20 +1070,8 @@
}
}
- protected void printTypeName(JType type) {
- if (type instanceof JReferenceType) {
- print(((JReferenceType) type).getShortName());
- } else {
- print(type.getName());
- }
- }
-
private void printUniqueName(HasName x) {
print(x.getName());
}
- private boolean fNeedSemi = true;
-
- private boolean fSuppressType = false;
-
}
diff --git a/dev/core/src/com/google/gwt/dev/jjs/impl/TypeMap.java b/dev/core/src/com/google/gwt/dev/jjs/impl/TypeMap.java
index 3057730..f5d2607 100644
--- a/dev/core/src/com/google/gwt/dev/jjs/impl/TypeMap.java
+++ b/dev/core/src/com/google/gwt/dev/jjs/impl/TypeMap.java
@@ -1,4 +1,18 @@
-// Copyright 2006 Google Inc. All Rights Reserved.
+/*
+ * Copyright 2006 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.impl;
import com.google.gwt.dev.jjs.ast.JArrayType;
@@ -18,8 +32,18 @@
*/
public class TypeMap {
+ /**
+ * Maps Eclipse AST nodes to our JNodes.
+ */
+ private final Map/* <Binding, JNode> */crossRefMap = new IdentityHashMap();
+
+ /**
+ * Centralizes creation and singleton management.
+ */
+ private final JProgram program;
+
public TypeMap(JProgram program) {
- fProgram = program;
+ this.program = program;
}
public JNode get(Binding binding) {
@@ -31,15 +55,15 @@
}
public JProgram getProgram() {
- return fProgram;
+ return program;
}
public void put(Binding binding, JNode to) {
if (binding == null) {
throw new InternalCompilerException("Trying to put null into typeMap.");
}
-
- Object old = fCrossRefMap.put(binding, to);
+
+ Object old = crossRefMap.put(binding, to);
assert (old == null);
}
@@ -48,7 +72,7 @@
}
private JNode internalGet(Binding binding) {
- JNode cached = (JNode) fCrossRefMap.get(binding);
+ JNode cached = (JNode) crossRefMap.get(binding);
if (cached != null) {
// Already seen this one.
return cached;
@@ -56,23 +80,23 @@
BaseTypeBinding baseTypeBinding = (BaseTypeBinding) binding;
switch (baseTypeBinding.id) {
case BaseTypeBinding.T_void:
- return fProgram.getTypeVoid();
+ return program.getTypeVoid();
case BaseTypeBinding.T_boolean:
- return fProgram.getTypePrimitiveBoolean();
+ return program.getTypePrimitiveBoolean();
case BaseTypeBinding.T_char:
- return fProgram.getTypePrimitiveChar();
+ return program.getTypePrimitiveChar();
case BaseTypeBinding.T_byte:
- return fProgram.getTypePrimitiveByte();
+ return program.getTypePrimitiveByte();
case BaseTypeBinding.T_short:
- return fProgram.getTypePrimitiveShort();
+ return program.getTypePrimitiveShort();
case BaseTypeBinding.T_int:
- return fProgram.getTypePrimitiveInt();
+ return program.getTypePrimitiveInt();
case BaseTypeBinding.T_long:
- return fProgram.getTypePrimitiveLong();
+ return program.getTypePrimitiveLong();
case BaseTypeBinding.T_float:
- return fProgram.getTypePrimitiveFloat();
+ return program.getTypePrimitiveFloat();
case BaseTypeBinding.T_double:
- return fProgram.getTypePrimitiveDouble();
+ return program.getTypePrimitiveDouble();
}
} else if (binding instanceof ArrayBinding) {
ArrayBinding arrayBinding = (ArrayBinding) binding;
@@ -82,22 +106,12 @@
// Don't create a new JArrayType; use TypeMap to get the singleton
// instance
- JArrayType arrayType = fProgram.getTypeArray(leafType,
- arrayBinding.dimensions);
+ JArrayType arrayType = program.getTypeArray(leafType,
+ arrayBinding.dimensions);
return arrayType;
}
return null;
}
- /**
- * Maps Eclipse AST nodes to our JNodes.
- */
- private final Map/* <Binding, JNode> */fCrossRefMap = new IdentityHashMap();
-
- /**
- * Centralizes creation and singleton management.
- */
- private final JProgram fProgram;
-
}
diff --git a/dev/core/src/com/google/gwt/dev/jjs/impl/TypeTightener.java b/dev/core/src/com/google/gwt/dev/jjs/impl/TypeTightener.java
index dc0e9a1..633c3c9 100644
--- a/dev/core/src/com/google/gwt/dev/jjs/impl/TypeTightener.java
+++ b/dev/core/src/com/google/gwt/dev/jjs/impl/TypeTightener.java
@@ -1,4 +1,18 @@
-// Copyright 2006 Google Inc. All Rights Reserved.
+/*
+ * Copyright 2006 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.impl;
import com.google.gwt.dev.jjs.ast.JArrayRef;
@@ -72,391 +86,12 @@
*/
public class TypeTightener {
- private final JProgram program;
- private final JNullType typeNull;
-
- private final Map/* <JReferenceType, Set<JClassType>> */implementors = new IdentityHashMap();
- private final Map/* <JMethod, Set<JExpression>> */returns = new IdentityHashMap();
- private final Map/* <JMethod, Set<JMethod>> */overriders = new IdentityHashMap();
- private final Map/* <JVariable, Set<JExpression>> */assignments = new IdentityHashMap();
- private final Map/* <JParameter, Set<JParameter>> */paramUpRefs = new IdentityHashMap();
-
- private static/* <T, V> */void add(Object target, Object value,
- Map/* <T, Set<V>> */map) {
- Set/* <V> */set = (Set) map.get(target);
- if (set == null) {
- set = new HashSet/* <V> */();
- map.put(target, set);
- }
- set.add(value);
- }
-
- /**
- * Record "type flow" information. Variables receive type flow via assignment.
- * As a special case, Parameters also receive type flow based on the types of
- * arguments used when calling the containing method (think of this as a kind
- * of assignment). Method return types receive type flow from their contained
- * return statements, plus the return type of any methods that
- * override/implement them.
- *
- * Note that we only have to run this pass ONCE to record the relationships,
- * because type tightening never changes any relationships, only the types of
- * the things related. In my original implementation, I had naively mapped
- * nodes onto sets of JReferenceType directly, which meant I had to rerun this
- * visitor each time.
- */
- public class RecordVisitor extends JVisitor {
-
- private JMethod fCurrentMethod;
-
- private void addAssignment(JVariable target, JExpression rhs) {
- add(target, rhs, assignments);
- }
-
- private void addImplementor(JReferenceType target, JClassType implementor) {
- add(target, implementor, implementors);
- }
-
- private void addOverrider(JMethod target, JMethod overrider) {
- add(target, overrider, overriders);
- }
-
- private void addReturn(JMethod target, JExpression expr) {
- add(target, expr, returns);
- }
-
- // @Override
- public void endVisit(JBinaryOperation x, Mutator m) {
- if (x.isAssignment() && (x.getType() instanceof JReferenceType)) {
- JExpression lhs = x.getLhs();
- if (lhs instanceof JVariableRef) {
- addAssignment(((JVariableRef) lhs).getTarget(), x.getRhs());
- }
- }
- }
-
- // @Override
- public void endVisit(JClassType x) {
- for (JClassType cur = x; cur != null; cur = cur.extnds) {
- addImplementor(cur, x);
- for (Iterator it = cur.implments.iterator(); it.hasNext();) {
- JInterfaceType implment = (JInterfaceType) it.next();
- addImplementor(implment, x);
- }
- }
- }
-
- // @Override
- public void endVisit(JField x) {
- if (x.constInitializer != null) {
- addAssignment(x, x.constInitializer);
- }
- fCurrentMethod = null;
- }
-
- // @Override
- public void endVisit(JLocalDeclarationStatement x) {
- JExpression initializer = x.getInitializer();
- if (initializer != null) {
- addAssignment(x.getLocalRef().getTarget(), initializer);
- }
- }
-
- // @Override
- public void endVisit(JMethod x) {
- for (int i = 0; i < x.overrides.size(); ++i) {
- JMethod method = (JMethod) x.overrides.get(i);
- addOverrider(method, x);
- }
- JMethod[] allVirtualOverrides = program.typeOracle.getAllVirtualOverrides(x);
- for (int i = 0; i < allVirtualOverrides.length; ++i) {
- JMethod method = allVirtualOverrides[i];
- addOverrider(method, x);
- }
- fCurrentMethod = null;
- }
-
- // @Override
- public void endVisit(JMethodCall x, Mutator m) {
- // All of the params in the target method are considered to be assigned by
- // the arguments from the caller
- Iterator/* <JExpression> */argIt = x.args.iterator();
- ArrayList params = x.getTarget().params;
- for (int i = 0; i < params.size(); ++i) {
- JParameter param = (JParameter) params.get(i);
- JExpression arg = (JExpression) argIt.next();
- if (param.getType() instanceof JReferenceType) {
- addAssignment(param, arg);
- }
- }
- }
-
- // @Override
- public void endVisit(JsniMethod x) {
- endVisit((JMethod) x);
- }
-
- // @Override
- public void endVisit(JReturnStatement x) {
- if (fCurrentMethod.getType() instanceof JReferenceType) {
- addReturn(fCurrentMethod, x.getExpression());
- }
- }
-
- // @Override
- public void endVisit(JsniFieldRef x) {
- // If this happens in JSNI, we can't make any type-tightening assumptions
- // Fake an assignment-to-self to prevent tightening
- addAssignment(x.getTarget(), x);
- }
-
- // @Override
- public void endVisit(JsniMethodRef x) {
- // If this happens in JSNI, we can't make any type-tightening assumptions
- // Fake an assignment-to-self on all args to prevent tightening
-
- JMethod method = x.getTarget();
-
- for (int i = 0; i < method.params.size(); ++i) {
- JParameter param = (JParameter) method.params.get(i);
- addAssignment(param, new JParameterRef(program, param));
- }
- }
-
- // @Override
- public void endVisit(JTryStatement x) {
- // Never tighten args to catch blocks
- // Fake an assignment-to-self to prevent tightening
- for (int i = 0; i < x.catchArgs.size(); ++i) {
- JLocalRef arg = (JLocalRef) x.catchArgs.get(i);
- addAssignment(arg.getTarget(), arg);
- }
- }
-
- /**
- * Merge param call args across overriders/implementors. We can't tighten a
- * param type in an overriding method if the declaring method is looser.
- */
- // @Override
- public boolean visit(JMethod x) {
- fCurrentMethod = x;
-
- List/* <JMethod> */overrides = x.overrides;
- JMethod[] virtualOverrides = program.typeOracle.getAllVirtualOverrides(x);
-
- if (overrides.isEmpty() && virtualOverrides.length == 0) {
- return true;
- }
-
- for (int j = 0, c = x.params.size(); j < c; ++j) {
- JParameter param = (JParameter) x.params.get(j);
- Set/* <JParameter> */set = (Set) paramUpRefs.get(param);
- if (set == null) {
- set = new HashSet/* <JParameter> */();
- paramUpRefs.put(param, set);
- }
- for (int i = 0; i < overrides.size(); ++i) {
- JMethod baseMethod = (JMethod) overrides.get(i);
- JParameter baseParam = (JParameter) baseMethod.params.get(j);
- set.add(baseParam);
- }
- for (int i = 0; i < virtualOverrides.length; ++i) {
- JMethod baseMethod = virtualOverrides[i];
- JParameter baseParam = (JParameter) baseMethod.params.get(j);
- set.add(baseParam);
- }
- }
-
- return true;
- }
- }
-
- /**
- * Wherever possible, use the type flow information recorded by RecordVisitor
- * to change the declared type of a field, local, parameter, or method to a
- * more specific type.
- *
- * We must iterate mutiple times because each way point we tighten creates
- * more opportunities to do additional tightening for the things that depend
- * on it.
- */
- public class TightenTypesVisitor extends JVisitor {
- private final ChangeList changeList = new ChangeList(
- "Tighten types on fields, locals, params, methods.");
-
- public ChangeList getChangeList() {
- return changeList;
- }
-
- /**
- * Tighten based on assignment, and for parameters, callArgs as well.
- */
- private void tighten(JVariable x) {
- if (!(x.getType() instanceof JReferenceType)) {
- return;
- }
- JReferenceType refType = (JReferenceType) x.getType();
-
- if (refType == typeNull) {
- return;
- }
-
- // tighten based on non-instantiability
- if (!program.typeOracle.isInstantiatedType(refType)) {
- changeList.changeType(x, typeNull);
- return;
- }
-
- // tighten based on assignment
- List/* <JReferenceType> */typeList = new ArrayList/* <JReferenceType> */();
-
- /*
- * Always assume at least one null assignment; if there really aren't any
- * other assignments, then this variable will get the null type. If there
- * are, it won't hurt anything because null type will always lose.
- */
- typeList.add(typeNull);
-
- Set/* <JExpression> */myAssignments = (Set) assignments.get(x);
- if (myAssignments != null) {
- for (Iterator iter = myAssignments.iterator(); iter.hasNext();) {
- JExpression expr = (JExpression) iter.next();
- JType type = expr.getType();
- if (!(type instanceof JReferenceType)) {
- return; // something fishy is going on, just abort
- }
- typeList.add(type);
- }
- }
-
- if (x instanceof JParameter) {
- Set/* <JParameter> */myParams = (Set) paramUpRefs.get(x);
- if (myParams != null) {
- for (Iterator iter = myParams.iterator(); iter.hasNext();) {
- JParameter param = (JParameter) iter.next();
- typeList.add(param.getType());
- }
- }
- }
-
- JReferenceType resultType = program.generalizeTypes(typeList);
- resultType = program.strongerType(refType, resultType);
- if (refType != resultType) {
- changeList.changeType(x, resultType);
- }
- }
-
- // @Override
- public void endVisit(JField x) {
- tighten(x);
- }
-
- // @Override
- public void endVisit(JLocal x) {
- tighten(x);
- }
-
- // @Override
- public void endVisit(JNewArray x, Mutator m) {
- // tighten leaf type based on non-instantiability
- JArrayType arrayType = x.getArrayType();
- JType leafType = arrayType.getLeafType();
- if (leafType instanceof JReferenceType) {
- if (!program.typeOracle.isInstantiatedType((JReferenceType) leafType)) {
- arrayType = program.getTypeArray(typeNull, arrayType.getDims());
- changeList.changeType(x, arrayType);
- }
- }
- }
-
- // @Override
- public void endVisit(JParameter x) {
- tighten(x);
- }
-
- // @Override
- public boolean visit(JClassType x) {
- // don't mess with classes used in code gen
- if (program.specialTypes.contains(x)) {
- return false;
- }
- return true;
- }
-
- /**
- * Tighten based on return types and overrides.
- */
- // @Override
- public void endVisit(JMethod x) {
-
- if (!(x.getType() instanceof JReferenceType)) {
- return;
- }
- JReferenceType refType = (JReferenceType) x.getType();
-
- if (refType == typeNull) {
- return;
- }
-
- // tighten based on non-instantiability
- if (!program.typeOracle.isInstantiatedType(refType)) {
- changeList.changeType(x, typeNull);
- return;
- }
-
- // tighten based on both returned types and possible overrides
- List/* <JReferenceType> */typeList = new ArrayList/* <JReferenceType> */();
-
- /*
- * Always assume at least one null assignment; if there really aren't any
- * other assignments, then this variable will get the null type. If there
- * are, it won't hurt anything because null type will always lose.
- */
- typeList.add(typeNull);
-
- Set/* <JExpression> */myReturns = (Set) returns.get(x);
- if (myReturns != null) {
- for (Iterator iter = myReturns.iterator(); iter.hasNext();) {
- JExpression expr = (JExpression) iter.next();
- typeList.add(expr.getType());
- }
- }
- Set/* <JMethod> */myOverriders = (Set) overriders.get(x);
- if (myOverriders != null) {
- for (Iterator iter = myOverriders.iterator(); iter.hasNext();) {
- JMethod method = (JMethod) iter.next();
- typeList.add(method.getType());
- }
- }
-
- JReferenceType resultType = program.generalizeTypes(typeList);
- resultType = program.strongerType(refType, resultType);
- if (refType != resultType) {
- changeList.changeType(x, resultType);
- }
- }
-
- public boolean visit(JsniMethod x) {
- /*
- * Explicitly NOT visiting native methods since we can't infer type
- * information.
- *
- * TODO(later): can we figure out simple pass-through info?
- */
- return false;
- }
- }
-
/**
* Replaces dangling null references with dummy calls.
*/
public class FixDanglingRefsVisitor extends JVisitor {
private final ChangeList changeList = new ChangeList(
- "Replace dangling null references with dummy calls.");
-
- public ChangeList getChangeList() {
- return changeList;
- }
+ "Replace dangling null references with dummy calls.");
// @Override
public void endVisit(JArrayRef x, Mutator m) {
@@ -521,7 +156,393 @@
changeList.replaceExpression(m, call);
}
}
+
+ public ChangeList getChangeList() {
+ return changeList;
+ }
}
+ /**
+ * Record "type flow" information. Variables receive type flow via assignment.
+ * As a special case, Parameters also receive type flow based on the types of
+ * arguments used when calling the containing method (think of this as a kind
+ * of assignment). Method return types receive type flow from their contained
+ * return statements, plus the return type of any methods that
+ * override/implement them.
+ *
+ * Note that we only have to run this pass ONCE to record the relationships,
+ * because type tightening never changes any relationships, only the types of
+ * the things related. In my original implementation, I had naively mapped
+ * nodes onto sets of JReferenceType directly, which meant I had to rerun this
+ * visitor each time.
+ */
+ public class RecordVisitor extends JVisitor {
+
+ private JMethod currentMethod;
+
+ // @Override
+ public void endVisit(JBinaryOperation x, Mutator m) {
+ if (x.isAssignment() && (x.getType() instanceof JReferenceType)) {
+ JExpression lhs = x.getLhs();
+ if (lhs instanceof JVariableRef) {
+ addAssignment(((JVariableRef) lhs).getTarget(), x.getRhs());
+ }
+ }
+ }
+
+ // @Override
+ public void endVisit(JClassType x) {
+ for (JClassType cur = x; cur != null; cur = cur.extnds) {
+ addImplementor(cur, x);
+ for (Iterator it = cur.implments.iterator(); it.hasNext();) {
+ JInterfaceType implment = (JInterfaceType) it.next();
+ addImplementor(implment, x);
+ }
+ }
+ }
+
+ // @Override
+ public void endVisit(JField x) {
+ if (x.constInitializer != null) {
+ addAssignment(x, x.constInitializer);
+ }
+ currentMethod = null;
+ }
+
+ // @Override
+ public void endVisit(JLocalDeclarationStatement x) {
+ JExpression initializer = x.getInitializer();
+ if (initializer != null) {
+ addAssignment(x.getLocalRef().getTarget(), initializer);
+ }
+ }
+
+ // @Override
+ public void endVisit(JMethod x) {
+ for (int i = 0; i < x.overrides.size(); ++i) {
+ JMethod method = (JMethod) x.overrides.get(i);
+ addOverrider(method, x);
+ }
+ JMethod[] allVirtualOverrides = program.typeOracle.getAllVirtualOverrides(x);
+ for (int i = 0; i < allVirtualOverrides.length; ++i) {
+ JMethod method = allVirtualOverrides[i];
+ addOverrider(method, x);
+ }
+ currentMethod = null;
+ }
+
+ // @Override
+ public void endVisit(JMethodCall x, Mutator m) {
+ // All of the params in the target method are considered to be assigned by
+ // the arguments from the caller
+ Iterator/* <JExpression> */argIt = x.args.iterator();
+ ArrayList params = x.getTarget().params;
+ for (int i = 0; i < params.size(); ++i) {
+ JParameter param = (JParameter) params.get(i);
+ JExpression arg = (JExpression) argIt.next();
+ if (param.getType() instanceof JReferenceType) {
+ addAssignment(param, arg);
+ }
+ }
+ }
+
+ // @Override
+ public void endVisit(JReturnStatement x) {
+ if (currentMethod.getType() instanceof JReferenceType) {
+ addReturn(currentMethod, x.getExpression());
+ }
+ }
+
+ // @Override
+ public void endVisit(JsniFieldRef x) {
+ // If this happens in JSNI, we can't make any type-tightening assumptions
+ // Fake an assignment-to-self to prevent tightening
+ addAssignment(x.getTarget(), x);
+ }
+
+ // @Override
+ public void endVisit(JsniMethod x) {
+ endVisit((JMethod) x);
+ }
+
+ // @Override
+ public void endVisit(JsniMethodRef x) {
+ // If this happens in JSNI, we can't make any type-tightening assumptions
+ // Fake an assignment-to-self on all args to prevent tightening
+
+ JMethod method = x.getTarget();
+
+ for (int i = 0; i < method.params.size(); ++i) {
+ JParameter param = (JParameter) method.params.get(i);
+ addAssignment(param, new JParameterRef(program, param));
+ }
+ }
+
+ // @Override
+ public void endVisit(JTryStatement x) {
+ // Never tighten args to catch blocks
+ // Fake an assignment-to-self to prevent tightening
+ for (int i = 0; i < x.catchArgs.size(); ++i) {
+ JLocalRef arg = (JLocalRef) x.catchArgs.get(i);
+ addAssignment(arg.getTarget(), arg);
+ }
+ }
+
+ /**
+ * Merge param call args across overriders/implementors. We can't tighten a
+ * param type in an overriding method if the declaring method is looser.
+ */
+ // @Override
+ public boolean visit(JMethod x) {
+ currentMethod = x;
+
+ List/* <JMethod> */overrides = x.overrides;
+ JMethod[] virtualOverrides = program.typeOracle.getAllVirtualOverrides(x);
+
+ if (overrides.isEmpty() && virtualOverrides.length == 0) {
+ return true;
+ }
+
+ for (int j = 0, c = x.params.size(); j < c; ++j) {
+ JParameter param = (JParameter) x.params.get(j);
+ Set/* <JParameter> */set = (Set) paramUpRefs.get(param);
+ if (set == null) {
+ set = new HashSet/* <JParameter> */();
+ paramUpRefs.put(param, set);
+ }
+ for (int i = 0; i < overrides.size(); ++i) {
+ JMethod baseMethod = (JMethod) overrides.get(i);
+ JParameter baseParam = (JParameter) baseMethod.params.get(j);
+ set.add(baseParam);
+ }
+ for (int i = 0; i < virtualOverrides.length; ++i) {
+ JMethod baseMethod = virtualOverrides[i];
+ JParameter baseParam = (JParameter) baseMethod.params.get(j);
+ set.add(baseParam);
+ }
+ }
+
+ return true;
+ }
+
+ private void addAssignment(JVariable target, JExpression rhs) {
+ add(target, rhs, assignments);
+ }
+
+ private void addImplementor(JReferenceType target, JClassType implementor) {
+ add(target, implementor, implementors);
+ }
+
+ private void addOverrider(JMethod target, JMethod overrider) {
+ add(target, overrider, overriders);
+ }
+
+ private void addReturn(JMethod target, JExpression expr) {
+ add(target, expr, returns);
+ }
+ }
+
+ /**
+ * Wherever possible, use the type flow information recorded by RecordVisitor
+ * to change the declared type of a field, local, parameter, or method to a
+ * more specific type.
+ *
+ * We must iterate mutiple times because each way point we tighten creates
+ * more opportunities to do additional tightening for the things that depend
+ * on it.
+ */
+ public class TightenTypesVisitor extends JVisitor {
+ private final ChangeList changeList = new ChangeList(
+ "Tighten types on fields, locals, params, methods.");
+
+ // @Override
+ public void endVisit(JField x) {
+ tighten(x);
+ }
+
+ // @Override
+ public void endVisit(JLocal x) {
+ tighten(x);
+ }
+
+ /**
+ * Tighten based on return types and overrides.
+ */
+ // @Override
+ public void endVisit(JMethod x) {
+
+ if (!(x.getType() instanceof JReferenceType)) {
+ return;
+ }
+ JReferenceType refType = (JReferenceType) x.getType();
+
+ if (refType == typeNull) {
+ return;
+ }
+
+ // tighten based on non-instantiability
+ if (!program.typeOracle.isInstantiatedType(refType)) {
+ changeList.changeType(x, typeNull);
+ return;
+ }
+
+ // tighten based on both returned types and possible overrides
+ List/* <JReferenceType> */typeList = new ArrayList/* <JReferenceType> */();
+
+ /*
+ * Always assume at least one null assignment; if there really aren't any
+ * other assignments, then this variable will get the null type. If there
+ * are, it won't hurt anything because null type will always lose.
+ */
+ typeList.add(typeNull);
+
+ Set/* <JExpression> */myReturns = (Set) returns.get(x);
+ if (myReturns != null) {
+ for (Iterator iter = myReturns.iterator(); iter.hasNext();) {
+ JExpression expr = (JExpression) iter.next();
+ typeList.add(expr.getType());
+ }
+ }
+ Set/* <JMethod> */myOverriders = (Set) overriders.get(x);
+ if (myOverriders != null) {
+ for (Iterator iter = myOverriders.iterator(); iter.hasNext();) {
+ JMethod method = (JMethod) iter.next();
+ typeList.add(method.getType());
+ }
+ }
+
+ JReferenceType resultType = program.generalizeTypes(typeList);
+ resultType = program.strongerType(refType, resultType);
+ if (refType != resultType) {
+ changeList.changeType(x, resultType);
+ }
+ }
+
+ // @Override
+ public void endVisit(JNewArray x, Mutator m) {
+ // tighten leaf type based on non-instantiability
+ JArrayType arrayType = x.getArrayType();
+ JType leafType = arrayType.getLeafType();
+ if (leafType instanceof JReferenceType) {
+ if (!program.typeOracle.isInstantiatedType((JReferenceType) leafType)) {
+ arrayType = program.getTypeArray(typeNull, arrayType.getDims());
+ changeList.changeType(x, arrayType);
+ }
+ }
+ }
+
+ // @Override
+ public void endVisit(JParameter x) {
+ tighten(x);
+ }
+
+ public ChangeList getChangeList() {
+ return changeList;
+ }
+
+ // @Override
+ public boolean visit(JClassType x) {
+ // don't mess with classes used in code gen
+ if (program.specialTypes.contains(x)) {
+ return false;
+ }
+ return true;
+ }
+
+ public boolean visit(JsniMethod x) {
+ /*
+ * Explicitly NOT visiting native methods since we can't infer type
+ * information.
+ *
+ * TODO(later): can we figure out simple pass-through info?
+ */
+ return false;
+ }
+
+ /**
+ * Tighten based on assignment, and for parameters, callArgs as well.
+ */
+ private void tighten(JVariable x) {
+ if (!(x.getType() instanceof JReferenceType)) {
+ return;
+ }
+ JReferenceType refType = (JReferenceType) x.getType();
+
+ if (refType == typeNull) {
+ return;
+ }
+
+ // tighten based on non-instantiability
+ if (!program.typeOracle.isInstantiatedType(refType)) {
+ changeList.changeType(x, typeNull);
+ return;
+ }
+
+ // tighten based on assignment
+ List/* <JReferenceType> */typeList = new ArrayList/* <JReferenceType> */();
+
+ /*
+ * Always assume at least one null assignment; if there really aren't any
+ * other assignments, then this variable will get the null type. If there
+ * are, it won't hurt anything because null type will always lose.
+ */
+ typeList.add(typeNull);
+
+ Set/* <JExpression> */myAssignments = (Set) assignments.get(x);
+ if (myAssignments != null) {
+ for (Iterator iter = myAssignments.iterator(); iter.hasNext();) {
+ JExpression expr = (JExpression) iter.next();
+ JType type = expr.getType();
+ if (!(type instanceof JReferenceType)) {
+ return; // something fishy is going on, just abort
+ }
+ typeList.add(type);
+ }
+ }
+
+ if (x instanceof JParameter) {
+ Set/* <JParameter> */myParams = (Set) paramUpRefs.get(x);
+ if (myParams != null) {
+ for (Iterator iter = myParams.iterator(); iter.hasNext();) {
+ JParameter param = (JParameter) iter.next();
+ typeList.add(param.getType());
+ }
+ }
+ }
+
+ JReferenceType resultType = program.generalizeTypes(typeList);
+ resultType = program.strongerType(refType, resultType);
+ if (refType != resultType) {
+ changeList.changeType(x, resultType);
+ }
+ }
+ }
+
+ public static boolean exec(JProgram program) {
+ return new TypeTightener(program).execImpl();
+ }
+
+ private static/* <T, V> */void add(Object target, Object value,
+ Map/* <T, Set<V>> */map) {
+ Set/* <V> */set = (Set) map.get(target);
+ if (set == null) {
+ set = new HashSet/* <V> */();
+ map.put(target, set);
+ }
+ set.add(value);
+ }
+
+ private final JProgram program;
+ private final JNullType typeNull;
+
+ private final Map/* <JReferenceType, Set<JClassType>> */implementors = new IdentityHashMap();
+
+ private final Map/* <JMethod, Set<JExpression>> */returns = new IdentityHashMap();
+
+ private final Map/* <JMethod, Set<JMethod>> */overriders = new IdentityHashMap();
+
+ private final Map/* <JVariable, Set<JExpression>> */assignments = new IdentityHashMap();
+
+ private final Map/* <JParameter, Set<JParameter>> */paramUpRefs = new IdentityHashMap();
private TypeTightener(JProgram program) {
this.program = program;
@@ -551,8 +572,4 @@
}
}
- public static boolean exec(JProgram program) {
- return new TypeTightener(program).execImpl();
- }
-
}