OSDN Git Service

original
[gb-231r1-is01/Gingerbread_2.3.3_r1_IS01.git] / dalvik / dx / src / com / android / dx / cf / code / ConcreteMethod.java
1 /*
2  * Copyright (C) 2007 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of 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,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 package com.android.dx.cf.code;
18
19 import com.android.dx.cf.attrib.AttCode;
20 import com.android.dx.cf.attrib.AttLineNumberTable;
21 import com.android.dx.cf.attrib.AttLocalVariableTable;
22 import com.android.dx.cf.attrib.AttLocalVariableTypeTable;
23 import com.android.dx.cf.attrib.AttSourceFile;
24 import com.android.dx.cf.iface.AttributeList;
25 import com.android.dx.cf.iface.ClassFile;
26 import com.android.dx.cf.iface.Method;
27 import com.android.dx.rop.code.AccessFlags;
28 import com.android.dx.rop.code.SourcePosition;
29 import com.android.dx.rop.cst.CstNat;
30 import com.android.dx.rop.cst.CstType;
31 import com.android.dx.rop.cst.CstUtf8;
32 import com.android.dx.rop.type.Prototype;
33
34 /**
35  * Container for all the giblets that make up a concrete Java bytecode method.
36  * It implements {@link Method}, so it provides all the original access
37  * (by delegation), but it also constructs and keeps useful versions of
38  * stuff extracted from the method's {@code Code} attribute.
39  */
40 public final class ConcreteMethod implements Method {
41     /** {@code non-null;} method being wrapped */
42     private final Method method;
43
44     /**
45      * {@code null-ok;} the class's {@code SourceFile} attribute value,
46      * if any
47      */
48     private final CstUtf8 sourceFile;
49
50     /**
51      * whether the class that this method is part of is defined with
52      * {@code ACC_SUPER}
53      */
54     private final boolean accSuper;
55
56     /** {@code non-null;} the code attribute */
57     private final AttCode attCode;
58
59     /** {@code non-null;} line number list */
60     private final LineNumberList lineNumbers;
61
62     /** {@code non-null;} local variable list */
63     private final LocalVariableList localVariables;
64
65     /**
66      * Constructs an instance.
67      *
68      * @param method {@code non-null;} the method to be based on
69      * @param cf {@code non-null;} the class file that contains this method
70      * @param keepLines whether to keep the line number information
71      * (if any)
72      * @param keepLocals whether to keep the local variable
73      * information (if any)
74      */
75     public ConcreteMethod(Method method, ClassFile cf, boolean keepLines,
76                           boolean keepLocals) {
77         this.method = method;
78         this.accSuper = (cf.getAccessFlags() & AccessFlags.ACC_SUPER) != 0;
79         this.sourceFile = cf.getSourceFile();
80
81         AttributeList attribs = method.getAttributes();
82         this.attCode = (AttCode) attribs.findFirst(AttCode.ATTRIBUTE_NAME);
83
84         AttributeList codeAttribs = attCode.getAttributes();
85
86         /*
87          * Combine all LineNumberTable attributes into one, with the
88          * combined result saved into the instance. The following code
89          * isn't particularly efficient for doing merges, but as far
90          * as I know, this situation rarely occurs "in the
91          * wild," so there's not much point in optimizing for it.
92          */
93         LineNumberList lineNumbers = LineNumberList.EMPTY;
94         if (keepLines) {
95             for (AttLineNumberTable lnt = (AttLineNumberTable)
96                      codeAttribs.findFirst(AttLineNumberTable.ATTRIBUTE_NAME);
97                  lnt != null;
98                  lnt = (AttLineNumberTable) codeAttribs.findNext(lnt)) {
99                 lineNumbers = LineNumberList.concat(lineNumbers,
100                         lnt.getLineNumbers());
101             }
102         }
103         this.lineNumbers = lineNumbers;
104
105         LocalVariableList localVariables = LocalVariableList.EMPTY;
106         if (keepLocals) {
107             /*
108              * Do likewise (and with the same caveat) for
109              * LocalVariableTable and LocalVariableTypeTable attributes.
110              * This combines both of these kinds of attribute into a
111              * single LocalVariableList.
112              */
113             for (AttLocalVariableTable lvt = (AttLocalVariableTable)
114                      codeAttribs.findFirst(
115                              AttLocalVariableTable.ATTRIBUTE_NAME);
116                  lvt != null;
117                  lvt = (AttLocalVariableTable) codeAttribs.findNext(lvt)) {
118                 localVariables =
119                     LocalVariableList.concat(localVariables,
120                             lvt.getLocalVariables());
121             }
122
123             LocalVariableList typeList = LocalVariableList.EMPTY;
124             for (AttLocalVariableTypeTable lvtt = (AttLocalVariableTypeTable)
125                      codeAttribs.findFirst(
126                              AttLocalVariableTypeTable.ATTRIBUTE_NAME);
127                  lvtt != null;
128                  lvtt =
129                      (AttLocalVariableTypeTable) codeAttribs.findNext(lvtt)) {
130                 typeList =
131                     LocalVariableList.concat(typeList,
132                             lvtt.getLocalVariables());
133             }
134
135             if (typeList.size() != 0) {
136                 localVariables =
137                     LocalVariableList.mergeDescriptorsAndSignatures(
138                             localVariables, typeList);
139             }
140         }
141         this.localVariables = localVariables;
142     }
143
144     /** {@inheritDoc} */
145     public CstNat getNat() {
146         return method.getNat();
147     }
148
149     /** {@inheritDoc} */
150     public CstUtf8 getName() {
151         return method.getName();
152     }
153
154     /** {@inheritDoc} */
155     public CstUtf8 getDescriptor() {
156         return method.getDescriptor();
157     }
158
159     /** {@inheritDoc} */
160     public int getAccessFlags() {
161         return method.getAccessFlags();
162     }
163
164     /** {@inheritDoc} */
165     public AttributeList getAttributes() {
166         return method.getAttributes();
167     }
168
169     /** {@inheritDoc} */
170     public CstType getDefiningClass() {
171         return method.getDefiningClass();
172     }
173
174     /** {@inheritDoc} */
175     public Prototype getEffectiveDescriptor() {
176         return method.getEffectiveDescriptor();
177     }
178
179     /**
180      * Gets whether the class that this method is part of is defined with
181      * {@code ACC_SUPER}.
182      *
183      * @return the {@code ACC_SUPER} value
184      */
185     public boolean getAccSuper() {
186         return accSuper;
187     }
188
189     /**
190      * Gets the maximum stack size.
191      *
192      * @return {@code >= 0;} the maximum stack size
193      */
194     public int getMaxStack() {
195         return attCode.getMaxStack();
196     }
197
198     /**
199      * Gets the number of locals.
200      *
201      * @return {@code >= 0;} the number of locals
202      */
203     public int getMaxLocals() {
204         return attCode.getMaxLocals();
205     }
206
207     /**
208      * Gets the bytecode array.
209      *
210      * @return {@code non-null;} the bytecode array
211      */
212     public BytecodeArray getCode() {
213         return attCode.getCode();
214     }
215
216     /**
217      * Gets the exception table.
218      *
219      * @return {@code non-null;} the exception table
220      */
221     public ByteCatchList getCatches() {
222         return attCode.getCatches();
223     }
224
225     /**
226      * Gets the line number list.
227      *
228      * @return {@code non-null;} the line number list
229      */
230     public LineNumberList getLineNumbers() {
231         return lineNumbers;
232     }
233
234     /**
235      * Gets the local variable list.
236      *
237      * @return {@code non-null;} the local variable list
238      */
239     public LocalVariableList getLocalVariables() {
240         return localVariables;
241     }
242
243     /**
244      * Returns a {@link SourcePosition} instance corresponding to the
245      * given bytecode offset.
246      *
247      * @param offset {@code >= 0;} the bytecode offset
248      * @return {@code non-null;} an appropriate instance
249      */
250     public SourcePosition makeSourcePosistion(int offset) {
251         return new SourcePosition(sourceFile, offset,
252                                   lineNumbers.pcToLine(offset));
253     }
254 }