001 /* 002 * The JastAdd Extensible Java Compiler (http://jastadd.org) is covered 003 * by the modified BSD License. You should have received a copy of the 004 * modified BSD license with this compiler. 005 * 006 * Copyright (c) 2005-2008, Torbjorn Ekman 007 * All rights reserved. 008 */ 009 010 import java.util.*; 011 import java.io.*; 012 013 aspect ConstantPool { 014 syn lazy ConstantPool TypeDecl.constantPool() = new ConstantPool(this); 015 016 syn lazy String TypeDecl.constantPoolName() { 017 if(!isNestedType()) { 018 String packageName = packageName(); 019 if(!packageName.equals("")) { 020 packageName = packageName.replace('.', '/') + "/"; 021 } 022 return packageName + name(); 023 } 024 else { 025 String prefix = enclosingType().constantPoolName(); 026 if(isAnonymous()) { 027 return prefix + "$" + uniqueIndex(); 028 } 029 else if(isLocalClass()) { 030 return prefix + "$" + uniqueIndex() + name(); 031 } 032 return prefix + "$" + name(); 033 } 034 } 035 036 syn lazy String ArrayDecl.constantPoolName() = typeDescriptor(); 037 038 public class ConstantPool { 039 public TypeDecl typeDecl; 040 public ConstantPool(TypeDecl typeDecl) { 041 this.typeDecl = typeDecl; 042 //if(!typeDecl.isFinal) 043 // System.out.println("Warning: trying to create constant pool for non final type decl " + typeDecl.fullName()); 044 } 045 046 public static final byte CONSTANT_Class = 7; 047 public static final byte CONSTANT_Fieldref = 9; 048 public static final byte CONSTANT_Methodref = 10; 049 public static final byte CONSTANT_InterfaceMethodref = 11; 050 public static final byte CONSTANT_String = 8; 051 public static final byte CONSTANT_Integer = 3; 052 public static final byte CONSTANT_Float = 4; 053 public static final byte CONSTANT_Long = 5; 054 public static final byte CONSTANT_Double = 6; 055 public static final byte CONSTANT_NameAndType = 12; 056 public static final byte CONSTANT_Utf8 = 1; 057 058 private int posCounter = 1; 059 060 private ArrayList list = new ArrayList(); 061 private void addCPInfo(CPInfo info) { 062 list.add(info); 063 } 064 065 // for debugging purposes 066 public int numElements() { 067 return list.size(); 068 } 069 public String toString() { 070 StringBuffer s = new StringBuffer(); 071 for(Iterator iter = list.iterator(); iter.hasNext(); ) { 072 s.append(iter.next().toString()); 073 s.append("\n"); 074 } 075 return s.toString(); 076 } 077 078 public void emit(DataOutputStream out) throws IOException { 079 out.writeChar(posCounter); 080 for(Iterator iter = list.iterator(); iter.hasNext(); ) { 081 CPInfo info = (CPInfo)iter.next(); 082 info.emit(out); 083 } 084 } 085 086 private int labelCounter = 1; 087 public int newLabel() { 088 return labelCounter++; 089 } 090 091 private HashMap classConstants = new HashMap(); 092 public int addClass(String name) { 093 Map map = classConstants; 094 Object key = name; 095 if(!map.containsKey(key)) { 096 CPInfo info = new ConstantClass(addUtf8(name.replace('.', '/'))); 097 info.pos = posCounter; posCounter += info.size(); 098 addCPInfo(info); 099 map.put(key, info); 100 String s = info.toString(); 101 return info.pos; 102 } 103 CPInfo info = (CPInfo)map.get(key); 104 return info.pos; 105 } 106 107 private HashMap fieldrefConstants = new HashMap(); 108 public int addFieldref(String classname, String name, String type) { 109 Map map = fieldrefConstants; 110 Object key = classname + name + type; 111 if(!map.containsKey(key)) { 112 CPInfo info = new ConstantFieldref(addClass(classname), addNameAndType(name, type)); 113 info.pos = posCounter; posCounter += info.size(); 114 addCPInfo(info); 115 map.put(key, info); 116 String s = info.toString(); 117 return info.pos; 118 } 119 CPInfo info = (CPInfo)map.get(key); 120 return info.pos; 121 } 122 123 private HashMap methodrefConstants = new HashMap(); 124 public int addMethodref(String classname, String name, String desc) { 125 Map map = methodrefConstants; 126 Object key = classname + name + desc; 127 if(!map.containsKey(key)) { 128 CPInfo info = new ConstantMethodref(addClass(classname), addNameAndType(name, desc)); 129 info.pos = posCounter; posCounter += info.size(); 130 addCPInfo(info); 131 map.put(key, info); 132 String s = info.toString(); 133 return info.pos; 134 } 135 CPInfo info = (CPInfo)map.get(key); 136 return info.pos; 137 } 138 139 private HashMap interfaceMethodrefConstants = new HashMap(); 140 public int addInterfaceMethodref(String classname, String name, String desc) { 141 Map map = interfaceMethodrefConstants; 142 Object key = classname + name + desc; 143 if(!map.containsKey(key)) { 144 CPInfo info = new ConstantInterfaceMethodref(addClass(classname), addNameAndType(name, desc)); 145 info.pos = posCounter; posCounter += info.size(); 146 addCPInfo(info); 147 map.put(key, info); 148 String s = info.toString(); 149 return info.pos; 150 } 151 CPInfo info = (CPInfo)map.get(key); 152 return info.pos; 153 } 154 155 private HashMap nameAndTypeConstants = new HashMap(); 156 public int addNameAndType(String name, String type) { 157 Map map = nameAndTypeConstants; 158 Object key = name + type; 159 if(!map.containsKey(key)) { 160 CPInfo info = new ConstantNameAndType(addUtf8(name), addUtf8(type)); 161 info.pos = posCounter; posCounter += info.size(); 162 addCPInfo(info); 163 map.put(key, info); 164 String s = info.toString(); 165 return info.pos; 166 } 167 CPInfo info = (CPInfo)map.get(key); 168 return info.pos; 169 } 170 171 private HashMap utf8Constants = new HashMap(); 172 public int addUtf8(String name) { 173 Map map = utf8Constants; 174 Object key = name; 175 if(!map.containsKey(key)) { 176 CPInfo info = new ConstantUtf8(name); 177 info.pos = posCounter; posCounter += info.size(); 178 addCPInfo(info); 179 map.put(key, info); 180 String s = info.toString(); 181 return info.pos; 182 } 183 CPInfo info = (CPInfo)map.get(key); 184 return info.pos; 185 } 186 187 private HashMap stringConstants = new HashMap(); 188 public int addConstant(String val) { 189 Map map = stringConstants; 190 Object key = val; 191 if(!map.containsKey(key)) { 192 CPInfo info = new ConstantString(addUtf8(val)); 193 info.pos = posCounter; posCounter += info.size(); 194 addCPInfo(info); 195 map.put(key, info); 196 String s = info.toString(); 197 return info.pos; 198 } 199 CPInfo info = (CPInfo)map.get(key); 200 return info.pos; 201 } 202 203 private HashMap intConstants = new HashMap(); 204 public int addConstant(int val) { 205 Map map = intConstants; 206 Object key = new Integer(val); 207 if(!map.containsKey(key)) { 208 CPInfo info = new ConstantInteger(val); 209 info.pos = posCounter; posCounter += info.size(); 210 addCPInfo(info); 211 map.put(key, info); 212 return info.pos; 213 } 214 CPInfo info = (CPInfo)map.get(key); 215 return info.pos; 216 } 217 218 private HashMap floatConstants = new HashMap(); 219 public int addConstant(float val) { 220 Map map = floatConstants; 221 Object key = new Float(val); 222 if(!map.containsKey(key)) { 223 CPInfo info = new ConstantFloat(val); 224 info.pos = posCounter; posCounter += info.size(); 225 addCPInfo(info); 226 map.put(key, info); 227 return info.pos; 228 } 229 CPInfo info = (CPInfo)map.get(key); 230 return info.pos; 231 } 232 233 private HashMap longConstants = new HashMap(); 234 public int addConstant(long val) { 235 Map map = longConstants; 236 Object key = new Long(val); 237 if(!map.containsKey(key)) { 238 CPInfo info = new ConstantLong(val); 239 info.pos = posCounter; posCounter += info.size(); 240 addCPInfo(info); 241 map.put(key, info); 242 return info.pos; 243 } 244 CPInfo info = (CPInfo)map.get(key); 245 return info.pos; 246 } 247 248 private HashMap doubleConstants = new HashMap(); 249 public int addConstant(double val) { 250 Map map = doubleConstants; 251 Object key = new Double(val); 252 if(!map.containsKey(key)) { 253 CPInfo info = new ConstantDouble(val); 254 info.pos = posCounter; posCounter += info.size(); 255 addCPInfo(info); 256 map.put(key, info); 257 return info.pos; 258 } 259 CPInfo info = (CPInfo)map.get(key); 260 return info.pos; 261 } 262 } 263 264 public class CPInfo { 265 public void emit(DataOutputStream out) throws IOException { 266 } 267 public int size() { 268 return 1; 269 } 270 public int pos; 271 } 272 273 public class ConstantClass extends CPInfo { 274 private int name; 275 public ConstantClass(int name) { 276 this.name = name; 277 } 278 public void emit(DataOutputStream out) throws IOException { 279 out.writeByte(ConstantPool.CONSTANT_Class); 280 out.writeChar(name); 281 } 282 public String toString() { 283 return pos + " ConstantClass: tag " + ConstantPool.CONSTANT_Class + ", name_index: " + name; 284 } 285 } 286 287 public class ConstantFieldref extends CPInfo { 288 private int classname; 289 private int nameandtype; 290 public ConstantFieldref(int classname, int nameandtype) { 291 this.classname = classname; 292 this.nameandtype = nameandtype; 293 } 294 public void emit(DataOutputStream out) throws IOException { 295 out.writeByte(ConstantPool.CONSTANT_Fieldref); 296 out.writeChar(classname); 297 out.writeChar(nameandtype); 298 } 299 public String toString() { 300 return pos + " ConstantFieldref: tag " + ConstantPool.CONSTANT_Fieldref + ", class_index: " + classname + ", name_and_type_index: " + nameandtype; 301 } 302 } 303 304 public class ConstantMethodref extends CPInfo { 305 private int classname; 306 private int nameandtype; 307 public ConstantMethodref(int classname, int nameandtype) { 308 this.classname = classname; 309 this.nameandtype = nameandtype; 310 } 311 312 public void emit(DataOutputStream out) throws IOException { 313 out.writeByte(ConstantPool.CONSTANT_Methodref); 314 out.writeChar(classname); 315 out.writeChar(nameandtype); 316 } 317 public String toString() { 318 return pos + " ConstantMethodref: tag " + ConstantPool.CONSTANT_Methodref + ", class_index: " + classname + ", name_and_type_index: " + nameandtype; 319 } 320 } 321 322 public class ConstantInterfaceMethodref extends CPInfo { 323 private int classname; 324 private int nameandtype; 325 public ConstantInterfaceMethodref(int classname, int nameandtype) { 326 this.classname = classname; 327 this.nameandtype = nameandtype; 328 } 329 public void emit(DataOutputStream out) throws IOException { 330 out.writeByte(ConstantPool.CONSTANT_InterfaceMethodref); 331 out.writeChar(classname); 332 out.writeChar(nameandtype); 333 } 334 public String toString() { 335 return pos + " ConstantInterfaceMethodref: tag " + ConstantPool.CONSTANT_InterfaceMethodref + ", class_index: " + classname + ", name_and_type_index: " + nameandtype; 336 } 337 } 338 339 public class ConstantNameAndType extends CPInfo { 340 private int name; 341 private int type; 342 public ConstantNameAndType(int name, int type) { 343 this.name = name; 344 this.type = type; 345 } 346 public void emit(DataOutputStream out) throws IOException { 347 out.writeByte(ConstantPool.CONSTANT_NameAndType); 348 out.writeChar(name); 349 out.writeChar(type); 350 } 351 public String toString() { 352 return pos + " NameAndType: tag " + ConstantPool.CONSTANT_NameAndType + ", name_index: " + name + ", descriptor_index: " + type; 353 } 354 } 355 356 public class ConstantUtf8 extends CPInfo { 357 private String name; 358 public ConstantUtf8(String name) { 359 this.name = name; 360 } 361 public void emit(DataOutputStream out) throws IOException { 362 out.writeByte(ConstantPool.CONSTANT_Utf8); 363 out.writeUTF(name); 364 } 365 public String toString() { 366 return pos + " ConstantUtf8: tag " + ConstantPool.CONSTANT_Utf8 + ", length: " + name.length() + ", bytes: " + name; 367 } 368 } 369 370 public class ConstantString extends CPInfo { 371 private int name; 372 public ConstantString(int name) { 373 this.name = name; 374 } 375 public void emit(DataOutputStream out) throws IOException { 376 out.writeByte(ConstantPool.CONSTANT_String); 377 out.writeChar(name); 378 } 379 public String toString() { 380 return pos + " ConstantString: tag " + ConstantPool.CONSTANT_String + ", string_index: " + name; 381 } 382 } 383 384 public class ConstantInteger extends CPInfo { 385 private int val; 386 public ConstantInteger(int val) { 387 this.val = val; 388 } 389 public void emit(DataOutputStream out) throws IOException { 390 out.writeByte(ConstantPool.CONSTANT_Integer); 391 out.writeInt(val); 392 } 393 public String toString() { 394 return pos + " ConstantInteger: tag " + ConstantPool.CONSTANT_Integer + ", bytes: " + val; 395 } 396 } 397 398 public class ConstantFloat extends CPInfo { 399 private float val; 400 public ConstantFloat(float val) { 401 this.val = val; 402 } 403 public void emit(DataOutputStream out) throws IOException { 404 out.writeByte(ConstantPool.CONSTANT_Float); 405 out.writeFloat(val); 406 } 407 public String toString() { 408 return pos + " ConstantFloat: tag " + ConstantPool.CONSTANT_Float + ", bytes: " + val; 409 } 410 } 411 412 public class ConstantLong extends CPInfo { 413 private long val; 414 public ConstantLong(long val) { 415 this.val = val; 416 } 417 public void emit(DataOutputStream out) throws IOException { 418 out.writeByte(ConstantPool.CONSTANT_Long); 419 out.writeLong(val); 420 } 421 public int size() { 422 return 2; 423 } 424 public String toString() { 425 return pos + " ConstantLong: tag " + ConstantPool.CONSTANT_Long + ", bytes: " + val; 426 } 427 } 428 429 public class ConstantDouble extends CPInfo { 430 private double val; 431 public ConstantDouble(double val) { 432 this.val = val; 433 } 434 public void emit(DataOutputStream out) throws IOException { 435 out.writeByte(ConstantPool.CONSTANT_Double); 436 out.writeDouble(val); 437 } 438 public int size() { 439 return 2; 440 } 441 public String toString() { 442 return pos + " ConstantDouble: tag " + ConstantPool.CONSTANT_Double + ", bytes: " + val; 443 } 444 } 445 446 }