1 30 31 39 40 package jbet; 41 import java.util.*; 42 43 public class InstrBlock extends Block 44 { 45 public Snippit code; public DataFlow.ProcState pse; public DataFlow.ProcState psx; public MethodInfo from; public boolean entry; public String handler; 52 public InstrBlock () 53 { 54 es = new ExitRec(); 55 pse = null; 56 psx = null; 57 entry = false; 58 handler = null; 59 code = new Snippit(); 60 } 61 62 public DataFlow.ProcState entry() { return pse; } 63 public DataFlow.ProcState exit () { return psx; } 64 65 public void printinfo (LineWriter out, boolean printcode) 66 { 67 if (from != null && from.block == this) 68 out.println ("block " + swval + " : " + from.cr.name() + "." + from.name + from.descriptor); 69 else 70 out.println ("block " + swval); 71 72 if (handler != null) { 73 out.println (" Exception handler for " + handler); 74 } 75 76 if ((enflags & En_jsr) != 0) 77 out.println (" Jsr target"); 78 79 if (entry() != null) { 80 out.print (" Entry Stack :"); 81 for (int i = 0; i < entry().stacklen; i++) 82 out.print (" " + i + ":" + entry().stack[i].toString()); 83 out.println(); 84 85 out.print (" Entry Locals:"); 86 for (int i = 0; i < entry().locals.length; i++) 87 if (entry().locals[i] != null) 88 out.print (" " + i + ":" + entry().locals[i].toString()); 89 out.println(); 90 } 91 92 if (exit() != null) { 93 out.print (" Exit Stack :"); 94 for (int i = 0; i < exit().stacklen; i++) 95 out.print (" " + i + ":" + exit().stack[i].toString()); 96 out.println(); 97 98 out.print (" Exit Locals:"); 99 for (int i = 0; i < exit().locals.length; i++) 100 if (exit().locals[i] != null) 101 out.print (" " + i + ":" + exit().locals[i].toString()); 102 out.println(); 103 } 104 105 if (printcode) { 106 code.printCode (out, true); 107 es.print (out); 108 } 109 } 110 111 private static int marker = 0; 112 113 115 116 private static String catchtype (String s) 117 { 118 if (s == null) 119 return "java/lang/Throwable"; 120 else 121 return s; 122 } 123 124 134 135 public static Vector FindBasicBlocks (final MethodInfo meth, final Hashtable callclasses) throws ClassFileException, DataFlowException 136 { 137 if (meth.code == null) 138 return null; 139 140 class _util { 141 ClassInfo getclass (Object name) throws ClassFileException 142 { 143 return (ClassInfo) callclasses.get (name); 144 } 145 146 ClassInfo getanyclass (String name) throws ClassFileException 148 { 149 ClassInfo cr2 = (ClassInfo) callclasses.get (name); 150 151 if (cr2 == null) 152 for (Iterator e = callclasses.values().iterator(); e.hasNext();) { 153 ClassInfo cr3 = (ClassInfo) e.next(); 154 if ((new Type ('L' + name + ';')).isa 155 (new Type ('L' + cr3.thisClass + ';'))) { 156 cr2 = cr3; 157 break; 158 } 159 } 160 161 return cr2; 162 } 163 164 boolean hasclass (Object name) 165 { 166 return callclasses.get (name) != null; 167 } 168 169 170 boolean replaceMethod (Instruction instr) 171 { 172 if (callclasses == null) 173 return false; 174 175 throw new GlobalException ("no callclasses supported"); 176 } 177 178 179 180 boolean canThrow (Instruction instr) 181 { 182 int op = instr.opCode(); 183 184 return (op == Instruction.OP_ATHROW || 185 op == Instruction.OP_INVOKEVIRTUAL || 186 op == Instruction.OP_INVOKESTATIC); 187 } 188 } 189 _util util = new _util(); 190 191 Snippit s = meth.code; 192 InstrBlock sb = null; 193 Vector blocks = new Vector(); 194 boolean leader = true; 195 Instruction next; 196 boolean[] jumps = new boolean[s.tail.pc() + 1]; 197 DataFlow tr; 198 199 200 if (meth.dataflow == null) { 201 tr = new DataFlow (meth); 202 tr.run(); 203 meth.dataflow = tr; 204 } else 205 tr = (DataFlow) meth.dataflow; 206 207 Hashtable localHash = new Hashtable(); 208 209 for (Instruction instr = s.head; instr != null; instr = instr.next) 210 { 211 s.advanceLocals(instr, localHash); 212 if (instr.usesLocals()) { 213 LocalVarRec rec = (LocalVarRec)localHash.get 214 (new Integer (instr.lvtIndex())); 215 if (rec != null) { 216 instr.setLvname(rec.name); 217 } 218 } 219 220 if (instr.usesBranch ()) { 222 if (instr.opCode () == Instruction.OP_LOOKUPSWITCH || 223 instr.opCode () == Instruction.OP_TABLESWITCH) 224 { 225 BranchTarget[] sw = instr.switchArray (); 226 for (int i = 0; i < sw.length; i++) 227 jumps[sw[i].instr.pc()] = true; 228 jumps[instr.branchTarget().instr.pc()] = true; 229 } 230 else 231 jumps[instr.branchTarget().instr.pc()] = true; 232 } 233 } 234 235 for (int i = 0; i < s.exVector.size(); i++) { 237 jumps[s.exAt (i).handler.instr.pc()] = true; 238 jumps[s.exAt (i).start.instr.pc()] = true; 239 jumps[s.exAt (i).end.instr.next.pc()] = true; 240 s.exAt (i).marker = ++marker; 241 } 242 243 for (Instruction instr = s.head; instr != null; instr = next) 244 { 245 246 if (instr.procState() == null) { next = instr.next; continue; } 248 249 251 if (jumps[instr.pc()]) 252 leader = true; 253 254 if (instr.prev != null) { 255 if (instr.prev.usesBranch () || 256 instr.prev.isReturn () || 257 instr.prev.opCode () == Instruction.OP_ATHROW) 258 leader = true; 259 260 if (util.replaceMethod (instr.prev)) 262 leader = true; 263 } 264 265 instr.setBlockNumber (0); 267 if (leader) { 268 272 273 if (instr.prev != null ) 274 for (int x = 0; x < s.exVector.size(); x++) { 275 ExceptionRec exo = s.exAt (x); 276 for (Instruction exi = exo.start.instr; exi != exo.end.instr.next; exi = exi.next) 277 if (exi == instr.prev) { 278 if (sb.es.exceptions == null) 279 sb.es.exceptions = new Vector(); 280 sb.es.exceptions.addElement 281 (new ExcInfo (catchtype (exo.catchType), exo)); 282 } 283 } 284 285 286 sb = new InstrBlock(); 287 sb.from = meth; 288 blocks.addElement (sb); 289 sb.swval = blocks.size(); 290 instr.setBlockNumber (blocks.size()); 291 292 for (int i = 0; i < s.exVector.size(); i++) 293 if (instr == s.exAt(i).handler.instr) { 294 ExceptionRec ex = s.exAt (i); 295 296 ex.handler.block = sb; 297 298 if (ex.catchType != null) 299 sb.handler = ex.catchType; 300 else 301 sb.handler = "java/lang/Throwable"; 302 } 303 } 304 305 next = instr.next; 306 sb.code.push (instr.dup()); 307 leader = false; 308 } 309 310 314 315 for (int j = 0; j < blocks.size(); j++) 316 { 317 sb = (InstrBlock)blocks.elementAt (j); 318 319 if (sb.code.head.procState() == null) { 321 Jbet.warn.println ("block #B" + sb.swval + " head " + sb.code.head.pc() + 322 " is unreachable"); 323 sb.code.head = sb.code.tail = null; 324 continue; 325 } 326 327 if (sb.es.exceptions != null) 329 for (int i = 0; i < sb.es.exceptions.size(); i++) { 330 ExcInfo ex = sb.es.exAt (i); 331 ex.handler = (InstrBlock) blocks.elementAt (ex.info.handler.instr.blockNumber()-1); 332 } 333 334 sb.pse = sb.code.head.procState(); 335 336 for (Instruction instr = sb.code.head; instr != null; instr = instr.next) 337 { 338 if (instr.opCode() != Instruction.AOP_EXCMARKER) { 339 sb.psx = instr.procState().dup(); 340 sb.psx.model (instr); 341 } 342 343 if (instr.usesBranch()) 344 switch (instr.opCode ()) { 345 case Instruction.OP_LOOKUPSWITCH: 346 case Instruction.OP_TABLESWITCH: 347 { 348 sb.code.remove (instr); 349 instr = instr.dup(); 350 BranchTarget[] sw = instr.switchArray (); 351 BranchTarget t = instr.branchTarget(); 352 if (t.instr.blockNumber() == 0) 353 Jbet.error.println ("bad jump at " + instr.pc() + " to pc=" 354 + t.instr.pc()); 355 for (int i = 0; i < sw.length; i++) { 356 if (sw[i].instr.blockNumber() == 0) 357 Jbet.error.println ("bad jump at "+instr.pc()+" to pc=" 358 + sw[i].instr.pc()); 359 sw[i].block = (InstrBlock)blocks.elementAt 360 (sw[i].instr.blockNumber()-1); 361 sw[i].instr = null; 362 } 363 sb.es.op = instr.opCode (); 364 sb.es.switches = sw; 365 sb.es.swofs = instr.immediate (); 366 sb.es.primary = (InstrBlock)blocks.elementAt (t.instr.blockNumber()-1); 367 sb.es.stackuse = 1; 368 } 369 break; 370 371 case Instruction.OP_IFNULL: 372 case Instruction.OP_IFNONNULL: 373 case Instruction.OP_IFEQ: 374 case Instruction.OP_IFNE: 375 case Instruction.OP_IFLE: 376 case Instruction.OP_IFLT: 377 case Instruction.OP_IFGT: 378 case Instruction.OP_IFGE: 379 case Instruction.OP_IF_ACMPEQ: 380 case Instruction.OP_IF_ACMPNE: 381 case Instruction.OP_IF_ICMPEQ: 382 case Instruction.OP_IF_ICMPNE: 383 case Instruction.OP_IF_ICMPLE: 384 case Instruction.OP_IF_ICMPLT: 385 case Instruction.OP_IF_ICMPGT: 386 case Instruction.OP_IF_ICMPGE: 387 sb.es.savestack = false; 388 389 default: 390 { 391 sb.es.stackuse = instr.stackUse(); 392 sb.code.remove (instr); 393 BranchTarget t = instr.branchTarget(); 394 if (t.instr.blockNumber() == 0) 395 Jbet.error.println ("bad jump at " + instr.pc() + " to pc=" 396 + t.instr.pc()); 397 sb.es.op = instr.opCode (); 398 399 if (sb.es.op == Instruction.OP_GOTO || sb.es.op == Instruction.OP_GOTO_W) { 400 sb.es.op = 0; 401 sb.es.primary = (InstrBlock)blocks.elementAt (t.instr.blockNumber()-1); 402 } 403 else if (sb.es.op==Instruction.OP_JSR || sb.es.op==Instruction.OP_JSR_W) { 404 sb.es.savestack = false; 405 sb.es.ret = (InstrBlock)blocks.elementAt (j+1); 406 407 InstrBlock jsrt = (InstrBlock)blocks.elementAt (t.instr.blockNumber()-1); 408 sb.es.primary = jsrt; 409 jsrt.enflags |= En_jsr; 410 } 411 else { 412 sb.es.jump = (InstrBlock)blocks.elementAt (t.instr.blockNumber()-1); 413 sb.es.primary = (InstrBlock)blocks.elementAt (j+1); 414 } 415 } 416 break; 417 } 418 else if (instr.isReturn ()) { 419 sb.es.primary = null; 420 sb.es.op = instr.opCode (); 421 sb.code.remove (instr); 422 sb.es.savestack = false; 423 sb.es.stackuse = instr.stackUse(); 424 425 break; 426 } 427 else if (instr.opCode () == Instruction.OP_RET) { 428 DataFlow.ProcState ps = instr.procState(); 429 sb.es.op = Instruction.OP_RET; 430 sb.es.retlvt = instr.lvtIndex (); 431 sb.es.switches = new BranchTarget [ ps.ret_places.size() ]; 432 for (int l = 0; l < sb.es.switches.length; l++) { 433 sb.es.switches[l] = new BranchTarget(); 434 sb.es.switches[l].block = (InstrBlock)blocks.elementAt 435 (((Instruction)ps.ret_places.elementAt(l)).blockNumber()-1); 436 } 437 sb.code.remove (instr); 438 break; 439 } 440 else if (instr.opCode () == Instruction.OP_ATHROW) { 441 sb.es.stackuse = instr.stackUse(); 442 sb.es.op = Instruction.OP_ATHROW; 443 sb.es.savestack = false; 444 sb.es.primary = null; 445 sb.code.remove (instr); 446 } 447 else if (util.replaceMethod (instr)) { 448 boolean ok = false; 449 ClassInfo cr2 = util.getanyclass (instr.classRef()); 450 451 if (cr2 == null) 452 Jbet.debug.println ("cr2 null: " + instr.classRef()); 453 else 454 for (int k = 0; k < cr2.methods.size(); k++) { 455 MethodInfo cmi = cr2.methodAt (k); 456 457 if (instr.descriptor ().equals (cmi.descriptor) && 458 instr.elemName().equals (cmi.name)) { 459 460 if (cmi.isNative()) { 461 ok = true; 462 break; 463 } 464 465 ok = true; 466 sb.es.method = cmi; 467 sb.es.mclass = cr2; 468 sb.es.op = instr.opCode (); 469 sb.es.primary = sb; 470 sb.es.ret = (InstrBlock)blocks.elementAt (j+1); 471 ((InstrBlock) sb.es.ret).entry = true; 472 sb.es.savestack = false; 473 474 477 sb.code.remove (instr); 478 break; 479 } 480 } 481 482 if (!ok) { 483 484 Jbet.error.println ("failed to replace method call " + instr.classRef() + "." + 485 instr.elemName() + instr.descriptor()); 486 } 487 } 488 } 489 490 if (sb.es.primary == null && j != blocks.size()-1 && sb.es.op != Instruction.OP_RET && 492 sb.es.op != Instruction.OP_ATHROW && sb.es.op != Instruction.OP_RETURN && 493 sb.es.op != Instruction.OP_IRETURN && sb.es.op != Instruction.OP_FRETURN && 494 sb.es.op != Instruction.OP_ARETURN && sb.es.op != Instruction.OP_LRETURN && 495 sb.es.op != Instruction.OP_DRETURN) 496 sb.es.primary = (InstrBlock)blocks.elementAt (j+1); 497 } 498 499 return blocks; 500 } 501 } 502 | Popular Tags |