2 * Copyright (C) 2007 The Android Open Source Project
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
17 package com.android.dx.cf.code;
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;
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.
40 public final class ConcreteMethod implements Method {
41 /** {@code non-null;} method being wrapped */
42 private final Method method;
45 * {@code null-ok;} the class's {@code SourceFile} attribute value,
48 private final CstUtf8 sourceFile;
51 * whether the class that this method is part of is defined with
54 private final boolean accSuper;
56 /** {@code non-null;} the code attribute */
57 private final AttCode attCode;
59 /** {@code non-null;} line number list */
60 private final LineNumberList lineNumbers;
62 /** {@code non-null;} local variable list */
63 private final LocalVariableList localVariables;
66 * Constructs an instance.
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
72 * @param keepLocals whether to keep the local variable
73 * information (if any)
75 public ConcreteMethod(Method method, ClassFile cf, boolean keepLines,
78 this.accSuper = (cf.getAccessFlags() & AccessFlags.ACC_SUPER) != 0;
79 this.sourceFile = cf.getSourceFile();
81 AttributeList attribs = method.getAttributes();
82 this.attCode = (AttCode) attribs.findFirst(AttCode.ATTRIBUTE_NAME);
84 AttributeList codeAttribs = attCode.getAttributes();
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.
93 LineNumberList lineNumbers = LineNumberList.EMPTY;
95 for (AttLineNumberTable lnt = (AttLineNumberTable)
96 codeAttribs.findFirst(AttLineNumberTable.ATTRIBUTE_NAME);
98 lnt = (AttLineNumberTable) codeAttribs.findNext(lnt)) {
99 lineNumbers = LineNumberList.concat(lineNumbers,
100 lnt.getLineNumbers());
103 this.lineNumbers = lineNumbers;
105 LocalVariableList localVariables = LocalVariableList.EMPTY;
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.
113 for (AttLocalVariableTable lvt = (AttLocalVariableTable)
114 codeAttribs.findFirst(
115 AttLocalVariableTable.ATTRIBUTE_NAME);
117 lvt = (AttLocalVariableTable) codeAttribs.findNext(lvt)) {
119 LocalVariableList.concat(localVariables,
120 lvt.getLocalVariables());
123 LocalVariableList typeList = LocalVariableList.EMPTY;
124 for (AttLocalVariableTypeTable lvtt = (AttLocalVariableTypeTable)
125 codeAttribs.findFirst(
126 AttLocalVariableTypeTable.ATTRIBUTE_NAME);
129 (AttLocalVariableTypeTable) codeAttribs.findNext(lvtt)) {
131 LocalVariableList.concat(typeList,
132 lvtt.getLocalVariables());
135 if (typeList.size() != 0) {
137 LocalVariableList.mergeDescriptorsAndSignatures(
138 localVariables, typeList);
141 this.localVariables = localVariables;
145 public CstNat getNat() {
146 return method.getNat();
150 public CstUtf8 getName() {
151 return method.getName();
155 public CstUtf8 getDescriptor() {
156 return method.getDescriptor();
160 public int getAccessFlags() {
161 return method.getAccessFlags();
165 public AttributeList getAttributes() {
166 return method.getAttributes();
170 public CstType getDefiningClass() {
171 return method.getDefiningClass();
175 public Prototype getEffectiveDescriptor() {
176 return method.getEffectiveDescriptor();
180 * Gets whether the class that this method is part of is defined with
183 * @return the {@code ACC_SUPER} value
185 public boolean getAccSuper() {
190 * Gets the maximum stack size.
192 * @return {@code >= 0;} the maximum stack size
194 public int getMaxStack() {
195 return attCode.getMaxStack();
199 * Gets the number of locals.
201 * @return {@code >= 0;} the number of locals
203 public int getMaxLocals() {
204 return attCode.getMaxLocals();
208 * Gets the bytecode array.
210 * @return {@code non-null;} the bytecode array
212 public BytecodeArray getCode() {
213 return attCode.getCode();
217 * Gets the exception table.
219 * @return {@code non-null;} the exception table
221 public ByteCatchList getCatches() {
222 return attCode.getCatches();
226 * Gets the line number list.
228 * @return {@code non-null;} the line number list
230 public LineNumberList getLineNumbers() {
235 * Gets the local variable list.
237 * @return {@code non-null;} the local variable list
239 public LocalVariableList getLocalVariables() {
240 return localVariables;
244 * Returns a {@link SourcePosition} instance corresponding to the
245 * given bytecode offset.
247 * @param offset {@code >= 0;} the bytecode offset
248 * @return {@code non-null;} an appropriate instance
250 public SourcePosition makeSourcePosistion(int offset) {
251 return new SourcePosition(sourceFile, offset,
252 lineNumbers.pcToLine(offset));