KickJava   Java API By Example, From Geeks To Geeks.

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


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.JArrayType;
20 import com.google.gwt.dev.jjs.ast.JClassType;
21 import com.google.gwt.dev.jjs.ast.JExpression;
22 import com.google.gwt.dev.jjs.ast.JInterfaceType;
23 import com.google.gwt.dev.jjs.ast.JMethod;
24 import com.google.gwt.dev.jjs.ast.JMethodCall;
25 import com.google.gwt.dev.jjs.ast.JModVisitor;
26 import com.google.gwt.dev.jjs.ast.JNullType;
27 import com.google.gwt.dev.jjs.ast.JProgram;
28 import com.google.gwt.dev.jjs.ast.JReferenceType;
29 import com.google.gwt.dev.jjs.ast.JType;
30
31 /**
32  * Update polymorphic method calls to tighter bindings based on the type of the
33  * qualifier. For a given polymorphic method call to a non-final target, see if
34  * the static type of the qualifer would let us target an override instead.
35  *
36  * This is possible because the qualifier might have been tightened by
37  * {@link com.google.gwt.dev.jjs.impl.TypeTightener}.
38  */

39 public class MethodCallTightener {
40
41   /**
42    * Updates polymorphic method calls to tighter bindings based on the type of
43    * the qualifier.
44    */

45   public class MethodCallTighteningVisitor extends JModVisitor {
46
47     // @Override
48
public void endVisit(JMethodCall x, Context ctx) {
49       JMethod method = x.getTarget();
50       JExpression instance = x.getInstance();
51
52       // The method call is already known statically
53
if (!x.canBePolymorphic()) {
54         return;
55       }
56
57       JType instanceType = instance.getType();
58       JReferenceType enclosingType = method.getEnclosingType();
59
60       if (instanceType == enclosingType
61           || instanceType instanceof JInterfaceType) {
62         // This method call is as tight as it can be for the type of the
63
// qualifier
64
return;
65       }
66
67       if (instanceType instanceof JArrayType) {
68         // shouldn't get here; arrays don't have extra methods
69
return;
70       }
71
72       if (instanceType instanceof JNullType) {
73         // TypeTightener will handle this case
74
return;
75       }
76
77       assert (instanceType instanceof JClassType);
78
79       /*
80        * Search myself and all my super types to find a tighter implementation
81        * of the called method, if possible.
82        */

83       JMethod foundMethod = null;
84       JClassType type;
85       outer : for (type = (JClassType) instanceType; type != null
86           && type != enclosingType; type = type.extnds) {
87         for (int i = 0; i < type.methods.size(); ++i) {
88           JMethod methodIt = (JMethod) type.methods.get(i);
89           if (JProgram.methodsDoMatch(method, methodIt)) {
90             foundMethod = methodIt;
91             break outer;
92           }
93         }
94       }
95
96       if (foundMethod == null) {
97         return;
98       }
99
100       /*
101        * Replace the call to the original method with a call to the same method
102        * on the tighter type.
103        */

104       JMethodCall call = new JMethodCall(program, x.getSourceInfo(),
105           x.getInstance(), foundMethod);
106       call.getArgs().addAll(x.getArgs());
107       ctx.replaceMe(call);
108     }
109   }
110
111   public static boolean exec(JProgram program) {
112     return new MethodCallTightener(program).execImpl();
113   }
114
115   private final JProgram program;
116
117   private MethodCallTightener(JProgram program) {
118     this.program = program;
119   }
120
121   private boolean execImpl() {
122     MethodCallTighteningVisitor tightener = new MethodCallTighteningVisitor();
123     tightener.accept(program);
124     return tightener.didChange();
125   }
126
127 }
128
Popular Tags