1 29 30 package com.caucho.bytecode; 31 32 import com.caucho.log.Log; 33 import com.caucho.vfs.TempBuffer; 34 import com.caucho.vfs.TempStream; 35 import com.caucho.vfs.WriteStream; 36 37 import java.io.IOException ; 38 import java.util.ArrayList ; 39 import java.util.logging.Logger ; 40 41 44 public class CodeAttribute extends Attribute { 45 static private final Logger log = Log.open(CodeAttribute.class); 46 47 private int _maxStack; 48 private int _maxLocals; 49 private byte []_code; 50 private ArrayList <ExceptionItem> _exceptions = 51 new ArrayList <ExceptionItem>(); 52 53 private ArrayList <Attribute> _attributes = new ArrayList <Attribute>(); 54 55 public CodeAttribute() 56 { 57 super("Code"); 58 } 59 60 CodeAttribute(String name) 61 { 62 super(name); 63 } 64 65 68 public int getMaxLocals() 69 { 70 return _maxLocals; 71 } 72 73 76 public void setMaxLocals(int max) 77 { 78 _maxLocals = max; 79 } 80 81 84 public int getMaxStack() 85 { 86 return _maxStack; 87 } 88 89 92 public void setMaxStack(int max) 93 { 94 _maxStack = max; 95 } 96 97 100 public void setCode(byte []code) 101 { 102 _code = code; 103 } 104 105 108 public byte []getCode() 109 { 110 return _code; 111 } 112 113 116 public void addAttribute(Attribute attr) 117 { 118 _attributes.add(attr); 119 } 120 121 124 public ArrayList <Attribute> getAttributes() 125 { 126 return _attributes; 127 } 128 129 132 public void setAttributes(ArrayList <Attribute> attributes) 133 { 134 if (_attributes != attributes) { 135 _attributes.clear(); 136 _attributes.addAll(attributes); 137 } 138 } 139 140 143 public Attribute removeAttribute(String name) 144 { 145 for (int i = _attributes.size() - 1; i >= 0; i--) { 146 Attribute attr = _attributes.get(i); 147 148 if (attr.getName().equals(name)) { 149 _attributes.remove(i); 150 return attr; 151 } 152 } 153 154 return null; 155 } 156 157 160 public ArrayList <ExceptionItem> getExceptions() 161 { 162 return _exceptions; 163 } 164 165 168 public void addException(ClassConstant type, int start, int end, int handler) 169 { 170 _exceptions.add(new ExceptionItem(type.getIndex(), start, end, handler)); 171 } 172 173 176 public void read(ByteCodeParser in) 177 throws IOException 178 { 179 int length = in.readInt(); 180 181 _maxStack = in.readShort(); 182 _maxLocals = in.readShort(); 183 184 int codeLength = in.readInt(); 185 186 _code = new byte[codeLength]; 187 in.read(_code, 0, codeLength); 188 189 int exnCount = in.readShort(); 190 191 for (int i = 0; i < exnCount; i++) { 192 ExceptionItem exn = new ExceptionItem(); 193 194 exn.setStart(in.readShort() & 0xffff); 195 exn.setEnd(in.readShort() & 0xffff); 196 exn.setHandler(in.readShort() & 0xffff); 197 exn.setType(in.readShort() & 0xffff); 198 199 _exceptions.add(exn); 200 } 201 202 int attrCount = in.readShort(); 203 204 for (int i = 0; i < attrCount; i++) { 205 Attribute attr = in.parseAttribute(); 206 207 _attributes.add(attr); 208 } 209 } 210 211 214 public void write(ByteCodeWriter out) 215 throws IOException 216 { 217 out.writeUTF8Const(getName()); 218 219 TempStream ts = new TempStream(); 220 ts.openWrite(); 221 WriteStream ws = new WriteStream(ts); 222 ByteCodeWriter o2 = new ByteCodeWriter(ws, out.getJavaClass()); 223 224 o2.writeShort(_maxStack); 225 o2.writeShort(_maxLocals); 226 o2.writeInt(_code.length); 227 o2.write(_code, 0, _code.length); 228 229 o2.writeShort(_exceptions.size()); 230 for (int i = 0; i < _exceptions.size(); i++) { 231 ExceptionItem exn = _exceptions.get(i); 232 233 o2.writeShort(exn.getStart()); 234 o2.writeShort(exn.getEnd()); 235 o2.writeShort(exn.getHandler()); 236 o2.writeShort(exn.getType()); 237 } 238 239 o2.writeShort(_attributes.size()); 240 for (int i = 0; i < _attributes.size(); i++) { 241 Attribute attr = _attributes.get(i); 242 243 attr.write(o2); 244 } 245 246 ws.close(); 247 248 out.writeInt(ts.getLength()); 249 TempBuffer ptr = ts.getHead(); 250 251 for (; ptr != null; ptr = ptr.getNext()) 252 out.write(ptr.getBuffer(), 0, ptr.getLength()); 253 254 ts.destroy(); 255 } 256 257 260 public Attribute export(JavaClass source, JavaClass target) 261 { 262 ConstantPool cp = target.getConstantPool(); 263 264 cp.addUTF8(getName()); 265 266 CodeAttribute attr = new CodeAttribute(getName()); 267 268 attr._maxStack = _maxStack; 269 attr._maxLocals = _maxLocals; 270 271 byte []code = new byte[_code.length]; 272 System.arraycopy(_code, 0, code, 0, _code.length); 273 attr._code = code; 274 275 for (int i = 0; i < _exceptions.size(); i++) { 276 ExceptionItem exn = _exceptions.get(i); 277 278 int type = exn.getType(); 279 280 if (type != 0) 281 type = cp.addClass(source.getConstantPool().getClass(type).getName()).getIndex(); 282 283 ExceptionItem newExn = new ExceptionItem(type, 284 exn.getStart(), 285 exn.getEnd(), 286 exn.getHandler()); 287 288 attr._exceptions.add(newExn); 289 } 290 291 for (int i = 0; i < _attributes.size(); i++) { 292 Attribute codeAttr = _attributes.get(i); 293 294 attr.addAttribute(codeAttr.export(source, target)); 295 } 296 297 try { 298 attr.exportCode(source, target); 299 } catch (Exception e) { 300 throw new RuntimeException (e); 301 } 302 303 return attr; 304 } 305 306 309 public void exportCode(JavaClass source, JavaClass target) 310 throws Exception 311 { 312 ExportAnalyzer analyzer = new ExportAnalyzer(source, target); 313 314 CodeEnhancer visitor = new CodeEnhancer(source, this); 315 316 visitor.analyze(analyzer, false); 317 318 visitor.update(); 319 } 320 321 public String toString() 322 { 323 return "CodeAttribute[" + getName() + "]"; 324 } 325 326 public static class ExceptionItem { 327 private int _type; 328 329 private int _start; 330 private int _end; 331 private int _handler; 332 333 public ExceptionItem() 334 { 335 } 336 337 public ExceptionItem(int type, int start, int end, int handler) 338 { 339 _type = type; 340 _start = start; 341 _end = end; 342 _handler = handler; 343 } 344 345 348 public void setType(int type) 349 { 350 _type = type; 351 } 352 353 356 public int getType() 357 { 358 return _type; 359 } 360 361 364 public void setStart(int pc) 365 { 366 _start = pc; 367 } 368 369 372 public int getStart() 373 { 374 return _start; 375 } 376 377 380 public void setEnd(int pc) 381 { 382 _end = pc; 383 } 384 385 388 public int getEnd() 389 { 390 return _end; 391 } 392 393 396 public void setHandler(int pc) 397 { 398 _handler = pc; 399 } 400 401 404 public int getHandler() 405 { 406 return _handler; 407 } 408 } 409 410 public static class ExportAnalyzer extends Analyzer { 411 private JavaClass _source; 412 private JavaClass _target; 413 414 public ExportAnalyzer(JavaClass source, JavaClass target) 415 { 416 _source = source; 417 _target = target; 418 } 419 420 public void analyze(CodeVisitor visitor) 421 throws Exception 422 { 423 int op = visitor.getOpcode(); 424 int index; 425 ConstantPool sourcePool = _source.getConstantPool(); 426 ConstantPool targetPool = _target.getConstantPool(); 427 ConstantPoolEntry entry; 428 429 switch (op) { 430 case CodeVisitor.ANEWARRAY: 431 case CodeVisitor.CHECKCAST: 432 case CodeVisitor.GETFIELD: 433 case CodeVisitor.GETSTATIC: 434 case CodeVisitor.INSTANCEOF: 435 case CodeVisitor.INVOKEINTERFACE: 436 case CodeVisitor.INVOKESPECIAL: 437 case CodeVisitor.INVOKESTATIC: 438 case CodeVisitor.INVOKEVIRTUAL: 439 case CodeVisitor.LDC_W: 440 case CodeVisitor.LDC2_W: 441 case CodeVisitor.MULTIANEWARRAY: 442 case CodeVisitor.NEW: 443 case CodeVisitor.PUTFIELD: 444 case CodeVisitor.PUTSTATIC: 445 index = visitor.getShortArg(1); 446 447 entry = sourcePool.getEntry(index); 448 int targetIndex = entry.export(targetPool); 449 450 visitor.setShortArg(1, targetIndex); 451 break; 452 453 case CodeVisitor.LDC: 454 index = visitor.getByteArg(1); 455 entry = sourcePool.getEntry(index); 456 index = entry.export(targetPool); 457 if (index <= 0xff) 458 visitor.setByteArg(1, index); 459 else { 460 CodeEnhancer enhancer = (CodeEnhancer) visitor; 461 enhancer.setByteArg(0, CodeVisitor.LDC_W); 462 enhancer.addByte(enhancer.getOffset() + 2, 0); 463 enhancer.setShortArg(1, index); 464 } 465 break; 466 467 default: 468 break; 469 } 470 } 471 } 472 } 473 | Popular Tags |