1 package alt.jiapi.util; 2 3 import java.lang.reflect.Modifier ; 4 5 import alt.jiapi.InstrumentationDescriptor; 6 import alt.jiapi.InstrumentationException; 7 import alt.jiapi.MethodInstrumentor; 8 import alt.jiapi.Rule; 9 import alt.jiapi.reflect.BranchInstruction; 10 import alt.jiapi.reflect.Instruction; 11 import alt.jiapi.reflect.InstructionFactory; 12 import alt.jiapi.reflect.InstructionList; 13 import alt.jiapi.reflect.JiapiClass; 14 import alt.jiapi.reflect.JiapiMethod; 15 import alt.jiapi.reflect.Loader; 16 import alt.jiapi.reflect.Signature; 17 import alt.jiapi.reflect.instruction.Invocation; 18 import alt.jiapi.reflect.instruction.OpcodeGroups; 19 import alt.jiapi.reflect.instruction.Opcodes; 20 21 import org.apache.log4j.Category; 22 23 49 public class HotSpotAdvisor { 50 private static Category log = Category.getInstance(HotSpotAdvisor.class); 51 65 public static final byte[] INVOCATIONS = OpcodeGroups.INVOKE_INSTRUCTIONS; 66 70 public static final byte[] RETURNS = OpcodeGroups.RETURN_INSTRUCTIONS; 71 75 public static final byte[] FIELD_ACCESSES = OpcodeGroups.FIELD_ACCESS_INSTRUCTIONS; 76 77 90 public HotSpotAdvisor(InstrumentationDescriptor id, 91 HotSpotAdvice advice, 92 byte hotSpot) { 93 this(id, advice, new byte[] {hotSpot}); 94 } 95 96 114 public HotSpotAdvisor(InstrumentationDescriptor id, 115 HotSpotAdvice advice, 116 byte[] hotSpots) { 117 this(id, advice, hotSpots, "*"); 118 } 119 120 121 139 public HotSpotAdvisor(InstrumentationDescriptor id, 140 HotSpotAdvice advice, 141 byte[] hotSpots, String resolution) { 142 try { 143 id.addExclusionRule(advice.getClass().getName()); 148 } 149 catch(Exception e) { 150 } 151 152 id.addInstrumentor(new HSInstrumentor(advice, hotSpots, resolution)); 153 } 154 155 156 160 private class HSInstrumentor extends MethodInstrumentor { 161 private byte[] hotSpots; 162 private JiapiMethod adviceMethod; 163 private Rule rule; 164 165 HSInstrumentor(HotSpotAdvice advice, byte[] hotSpots, String resolution) { 166 try { 167 this.rule = new Rule(resolution); 168 Loader l = new Loader(); 169 log.debug("Loading advice " + advice.getClass().getName()); 170 JiapiClass clazz = l.loadClass(advice.getClass().getName()); 171 172 log.debug("Getting advice() method "); 173 this.adviceMethod = 174 clazz.getDeclaredMethod("advice", new String [0]); 175 this.hotSpots = hotSpots; 176 } 177 catch(NoSuchMethodException nsme) { 178 log.error("Internal error: Could not find HotSpotAdvice.advice() method", nsme); 181 throw new InstrumentationException("Could not find method advice() from " + advice.getClass() + ": " + nsme); 182 } 183 catch(ClassNotFoundException cnfe) { 184 log.error("Internal error: Could load class HotSpotAdvice", cnfe); 187 188 throw new InstrumentationException("Could not load class " + advice.getClass() + ": " + cnfe); 189 } 190 catch(java.io.IOException ioe) { 191 log.error("Internal error: Could load class HotSpotAdvice", ioe); 193 194 throw new InstrumentationException("Could not load class " + advice.getClass() + ": " + ioe); 195 } 196 catch(Exception e) { 197 log.error("Failed to initialize HotSpotAdvisor", e); 198 199 throw new InstrumentationException("Failed to initialize HotSpotAdvisor: " + e); 200 } 201 } 202 203 207 public void instrument(JiapiMethod m) throws InstrumentationException { 208 log.debug("Instrumenting " + m.getDeclaringClass().getName() + 209 "#" + m); 210 211 HotSpotLocator hsl = 212 new HotSpotLocator(m.getInstructionList(), hotSpots); 213 214 HotSpot[] hsa = hsl.getHotSpots(); 215 for (int i = 0; i < hsa.length; i++) { 216 HotSpot hs = hsa[i]; 217 if (rule.match(hs.getName())) { 218 copyInstructions(hs); 219 } 220 } 221 } 222 223 226 private void copyInstructions(HotSpot hs) { 227 InstructionList am_il = adviceMethod.getInstructionList(); 228 InstructionList il = hs.getInstructionList(); 229 Instruction firstHotSpotInstruction = il.get(0); 230 231 am_il = changeLocalVars(am_il, il.getDeclaringMethod().getMaxLocals()-1); 235 236 int idx = indexOfDoHotSpot(); 237 238 if (idx == -1) { 239 log.debug("Replacing hotspot with advice-method"); 240 il.clear(); 241 il.add(am_il); 242 return; 243 } 244 else { 245 InstructionList before = am_il.createView(0, idx - 1); 246 247 if (before.size() > 0) { 251 checkForBranchTarget(firstHotSpotInstruction, il.getDeclaringMethod().getInstructionList(), before.get(0)); 252 } 253 254 InstructionList after = null; 255 if (idx+1 < am_il.size()) { 256 after = am_il.createView(idx + 1, am_il.size() - 1); 258 } 259 260 261 il.insert(0, before); 263 if (after != null) { 264 il.add(after); 265 } 266 } 267 268 269 processAdviceTriggers(il, hs); 271 } 272 273 274 287 private int indexOfDoHotSpot() { 288 InstructionList il = adviceMethod.getInstructionList(); 289 HotSpotLocator hsl = new HotSpotLocator(il, Opcodes.INVOKEVIRTUAL); 290 291 HotSpot[] dohsCandidates = hsl.getHotSpots(); 292 for (int i = 0; i < dohsCandidates.length; i++) { 293 Invocation inv = 294 (Invocation)dohsCandidates[i].getHotSpotInstruction(); 295 296 if (!inv.getClassName().equals(adviceMethod.getDeclaringClass().getName())) { 297 continue; 299 } 300 301 if ("doHotSpot".equals(inv.getMethodName())) { 302 return il.indexOf(inv); 308 } 309 } 310 311 return -1; 312 } 313 314 315 327 private InstructionList changeLocalVars(InstructionList advice, 328 int maxLocalsInOtherList) { 329 335 maxLocalsInOtherList--; 340 345 InstructionList newList = new InstructionList(); 346 347 InstructionFactory factory = new InstructionFactory(); 348 for(int i = 0; i < advice.size(); i++) { 349 Instruction ins = advice.get(i); 350 newList.add(ins); 351 switch(ins.getOpcode()) { 352 case Opcodes.ALOAD_0: 354 newList.replace(i, factory.aload(maxLocalsInOtherList)); 355 break; 356 case Opcodes.ALOAD_1: 357 newList.replace(i, factory.aload(maxLocalsInOtherList + 1)); 358 break; 359 case Opcodes.ALOAD_2: 360 newList.replace(i, factory.aload(maxLocalsInOtherList + 2)); 361 break; 362 case Opcodes.ALOAD_3: 363 newList.replace(i, factory.aload(maxLocalsInOtherList + 3)); 364 break; 365 case Opcodes.ALOAD: 366 ins.getBytes()[1] += (byte)maxLocalsInOtherList; 370 break; 371 case Opcodes.ASTORE_0: 372 newList.replace(i, factory.astore(maxLocalsInOtherList)); 373 break; 374 case Opcodes.ASTORE_1: 375 newList.replace(i, factory.astore(maxLocalsInOtherList + 1)); 376 break; 377 case Opcodes.ASTORE_2: 378 newList.replace(i, factory.astore(maxLocalsInOtherList + 2)); 379 break; 380 case Opcodes.ASTORE_3: 381 newList.replace(i, factory.astore(maxLocalsInOtherList + 3)); 382 break; 383 case Opcodes.ASTORE: 384 ins.getBytes()[1] += (byte)maxLocalsInOtherList; 388 break; 389 390 case Opcodes.ILOAD_0: 392 newList.replace(i, factory.iload(maxLocalsInOtherList)); 393 break; 394 case Opcodes.ILOAD_1: 395 newList.replace(i, factory.iload(maxLocalsInOtherList + 1)); 396 break; 397 case Opcodes.ILOAD_2: 398 newList.replace(i, factory.iload(maxLocalsInOtherList + 2)); 399 break; 400 case Opcodes.ILOAD_3: 401 newList.replace(i, factory.iload(maxLocalsInOtherList + 3)); 402 break; 403 case Opcodes.ILOAD: 404 ins.getBytes()[1] += (byte)maxLocalsInOtherList; 408 break; 409 case Opcodes.ISTORE_0: 410 newList.replace(i, factory.istore(maxLocalsInOtherList)); 411 break; 412 case Opcodes.ISTORE_1: 413 newList.replace(i, factory.istore(maxLocalsInOtherList + 1)); 414 break; 415 case Opcodes.ISTORE_2: 416 newList.replace(i, factory.istore(maxLocalsInOtherList + 2)); 417 break; 418 case Opcodes.ISTORE_3: 419 newList.replace(i, factory.istore(maxLocalsInOtherList + 3)); 420 break; 421 case Opcodes.ISTORE: 422 ins.getBytes()[1] += (byte)maxLocalsInOtherList; 426 break; 427 428 case Opcodes.DLOAD_0: 430 newList.replace(i, factory.dload(maxLocalsInOtherList)); 431 break; 432 case Opcodes.DLOAD_1: 433 newList.replace(i, factory.dload(maxLocalsInOtherList + 1)); 434 break; 435 case Opcodes.DLOAD_2: 436 newList.replace(i, factory.dload(maxLocalsInOtherList + 2)); 437 break; 438 case Opcodes.DLOAD_3: 439 newList.replace(i, factory.dload(maxLocalsInOtherList + 3)); 440 break; 441 case Opcodes.DLOAD: 442 ins.getBytes()[1] += (byte)maxLocalsInOtherList; 446 break; 447 case Opcodes.DSTORE_0: 448 newList.replace(i, factory.dstore(maxLocalsInOtherList)); 449 break; 450 case Opcodes.DSTORE_1: 451 newList.replace(i, factory.dstore(maxLocalsInOtherList + 1)); 452 break; 453 case Opcodes.DSTORE_2: 454 newList.replace(i, factory.dstore(maxLocalsInOtherList + 2)); 455 break; 456 case Opcodes.DSTORE_3: 457 newList.replace(i, factory.dstore(maxLocalsInOtherList + 3)); 458 break; 459 case Opcodes.DSTORE: 460 ins.getBytes()[1] += (byte)maxLocalsInOtherList; 464 break; 465 466 case Opcodes.LLOAD_0: 468 newList.replace(i, factory.lload(maxLocalsInOtherList)); 469 break; 470 case Opcodes.LLOAD_1: 471 newList.replace(i, factory.lload(maxLocalsInOtherList + 1)); 472 break; 473 case Opcodes.LLOAD_2: 474 newList.replace(i, factory.lload(maxLocalsInOtherList + 2)); 475 break; 476 case Opcodes.LLOAD_3: 477 newList.replace(i, factory.lload(maxLocalsInOtherList + 3)); 478 break; 479 case Opcodes.LLOAD: 480 ins.getBytes()[1] += (byte)maxLocalsInOtherList; 484 break; 485 case Opcodes.LSTORE_0: 486 newList.replace(i, factory.lstore(maxLocalsInOtherList)); 487 break; 488 case Opcodes.LSTORE_1: 489 newList.replace(i, factory.lstore(maxLocalsInOtherList + 1)); 490 break; 491 case Opcodes.LSTORE_2: 492 newList.replace(i, factory.lstore(maxLocalsInOtherList + 2)); 493 break; 494 case Opcodes.LSTORE_3: 495 newList.replace(i, factory.lstore(maxLocalsInOtherList + 3)); 496 break; 497 case Opcodes.LSTORE: 498 ins.getBytes()[1] += (byte)maxLocalsInOtherList; 502 break; 503 504 case Opcodes.FLOAD_0: 506 newList.replace(i, factory.fload(maxLocalsInOtherList)); 507 break; 508 case Opcodes.FLOAD_1: 509 newList.replace(i, factory.fload(maxLocalsInOtherList + 1)); 510 break; 511 case Opcodes.FLOAD_2: 512 newList.replace(i, factory.fload(maxLocalsInOtherList + 2)); 513 break; 514 case Opcodes.FLOAD_3: 515 newList.replace(i, factory.fload(maxLocalsInOtherList + 3)); 516 break; 517 case Opcodes.FLOAD: 518 ins.getBytes()[1] += (byte)maxLocalsInOtherList; 522 break; 523 case Opcodes.FSTORE_0: 524 newList.replace(i, factory.fstore(maxLocalsInOtherList)); 525 break; 526 case Opcodes.FSTORE_1: 527 newList.replace(i, factory.fstore(maxLocalsInOtherList + 1)); 528 break; 529 case Opcodes.FSTORE_2: 530 newList.replace(i, factory.fstore(maxLocalsInOtherList + 2)); 531 break; 532 case Opcodes.FSTORE_3: 533 newList.replace(i, factory.fstore(maxLocalsInOtherList + 3)); 534 break; 535 case Opcodes.FSTORE: 536 ins.getBytes()[1] += (byte)maxLocalsInOtherList; 540 break; 541 542 } 543 } 544 545 return newList; 546 } 547 548 549 553 private void processAdviceTriggers(InstructionList il, HotSpot hs) { 554 555 InstructionFactory factory = il.getInstructionFactory(); 556 HotSpotLocator hsl = new HotSpotLocator(il, Opcodes.INVOKEVIRTUAL); 559 560 HotSpot[] triggerCandidates = hsl.getHotSpots(); 561 for (int i = 0; i < triggerCandidates.length; i++) { 562 Invocation inv = 563 (Invocation)triggerCandidates[i].getHotSpotInstruction(); 564 565 if (!inv.getClassName().equals(adviceMethod.getDeclaringClass().getName())) { 566 continue; 568 } 569 570 int idx = il.indexOf(inv); 572 573 InstructionList view = il.createView(idx-1, idx + 1); 577 view.clear(); 578 579 if ("getHotSpotName".equals(inv.getMethodName())) { 582 view.add(factory.pushConstant(hs.getName())); 583 } 584 else if ("getArguments".equals(inv.getMethodName())) { 585 } 588 else if ("getInstrumentedObject".equals(inv.getMethodName())) { 589 JiapiMethod jm = il.getDeclaringMethod(); 590 int modifiers = jm.getModifiers(); 591 if (Modifier.isStatic(modifiers)) { 592 view.add(factory.pushConstant(jm.getDeclaringClass().getName())); 595 view.add(factory.invoke(Modifier.STATIC, "java.lang.Class", "forName", new Signature("java.lang.Class", new String [] {"java.lang.String"}))); 596 } 597 else { 598 view.add(factory.aload(0)); 599 } 600 } 603 } 604 } 605 } 606 607 608 public void checkForBranchTarget(Instruction firstHotSpotInstruction, 609 InstructionList methodList, 610 Instruction firstBeforeInstruction) { 611 for (int idx = 0; idx < methodList.size(); idx++) { 612 Instruction i = (Instruction)methodList.get(idx); 613 614 if (i instanceof BranchInstruction) { 615 BranchInstruction bi = (BranchInstruction)i; 616 if (bi.getTarget() == firstHotSpotInstruction) { 617 bi.setTarget(firstBeforeInstruction); 618 } 619 } 620 } 621 } 622 623 } 624 | Popular Tags |