KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > google > gwt > dev > jjs > impl > MethodAndClassFinalizer


1 /*
2  * Copyright 2007 Google Inc.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License"); you may not
5  * use this file except in compliance with the License. You may obtain a copy of
6  * the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12  * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13  * License for the specific language governing permissions and limitations under
14  * the License.
15  */

16 package com.google.gwt.dev.jjs.impl;
17
18 import com.google.gwt.dev.jjs.ast.Context;
19 import com.google.gwt.dev.jjs.ast.JClassType;
20 import com.google.gwt.dev.jjs.ast.JInterfaceType;
21 import com.google.gwt.dev.jjs.ast.JMethod;
22 import com.google.gwt.dev.jjs.ast.JProgram;
23 import com.google.gwt.dev.jjs.ast.JReferenceType;
24 import com.google.gwt.dev.jjs.ast.JVisitor;
25 import com.google.gwt.dev.jjs.ast.js.JsniMethod;
26
27 import java.util.HashSet JavaDoc;
28 import java.util.Set JavaDoc;
29
30 /**
31  * Finds all methods and classes are effectively final. That is, methods that
32  * are never overriden and classes that are never subclassed. Mark all such
33  * methods and classes as final, since it helps us optimize.
34  */

35 public class MethodAndClassFinalizer {
36
37   /**
38    * Any method and classes that weren't marked during MarkVisitor can be set
39    * final.
40    *
41    * Open question: What does it mean if an interface/abstract method becomes
42    * final? Is this possible after Pruning? I guess it means that someone tried
43    * to make a call to method that wasn't actually implemented anywhere in the
44    * program. But if it wasn't implemented, then the enclosing class should have
45    * come up as not instantiated and been culled. So I think it's not possible.
46    */

47   private class FinalizeVisitor extends JVisitor {
48
49     private boolean didChange = false;
50
51     public boolean didChange() {
52       return didChange;
53     }
54
55     // @Override
56
public boolean visit(JClassType x, Context ctx) {
57       if (!x.isFinal() && !isSubclassed.contains(x)) {
58         x.setFinal(true);
59         didChange = true;
60       }
61       for (int i = 0; i < x.methods.size(); ++i) {
62         JMethod method = (JMethod) x.methods.get(i);
63         accept(method);
64       }
65       return false;
66     }
67
68     // @Override
69
public boolean visit(JInterfaceType x, Context ctx) {
70       for (int i = 0; i < x.methods.size(); ++i) {
71         JMethod method = (JMethod) x.methods.get(i);
72         accept(method);
73       }
74       return false;
75     }
76
77     // @Override
78
public boolean visit(JMethod x, Context ctx) {
79       if (!x.isFinal() && !isOverriden.contains(x)) {
80         x.setFinal(true);
81         didChange = true;
82       }
83       return false;
84     }
85
86     // @Override
87
public boolean visit(JsniMethod x, Context ctx) {
88       return visit((JMethod) x, ctx);
89     }
90   }
91   /**
92    * Find all methods and classes that ARE overriden/subclassed.
93    */

94   private class MarkVisitor extends JVisitor {
95
96     // @Override
97
public boolean visit(JClassType x, Context ctx) {
98       if (x.extnds != null) {
99         isSubclassed.add(x.extnds);
100       }
101
102       for (int i = 0; i < x.methods.size(); ++i) {
103         JMethod method = (JMethod) x.methods.get(i);
104         accept(method);
105       }
106       return false;
107     }
108
109     // @Override
110
public boolean visit(JInterfaceType x, Context ctx) {
111       for (int i = 0; i < x.methods.size(); ++i) {
112         JMethod method = (JMethod) x.methods.get(i);
113         accept(method);
114       }
115       return false;
116     }
117
118     // @Override
119
public boolean visit(JMethod x, Context ctx) {
120       for (int i = 0; i < x.overrides.size(); ++i) {
121         JMethod it = (JMethod) x.overrides.get(i);
122         isOverriden.add(it);
123       }
124       return false;
125     }
126
127     // @Override
128
public boolean visit(JProgram x, Context ctx) {
129       for (int i = 0; i < x.getDeclaredTypes().size(); ++i) {
130         JReferenceType type = (JReferenceType) x.getDeclaredTypes().get(i);
131         accept(type);
132       }
133       return false;
134     }
135
136     // @Override
137
public boolean visit(JsniMethod x, Context ctx) {
138       return visit((JMethod) x, ctx);
139     }
140   }
141
142   public static boolean exec(JProgram program) {
143     return new MethodAndClassFinalizer().execImpl(program);
144   }
145
146   private final Set JavaDoc/* <JMethod> */isOverriden = new HashSet JavaDoc/* <JMethod> */();
147
148   private final Set JavaDoc/* <JClassType> */isSubclassed = new HashSet JavaDoc/* <JClassType> */();
149
150   private MethodAndClassFinalizer() {
151   }
152
153   private boolean execImpl(JProgram program) {
154     MarkVisitor marker = new MarkVisitor();
155     marker.accept(program);
156
157     FinalizeVisitor finalizer = new FinalizeVisitor();
158     finalizer.accept(program);
159     return finalizer.didChange();
160   }
161
162 }
163
Popular Tags