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