1 /*
2 * Copyright (c) 1996, 2014, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation.
8 *
9 * This code is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
12 * version 2 for more details (a copy is included in the LICENSE file that
13 * accompanied this code).
14 *
15 * You should have received a copy of the GNU General Public License version
16 * 2 along with this work; if not, write to the Free Software Foundation,
17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18 *
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20 * or visit www.oracle.com if you need additional information or have any
21 * questions.
22 */
23 package org.openjdk.asmtools.jasm;
24
25 import org.openjdk.asmtools.jasm.Tables.AttrTag;
26 import org.openjdk.asmtools.jasm.ConstantPool.ConstCell;
27 import java.io.IOException;
28 import java.util.ArrayList;
29 import java.util.List;
30 import java.util.TreeMap;
31
32 /**
33 *
34 */
35 class MethodData extends MemberData {
36
37 /**
38 * MethodParamData
39 */
40 class ParamNameData implements Data {
41
42 int access;
43 ConstCell name;
44
45 public ParamNameData(int access, ConstCell name) {
46 this.access = access;
47 this.name = name;
48 }
49
50 @Override
51 public int getLength() {
52 return 4;
53 }
54
55 @Override
56 public void write(CheckedDataOutputStream out) throws IOException {
57 int nm = 0;
58 int ac = 0;
59 if (name != null) {
60 nm = name.arg;
61 ac = access;
62 }
63 out.writeShort(nm);
64 out.writeShort(ac);
65 }
66 }// end class MethodParamData
67
68 /**
69 * Used to store Parameter Arrays (as attributes)
70 */
71 static public class DataPArrayAttr<T extends Data> extends AttrData implements Constants {
72
73 TreeMap<Integer, ArrayList<T>> elements; // Data
74 int paramsTotal;
75
76 public DataPArrayAttr(ClassData cls, String name, int paramsTotal, TreeMap<Integer, ArrayList<T>> elements) {
77 super(cls, name);
78 this.paramsTotal = paramsTotal;
79 this.elements = elements;
80 }
81
82 public DataPArrayAttr(ClassData cls, String name, int paramsTotal) {
83 this(cls, name, paramsTotal, new TreeMap<Integer, ArrayList<T>>());
84 }
85
86 public void put(int paramNum, T element) {
87 ArrayList<T> v = get(paramNum);
88 if (v == null) {
89 v = new ArrayList<>();
90 elements.put(paramNum, v);
91 }
92
93 v.add(element);
94 }
95
96 public ArrayList<T> get(int paramNum) {
97 return elements.get(paramNum);
98 }
99
100 @Override
101 public int attrLength() {
102 int length = 1; // One byte for the parameter count
103
104 // calculate overall size here rather than in add()
105 // because it may not be available at the time of invoking of add()
106 for (int i = 0; i < paramsTotal; i++) {
107 ArrayList<T> attrarray = get(i);
108 if (attrarray != null) {
109 for (Data item : attrarray) {
110 length += item.getLength();
111 }
112 }
113 length += 2; // 2 bytes for the annotation count for each parameter
114 }
115
116 return length;
117 }
118
119 @Override
120 public void write(CheckedDataOutputStream out) throws IOException {
121 super.write(out); // attr name, attr len
122 out.writeByte(paramsTotal); // number of parameters total (in byte)
123
124 for (int i = 0; i < paramsTotal; i++) {
125 ArrayList<T> attrarray = get(i);
126 if (attrarray != null) {
127 // write out the number of annotations for the current param
128 out.writeShort(attrarray.size());
129 for (T item : attrarray) {
130 item.write(out); // write the current annotation
131 }
132 } else {
133 out.writeShort(0);
134 // No annotations to write out
135 }
136 }
137 }
138 }// end class DataPArrayAttr
139
140
141 /* Method Data Fields */
142 protected Environment env;
143 protected ConstCell nameCell, sigCell;
144 protected CodeAttr code;
145 protected DataVectorAttr<ConstCell> exceptions = null;
146 protected DataVectorAttr<ParamNameData> paramNames = null;
147 protected DataPArrayAttr<AnnotationData> pannotAttrVis = null;
148 protected DataPArrayAttr<AnnotationData> pannotAttrInv = null;
149 protected DefaultAnnotationAttr defaultAnnot = null;
150
151 public MethodData(ClassData cls, int acc,
152 ConstCell name, ConstCell sig, ArrayList<ConstCell> exc_table) {
153 super(cls, acc);
154 this.env = cls.env;
155 nameCell = name;
156 sigCell = sig;
157 if ((exc_table != null) && (!exc_table.isEmpty())) {
158 exceptions = new DataVectorAttr<>(cls,
159 AttrTag.ATT_Exceptions.parsekey(),
160 exc_table);
161 }
162 // Normalize the modifiers to access flags
163 if (Modifiers.hasPseudoMod(acc)) {
164 createPseudoMod();
165 }
166 }
167
168 public void addMethodParameter(int totalParams, int paramNum, ConstCell name, int access) {
169 env.traceln("addMethodParameter Param[" + paramNum + "] (name: " + name.toString() + ", Flags (" + access + ").");
170 if (paramNames == null) {
171 paramNames = new DataVectorAttr<>(cls, AttrTag.ATT_MethodParameters.parsekey(), true);
172 for (int i = 0; i < totalParams; i++) {
173 // initialize the paramName array (in case the name is not given in Jasm syntax)
174 paramNames.add(new ParamNameData(0, null));
175 }
176 }
177 paramNames.put(paramNum, new ParamNameData(access, name));
178 }
179
180 public CodeAttr startCode(int pos, int paramcnt, Argument max_stack, Argument max_locals) {
181 code = new CodeAttr(this, pos, paramcnt, max_stack, max_locals);
182 return code;
183 }
184
185 public void addDefaultAnnotation(DefaultAnnotationAttr data) {
186 defaultAnnot = data;
187 }
188
189 public void addParamAnnotation(int totalParams, int paramNum, AnnotationData data) {
190 if (!data.invisible) {
191 if (pannotAttrVis == null) {
192 pannotAttrVis = new DataPArrayAttr<>(cls,
193 AttrTag.ATT_RuntimeVisibleParameterAnnotations.parsekey(),
194 totalParams);
195 }
196 pannotAttrVis.put(paramNum, data);
197
198 } else {
199 if (pannotAttrInv == null) {
200 pannotAttrInv = new DataPArrayAttr<>(cls,
201 AttrTag.ATT_RuntimeInvisibleParameterAnnotations.parsekey(),
202 totalParams);
203 }
204 pannotAttrInv.put(paramNum, data);
205 }
206 }
207
208 @Override
209 protected DataVector getAttrVector() {
210 DataVector dv = getDataVector( exceptions, syntheticAttr, deprecatedAttr, paramNames, code, defaultAnnot);
211 if (pannotAttrVis != null) {
212 dv.add(pannotAttrVis);
213 }
214 if (pannotAttrInv != null) {
215 dv.add(pannotAttrInv);
216 }
217 return dv;
218 }
219
220 /*====================================================== Write */
221 public void write(CheckedDataOutputStream out) throws IOException, Parser.CompilerError {
222 out.writeShort(access);
223 out.writeShort(nameCell.arg);
224 out.writeShort(sigCell.arg);
225 getAttrVector().write(out);
226 }
227 } // end MethodData
228