001 /* Copyright (c) 2005-2008, Torbjorn Ekman 002 * 2013, Jesper Öqvist <jesper.oqvist@cs.lth.se> 003 * All rights reserved. 004 * 005 * Redistribution and use in source and binary forms, with or without 006 * modification, are permitted provided that the following conditions are met: 007 * 008 * 1. Redistributions of source code must retain the above copyright notice, 009 * this list of conditions and the following disclaimer. 010 * 011 * 2. Redistributions in binary form must reproduce the above copyright notice, 012 * this list of conditions and the following disclaimer in the documentation 013 * and/or other materials provided with the distribution. 014 * 015 * 3. Neither the name of the copyright holder nor the names of its 016 * contributors may be used to endorse or promote products derived from this 017 * software without specific prior written permission. 018 * 019 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 020 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 021 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 022 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 023 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 024 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 025 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 026 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 027 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 028 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 029 * POSSIBILITY OF SUCH DAMAGE. 030 */ 031 032 import java.util.*; 033 import java.io.*; 034 035 aspect ConstantPool { 036 syn lazy ConstantPool TypeDecl.constantPool() = new ConstantPool(this); 037 038 public class ConstantPool { 039 public TypeDecl typeDecl; 040 public ConstantPool(TypeDecl typeDecl) { 041 this.typeDecl = typeDecl; 042 } 043 044 public static final byte CONSTANT_Class = 7; 045 public static final byte CONSTANT_Fieldref = 9; 046 public static final byte CONSTANT_Methodref = 10; 047 public static final byte CONSTANT_InterfaceMethodref = 11; 048 public static final byte CONSTANT_String = 8; 049 public static final byte CONSTANT_Integer = 3; 050 public static final byte CONSTANT_Float = 4; 051 public static final byte CONSTANT_Long = 5; 052 public static final byte CONSTANT_Double = 6; 053 public static final byte CONSTANT_NameAndType = 12; 054 public static final byte CONSTANT_Utf8 = 1; 055 056 private int posCounter = 1; 057 058 private ArrayList list = new ArrayList(); 059 060 private void addCPInfo(CPInfo info) { 061 info.pos = posCounter; 062 posCounter += info.size(); 063 if (posCounter > 0xFFFF) { 064 throw new Error("Too many constants in class!"); 065 } 066 list.add(info); 067 } 068 069 // for debugging purposes 070 public int numElements() { 071 return list.size(); 072 } 073 public String toString() { 074 StringBuffer s = new StringBuffer(); 075 for(Iterator iter = list.iterator(); iter.hasNext(); ) { 076 s.append(iter.next().toString()); 077 s.append("\n"); 078 } 079 return s.toString(); 080 } 081 082 public void emit(DataOutputStream out) throws IOException { 083 out.writeChar(posCounter); 084 for(Iterator iter = list.iterator(); iter.hasNext(); ) { 085 CPInfo info = (CPInfo)iter.next(); 086 info.emit(out); 087 } 088 } 089 090 private int labelCounter = 1; 091 public int newLabel() { 092 return labelCounter++; 093 } 094 095 private HashMap classConstants = new HashMap(); 096 public int addClass(String name) { 097 Map map = classConstants; 098 Object key = name; 099 if(!map.containsKey(key)) { 100 CPInfo info = new ConstantClass(addUtf8(name.replace('.', '/'))); 101 addCPInfo(info); 102 map.put(key, info); 103 String s = info.toString(); 104 return info.pos; 105 } 106 CPInfo info = (CPInfo)map.get(key); 107 return info.pos; 108 } 109 110 private HashMap fieldrefConstants = new HashMap(); 111 public int addFieldref(String classname, String name, String type) { 112 Map map = fieldrefConstants; 113 Object key = classname + name + type; 114 if(!map.containsKey(key)) { 115 CPInfo info = new ConstantFieldref(addClass(classname), addNameAndType(name, type)); 116 addCPInfo(info); 117 map.put(key, info); 118 String s = info.toString(); 119 return info.pos; 120 } 121 CPInfo info = (CPInfo)map.get(key); 122 return info.pos; 123 } 124 125 private HashMap methodrefConstants = new HashMap(); 126 public int addMethodref(String classname, String name, String desc) { 127 Map map = methodrefConstants; 128 Object key = classname + name + desc; 129 if(!map.containsKey(key)) { 130 CPInfo info = new ConstantMethodref(addClass(classname), addNameAndType(name, desc)); 131 addCPInfo(info); 132 map.put(key, info); 133 String s = info.toString(); 134 return info.pos; 135 } 136 CPInfo info = (CPInfo)map.get(key); 137 return info.pos; 138 } 139 140 private HashMap interfaceMethodrefConstants = new HashMap(); 141 public int addInterfaceMethodref(String classname, String name, String desc) { 142 Map map = interfaceMethodrefConstants; 143 Object key = classname + name + desc; 144 if(!map.containsKey(key)) { 145 CPInfo info = new ConstantInterfaceMethodref(addClass(classname), addNameAndType(name, desc)); 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 addCPInfo(info); 162 map.put(key, info); 163 String s = info.toString(); 164 return info.pos; 165 } 166 CPInfo info = (CPInfo)map.get(key); 167 return info.pos; 168 } 169 170 private HashMap utf8Constants = new HashMap(); 171 public int addUtf8(String name) { 172 Map map = utf8Constants; 173 Object key = name; 174 if(!map.containsKey(key)) { 175 CPInfo info = new ConstantUtf8(name); 176 addCPInfo(info); 177 map.put(key, info); 178 String s = info.toString(); 179 return info.pos; 180 } 181 CPInfo info = (CPInfo)map.get(key); 182 return info.pos; 183 } 184 185 private HashMap stringConstants = new HashMap(); 186 187 /** 188 * Add value to constant pool. 189 * @return index of value in constant pool 190 */ 191 public int addConstant(String val) { 192 Map map = stringConstants; 193 Object key = val; 194 if(!map.containsKey(key)) { 195 CPInfo info = new ConstantString(addUtf8(val)); 196 addCPInfo(info); 197 map.put(key, info); 198 String s = info.toString(); 199 return info.pos; 200 } 201 CPInfo info = (CPInfo)map.get(key); 202 return info.pos; 203 } 204 205 private HashMap intConstants = new HashMap(); 206 207 /** 208 * Add value to constant pool. 209 * @return index of value in constant pool 210 */ 211 public int addConstant(int val) { 212 Map map = intConstants; 213 Object key = new Integer(val); 214 if(!map.containsKey(key)) { 215 CPInfo info = new ConstantInteger(val); 216 addCPInfo(info); 217 map.put(key, info); 218 return info.pos; 219 } 220 CPInfo info = (CPInfo)map.get(key); 221 return info.pos; 222 } 223 224 private HashMap floatConstants = new HashMap(); 225 226 /** 227 * Add value to constant pool. 228 * @return index of value in constant pool 229 */ 230 public int addConstant(float val) { 231 Map map = floatConstants; 232 Object key = new Float(val); 233 if(!map.containsKey(key)) { 234 CPInfo info = new ConstantFloat(val); 235 addCPInfo(info); 236 map.put(key, info); 237 return info.pos; 238 } 239 CPInfo info = (CPInfo)map.get(key); 240 return info.pos; 241 } 242 243 private HashMap longConstants = new HashMap(); 244 245 /** 246 * Add value to constant pool. 247 * @return index of value in constant pool 248 */ 249 public int addConstant(long val) { 250 Map map = longConstants; 251 Object key = new Long(val); 252 if(!map.containsKey(key)) { 253 CPInfo info = new ConstantLong(val); 254 addCPInfo(info); 255 map.put(key, info); 256 return info.pos; 257 } 258 CPInfo info = (CPInfo)map.get(key); 259 return info.pos; 260 } 261 262 private HashMap doubleConstants = new HashMap(); 263 264 /** 265 * Add value to constant pool. 266 * @return index of value in constant pool 267 */ 268 public int addConstant(double val) { 269 Map map = doubleConstants; 270 Object key = new Double(val); 271 if(!map.containsKey(key)) { 272 CPInfo info = new ConstantDouble(val); 273 addCPInfo(info); 274 map.put(key, info); 275 return info.pos; 276 } 277 CPInfo info = (CPInfo)map.get(key); 278 return info.pos; 279 } 280 } 281 282 public class CPInfo { 283 public void emit(DataOutputStream out) throws IOException { 284 } 285 public int size() { 286 return 1; 287 } 288 public int pos; 289 } 290 291 public class ConstantClass extends CPInfo { 292 private int name; 293 public ConstantClass(int name) { 294 this.name = name; 295 } 296 public void emit(DataOutputStream out) throws IOException { 297 out.writeByte(ConstantPool.CONSTANT_Class); 298 out.writeChar(name); 299 } 300 public String toString() { 301 return pos + " ConstantClass: tag " + ConstantPool.CONSTANT_Class + ", name_index: " + name; 302 } 303 } 304 305 public class ConstantFieldref extends CPInfo { 306 private int classname; 307 private int nameandtype; 308 public ConstantFieldref(int classname, int nameandtype) { 309 this.classname = classname; 310 this.nameandtype = nameandtype; 311 } 312 public void emit(DataOutputStream out) throws IOException { 313 out.writeByte(ConstantPool.CONSTANT_Fieldref); 314 out.writeChar(classname); 315 out.writeChar(nameandtype); 316 } 317 public String toString() { 318 return pos + " ConstantFieldref: tag " + ConstantPool.CONSTANT_Fieldref + ", class_index: " + classname + ", name_and_type_index: " + nameandtype; 319 } 320 } 321 322 public class ConstantMethodref extends CPInfo { 323 private int classname; 324 private int nameandtype; 325 public ConstantMethodref(int classname, int nameandtype) { 326 this.classname = classname; 327 this.nameandtype = nameandtype; 328 } 329 330 public void emit(DataOutputStream out) throws IOException { 331 out.writeByte(ConstantPool.CONSTANT_Methodref); 332 out.writeChar(classname); 333 out.writeChar(nameandtype); 334 } 335 public String toString() { 336 return pos + " ConstantMethodref: tag " + ConstantPool.CONSTANT_Methodref + ", class_index: " + classname + ", name_and_type_index: " + nameandtype; 337 } 338 } 339 340 public class ConstantInterfaceMethodref extends CPInfo { 341 private int classname; 342 private int nameandtype; 343 public ConstantInterfaceMethodref(int classname, int nameandtype) { 344 this.classname = classname; 345 this.nameandtype = nameandtype; 346 } 347 public void emit(DataOutputStream out) throws IOException { 348 out.writeByte(ConstantPool.CONSTANT_InterfaceMethodref); 349 out.writeChar(classname); 350 out.writeChar(nameandtype); 351 } 352 public String toString() { 353 return pos + " ConstantInterfaceMethodref: tag " + ConstantPool.CONSTANT_InterfaceMethodref + ", class_index: " + classname + ", name_and_type_index: " + nameandtype; 354 } 355 } 356 357 public class ConstantNameAndType extends CPInfo { 358 private int name; 359 private int type; 360 public ConstantNameAndType(int name, int type) { 361 this.name = name; 362 this.type = type; 363 } 364 public void emit(DataOutputStream out) throws IOException { 365 out.writeByte(ConstantPool.CONSTANT_NameAndType); 366 out.writeChar(name); 367 out.writeChar(type); 368 } 369 public String toString() { 370 return pos + " NameAndType: tag " + ConstantPool.CONSTANT_NameAndType + ", name_index: " + name + ", descriptor_index: " + type; 371 } 372 } 373 374 public class ConstantUtf8 extends CPInfo { 375 private String name; 376 public ConstantUtf8(String name) { 377 this.name = name; 378 } 379 public void emit(DataOutputStream out) throws IOException { 380 out.writeByte(ConstantPool.CONSTANT_Utf8); 381 out.writeUTF(name); 382 } 383 public String toString() { 384 return pos + " ConstantUtf8: tag " + ConstantPool.CONSTANT_Utf8 + ", length: " + name.length() + ", bytes: " + name; 385 } 386 } 387 388 public class ConstantString extends CPInfo { 389 private int name; 390 public ConstantString(int name) { 391 this.name = name; 392 } 393 public void emit(DataOutputStream out) throws IOException { 394 out.writeByte(ConstantPool.CONSTANT_String); 395 out.writeChar(name); 396 } 397 public String toString() { 398 return pos + " ConstantString: tag " + ConstantPool.CONSTANT_String + ", string_index: " + name; 399 } 400 } 401 402 public class ConstantInteger extends CPInfo { 403 private int val; 404 public ConstantInteger(int val) { 405 this.val = val; 406 } 407 public void emit(DataOutputStream out) throws IOException { 408 out.writeByte(ConstantPool.CONSTANT_Integer); 409 out.writeInt(val); 410 } 411 public String toString() { 412 return pos + " ConstantInteger: tag " + ConstantPool.CONSTANT_Integer + ", bytes: " + val; 413 } 414 } 415 416 public class ConstantFloat extends CPInfo { 417 private float val; 418 public ConstantFloat(float val) { 419 this.val = val; 420 } 421 public void emit(DataOutputStream out) throws IOException { 422 out.writeByte(ConstantPool.CONSTANT_Float); 423 out.writeFloat(val); 424 } 425 public String toString() { 426 return pos + " ConstantFloat: tag " + ConstantPool.CONSTANT_Float + ", bytes: " + val; 427 } 428 } 429 430 public class ConstantLong extends CPInfo { 431 private long val; 432 public ConstantLong(long val) { 433 this.val = val; 434 } 435 public void emit(DataOutputStream out) throws IOException { 436 out.writeByte(ConstantPool.CONSTANT_Long); 437 out.writeLong(val); 438 } 439 public int size() { 440 return 2; 441 } 442 public String toString() { 443 return pos + " ConstantLong: tag " + ConstantPool.CONSTANT_Long + ", bytes: " + val; 444 } 445 } 446 447 public class ConstantDouble extends CPInfo { 448 private double val; 449 public ConstantDouble(double val) { 450 this.val = val; 451 } 452 public void emit(DataOutputStream out) throws IOException { 453 out.writeByte(ConstantPool.CONSTANT_Double); 454 out.writeDouble(val); 455 } 456 public int size() { 457 return 2; 458 } 459 public String toString() { 460 return pos + " ConstantDouble: tag " + ConstantPool.CONSTANT_Double + ", bytes: " + val; 461 } 462 } 463 464 }