1 19 20 package jode.flow; 21 import java.lang.reflect.Modifier ; 22 import jode.GlobalOptions; 23 import jode.decompiler.Analyzer; 24 import jode.decompiler.ClassAnalyzer; 25 import jode.decompiler.MethodAnalyzer; 26 import jode.decompiler.FieldAnalyzer; 27 import jode.decompiler.MethodAnalyzer; 28 import jode.decompiler.Options; 29 import jode.decompiler.OuterValues; 30 import jode.decompiler.OuterValueListener; 31 import jode.expr.*; 32 import jode.type.MethodType; 33 import jode.type.Type; 34 import jode.bytecode.ClassInfo; 35 import jode.bytecode.InnerClassInfo; 36 import jode.bytecode.MethodInfo; 37 38 import java.util.Vector ; 39 import java.util.Enumeration ; 40 41 84 public class TransformConstructors { 85 90 91 ClassAnalyzer clazzAnalyzer; 92 boolean isStatic; 93 94 97 MethodAnalyzer[] cons; 98 int type0Count; 99 int type01Count; 100 101 OuterValues outerValues; 102 103 public TransformConstructors(ClassAnalyzer clazzAnalyzer, 104 boolean isStatic, MethodAnalyzer[] cons) { 105 this.clazzAnalyzer = clazzAnalyzer; 106 this.isStatic = isStatic; 107 this.cons = cons; 108 if (!isStatic) 109 this.outerValues = clazzAnalyzer.getOuterValues(); 110 lookForConstructorCall(); 111 } 112 113 129 private int getConstructorType(StructuredBlock body) { 130 133 InstructionBlock ib; 134 if (body instanceof InstructionBlock) 135 ib = (InstructionBlock)body; 136 else if (body instanceof SequentialBlock 137 && (body.getSubBlocks()[0] 138 instanceof InstructionBlock)) 139 ib = (InstructionBlock) body.getSubBlocks()[0]; 140 else 141 return 0; 142 143 Expression superExpr = ib.getInstruction().simplify(); 144 if (!(superExpr instanceof InvokeOperator) 145 || superExpr.getFreeOperandCount() != 0) 146 return 0; 147 InvokeOperator superInvoke = (InvokeOperator) superExpr; 148 if (!superInvoke.isConstructor() 149 || !superInvoke.isSuperOrThis()) 150 return 0; 151 Expression thisExpr = superInvoke.getSubExpressions()[0]; 152 if (!isThis(thisExpr, clazzAnalyzer.getClazz())) 153 return 0; 154 155 if (superInvoke.isThis()) 156 return 2; 157 else 158 return 1; 159 } 160 161 public void lookForConstructorCall() { 162 type01Count = cons.length; 163 for (int i=0; i< type01Count; ) { 164 MethodAnalyzer current = cons[i]; 165 FlowBlock header = cons[i].getMethodHeader(); 166 167 if (header == null || !header.hasNoJumps()) 168 return; 169 170 StructuredBlock body = cons[i].getMethodHeader().block; 171 int type = isStatic ? 0 : getConstructorType(body); 172 if ((GlobalOptions.debuggingFlags 173 & GlobalOptions.DEBUG_CONSTRS) != 0) 174 GlobalOptions.err.println("constr "+i+": type"+type+" "+body); 175 176 switch(type) { 177 case 0: 178 cons[i] = cons[type0Count]; 180 cons[type0Count++] = current; 181 182 case 1: 183 i++; 185 break; 186 case 2: 187 cons[i] = cons[--type01Count]; 189 cons[type01Count] = current; 190 break; 191 } 192 } 193 } 194 195 public static boolean isThis(Expression thisExpr, ClassInfo clazz) { 196 return ((thisExpr instanceof ThisOperator) 197 && (((ThisOperator)thisExpr).getClassInfo() == clazz)); 198 } 199 200 207 private void checkAnonymousConstructor() { 208 if (isStatic || cons.length != 1 209 || type01Count - type0Count != 1 210 || clazzAnalyzer.getName() != null) 211 return; 212 213 if ((GlobalOptions.debuggingFlags 214 & GlobalOptions.DEBUG_CONSTRS) != 0) 215 GlobalOptions.err.println("checkAnonymousConstructor of " 216 +clazzAnalyzer.getClazz()); 217 218 StructuredBlock sb = cons[0].getMethodHeader().block; 219 if (sb instanceof SequentialBlock) 220 sb = sb.getSubBlocks()[0]; 221 222 InstructionBlock superBlock = (InstructionBlock) sb; 223 240 Expression expr = superBlock.getInstruction().simplify(); 241 InvokeOperator superCall = (InvokeOperator) expr; 242 Expression[] subExpr = superCall.getSubExpressions(); 243 244 247 for (int i = 1; i < subExpr.length; i++) { 248 if (!(subExpr[i] instanceof LocalLoadOperator)) 249 return; 250 } 251 252 Type[] params = cons[0].getType().getParameterTypes(); 253 boolean jikesAnon = false; 254 255 int minOuter = params.length; 256 257 int slot = 1; 258 for (int i = 0; i < params.length - 1; i++) 259 slot += params[i].stackSize(); 260 261 262 263 int start = 1; 264 if (subExpr.length > 2) { 265 LocalLoadOperator llop = (LocalLoadOperator) subExpr[1]; 266 267 if (llop.getLocalInfo().getSlot() == slot) { 268 jikesAnon = true; 269 start++; 270 minOuter--; 272 slot -= params[minOuter - 1].stackSize(); 273 } 274 } 275 276 int sub = subExpr.length - 1; 277 278 while (sub >= start) { 279 LocalLoadOperator llop = (LocalLoadOperator) subExpr[sub]; 280 281 if ((GlobalOptions.debuggingFlags 282 & GlobalOptions.DEBUG_CONSTRS) != 0) 283 GlobalOptions.err.println(" pos "+sub+": "+slot+"," 284 + llop.getLocalInfo().getSlot()+ 285 "; "+minOuter); 286 287 if (llop.getLocalInfo().getSlot() != slot) { 288 slot += params[minOuter - 1].stackSize(); 290 break; 291 } 292 sub--; 293 294 minOuter--; 295 if (minOuter == 0) 296 break; 297 slot -= params[minOuter - 1].stackSize(); 298 } 299 ClassAnalyzer superAna = superCall.getClassAnalyzer(); 300 OuterValues superOV = null; 301 if (superAna != null 302 && superAna.getParent() instanceof MethodAnalyzer) { 303 superOV = superAna.getOuterValues(); 305 } 306 int minSuperOuter = sub - start + 1; 307 if ((GlobalOptions.debuggingFlags 308 & GlobalOptions.DEBUG_CONSTRS) != 0) 309 GlobalOptions.err.println(" super outer: " + superOV); 310 311 312 for (; sub >= start; sub--) { 313 LocalLoadOperator llop = (LocalLoadOperator) subExpr[sub]; 314 if (llop.getLocalInfo().getSlot() >= slot) { 315 if ((GlobalOptions.debuggingFlags 316 & GlobalOptions.DEBUG_CONSTRS) != 0) 317 GlobalOptions.err.println(" Illegal slot at "+sub+":" 318 + llop.getLocalInfo().getSlot()); 319 return; 320 } 321 } 322 323 if (minSuperOuter == 1 324 && superAna.getParent() instanceof ClassAnalyzer) { 325 326 LocalLoadOperator llop = (LocalLoadOperator) subExpr[start]; 327 if (outerValues.getValueBySlot(llop.getLocalInfo().getSlot()) 328 instanceof ThisOperator) { 329 minSuperOuter = 0; 330 outerValues.setImplicitOuterClass(true); 331 } 332 } 333 334 if (minSuperOuter > 0) { 335 if (superOV == null || superOV.getCount() < minSuperOuter) { 336 if ((GlobalOptions.debuggingFlags 337 & GlobalOptions.DEBUG_CONSTRS) != 0) 338 GlobalOptions.err.println(" super outer doesn't match: " 339 + minSuperOuter); 340 return; 341 } 342 superOV.setMinCount(minSuperOuter); 343 } 344 345 outerValues.setMinCount(minOuter); 346 if (superOV != null) { 347 final int ovdiff = minOuter - minSuperOuter; 348 outerValues.setCount(superOV.getCount() + ovdiff); 349 superOV.addOuterValueListener(new OuterValueListener() { 350 public void shrinkingOuterValues 351 (OuterValues other, int newCount) { 352 outerValues.setCount(newCount + ovdiff); 353 } 354 }); 355 } else 356 outerValues.setCount(minOuter); 357 358 if (jikesAnon) 359 outerValues.setJikesAnonymousInner(true); 360 if ((GlobalOptions.debuggingFlags 361 & GlobalOptions.DEBUG_CONSTRS) != 0) 362 GlobalOptions.err.println(" succeeded: "+outerValues); 363 cons[0].setAnonymousConstructor(true); 364 superBlock.removeBlock(); 365 type0Count++; 366 } 367 368 private boolean checkJikesSuper(Expression expr) { 369 if (expr instanceof LocalStoreOperator 370 || expr instanceof IIncOperator) 371 return false; 372 if (expr instanceof Operator) { 373 Expression subExpr[] = ((Operator)expr).getSubExpressions(); 374 for (int i=0; i< subExpr.length; i++) { 375 if (!checkJikesSuper(subExpr[i])) 376 return false; 377 } 378 } 379 return true; 380 } 381 382 private Expression renameJikesSuper(Expression expr, 383 MethodAnalyzer methodAna, 384 int firstOuterSlot, 385 int firstParamSlot) { 386 if (expr instanceof LocalLoadOperator) { 387 LocalLoadOperator llop = (LocalLoadOperator) expr; 388 int slot = llop.getLocalInfo().getSlot(); 389 if (slot >= firstOuterSlot && slot < firstParamSlot) 390 return outerValues.getValueBySlot(slot); 391 else { 392 Type[] paramTypes = methodAna.getType().getParameterTypes(); 393 int param; 394 395 if (slot >= firstParamSlot) 396 slot -= firstParamSlot - firstOuterSlot; 397 for (param = 0; slot > 1 && param < paramTypes.length; param++) 398 slot -= paramTypes[param].stackSize(); 399 llop.setLocalInfo(methodAna.getParamInfo(1+param)); 400 llop.setMethodAnalyzer(methodAna); 401 return llop; 402 } 403 } 404 if (expr instanceof Operator) { 405 Expression subExpr[] = ((Operator)expr).getSubExpressions(); 406 for (int i=0; i< subExpr.length; i++) { 407 Expression newSubExpr = 408 renameJikesSuper(subExpr[i], methodAna, 409 firstOuterSlot, firstParamSlot); 410 if (newSubExpr != subExpr[i]) 411 ((Operator)expr).setSubExpressions(i, newSubExpr); 412 } 413 } 414 return expr; 415 } 416 417 public void checkJikesContinuation() { 418 if ((GlobalOptions.debuggingFlags 419 & GlobalOptions.DEBUG_CONSTRS) != 0) 420 System.err.println("checkJikesContinuation: "+outerValues); 421 constr_loop: 422 for (int i=0; i < cons.length; i++) { 423 if ((GlobalOptions.debuggingFlags 424 & GlobalOptions.DEBUG_CONSTRS) != 0) 425 GlobalOptions.err.println("constr "+i+" type" 426 + (i < type0Count ? 0 : 427 i < type01Count ? 1 : 2) + " : " 428 + cons[i].getMethodHeader()); 429 430 MethodAnalyzer constr = cons[i]; 431 MethodType constrType = constr.getType(); 432 433 451 StructuredBlock sb = constr.getMethodHeader().block; 452 453 Vector localLoads = null; 454 InstructionBlock superBlock = null; 455 if (i >= type0Count) { 456 459 if (!(sb instanceof SequentialBlock) 460 || !(sb.getSubBlocks()[1] instanceof InstructionBlock)) 461 continue constr_loop; 462 463 superBlock = (InstructionBlock) sb.getSubBlocks()[0]; 464 sb = sb.getSubBlocks()[1]; 465 466 Expression superExpr = superBlock.getInstruction().simplify(); 467 InvokeOperator superInvoke = (InvokeOperator) superExpr; 468 superBlock.setInstruction(superInvoke); 469 470 Expression[] subExpr = superInvoke.getSubExpressions(); 471 for (int j=1; j< subExpr.length; j++) { 472 if (!checkJikesSuper(subExpr[j])) 473 continue constr_loop; 474 } 475 } 476 477 if (!(sb instanceof InstructionBlock)) 478 continue constr_loop; 479 480 481 Expression lastExpr 482 = ((InstructionBlock)sb).getInstruction().simplify(); 483 if (!(lastExpr instanceof InvokeOperator)) 484 continue constr_loop; 485 486 InvokeOperator invoke = (InvokeOperator) lastExpr; 487 if (!invoke.isThis() 488 || invoke.getFreeOperandCount() != 0) 489 continue constr_loop; 490 MethodAnalyzer methodAna = invoke.getMethodAnalyzer(); 491 if (methodAna == null) 492 continue constr_loop; 493 MethodType methodType = methodAna.getType(); 494 Expression[] methodParams = invoke.getSubExpressions(); 495 496 if (!methodAna.getName().startsWith("constructor$") 497 || methodType.getReturnType() != Type.tVoid) 498 continue constr_loop; 499 500 if (!isThis(methodParams[0], clazzAnalyzer.getClazz())) 501 continue constr_loop; 502 for (int j=1; j < methodParams.length; j++) { 503 if (!(methodParams[j] instanceof LocalLoadOperator)) 504 continue constr_loop; 505 } 506 507 Type[] paramTypes = constr.getType().getParameterTypes(); 508 int paramCount = paramTypes.length; 509 if (outerValues.isJikesAnonymousInner()) 510 paramCount--; 511 512 int maxOuterCount = paramCount - methodParams.length + 2; 513 int minOuterCount = maxOuterCount - 1; 514 int slot = 1; 515 int firstParam = 1; 516 Expression outer0 = null; 517 518 if (maxOuterCount > 0 519 && methodParams.length > 1 520 && outerValues.getCount() > 0) { 521 526 if (((LocalLoadOperator)methodParams[firstParam] 527 ).getLocalInfo().getSlot() == 1) { 528 minOuterCount = maxOuterCount; 529 outer0 = outerValues.getValue(0); 530 firstParam++; 531 } else 532 maxOuterCount--; 533 for (int j=0; j < maxOuterCount; j++) 534 slot += paramTypes[j].stackSize(); 535 } 536 537 if (minOuterCount > outerValues.getCount()) 538 continue constr_loop; 539 540 int firstParamSlot = slot; 541 int firstOuterSlot = firstParam; 542 int slotDist = firstParamSlot - firstOuterSlot; 543 545 for (int j=firstParam; j < methodParams.length; j++) { 546 if (((LocalLoadOperator) methodParams[j] 547 ).getLocalInfo().getSlot() != slot) 548 continue constr_loop; 549 slot += methodParams[j].getType().stackSize(); 550 } 551 552 outerValues.setMinCount(minOuterCount); 553 outerValues.setCount(maxOuterCount); 554 555 557 if (superBlock != null) { 558 Expression newExpr = 559 renameJikesSuper(superBlock.getInstruction(), methodAna, 560 firstOuterSlot, firstParamSlot); 561 superBlock.removeBlock(); 562 methodAna.insertStructuredBlock(superBlock); 563 } 564 if (outer0 != null) { 565 methodAna.getParamInfo(1).setExpression(outer0); 566 methodAna.getMethodHeader().simplify(); 567 } 568 569 if ((GlobalOptions.debuggingFlags 570 & GlobalOptions.DEBUG_CONSTRS) != 0) 571 GlobalOptions.err.println(" succeeded"); 572 573 constr.setJikesConstructor(constr); 574 methodAna.setJikesConstructor(constr); 575 methodAna.setHasOuterValue(firstOuterSlot == 2); 576 if (constr.isAnonymousConstructor()) 577 methodAna.setAnonymousConstructor(true); 578 } 579 } 580 581 587 private Expression transformFieldInitializer(int fieldSlot, 588 Expression expr) { 589 if (expr instanceof LocalVarOperator) { 590 if (!(expr instanceof LocalLoadOperator)) { 591 if ((GlobalOptions.debuggingFlags 592 & GlobalOptions.DEBUG_CONSTRS) != 0) 593 GlobalOptions.err.println("illegal local op: "+expr); 594 return null; 595 } 596 if (outerValues != null 597 && (Options.options & Options.OPTION_CONTRAFO) != 0) { 598 int slot = ((LocalLoadOperator)expr).getLocalInfo().getSlot(); 599 Expression outExpr = outerValues.getValueBySlot(slot); 600 if (outExpr != null) 601 return outExpr; 602 } 603 if ((GlobalOptions.debuggingFlags 604 & GlobalOptions.DEBUG_CONSTRS) != 0) 605 GlobalOptions.err.println("not outerValue: "+expr 606 +" "+outerValues); 607 return null; 608 } 609 if (expr instanceof FieldOperator) { 610 if (expr instanceof PutFieldOperator) 611 return null; 612 FieldOperator fo = (FieldOperator) expr; 613 if (fo.getClassInfo() == clazzAnalyzer.getClazz() 614 && clazzAnalyzer.getFieldIndex(fo.getFieldName(), 615 fo.getFieldType()) >= fieldSlot) 616 return null; 617 } 618 if (expr instanceof InvokeOperator) { 619 622 MethodInfo method = ((InvokeOperator) expr).getMethodInfo(); 623 String [] excs = method == null ? null : method.getExceptions(); 624 if (excs != null) { 625 ClassInfo runtimeException 626 = ClassInfo.forName("java.lang.RuntimeException"); 627 ClassInfo error = ClassInfo.forName("java.lang.Error"); 628 for (int i = 0; i < excs.length; i++) { 629 ClassInfo exClass = ClassInfo.forName(excs[i]); 630 if (!runtimeException.superClassOf(exClass) 631 && !error.superClassOf(exClass)) 632 return null; 633 } 634 } 635 } 636 if (expr instanceof Operator) { 637 Operator op = (Operator) expr; 638 Expression[] subExpr = op.getSubExpressions(); 639 for (int i=0; i< subExpr.length; i++) { 640 Expression transformed 641 = transformFieldInitializer(fieldSlot, subExpr[i]); 642 if (transformed == null) 643 return null; 644 if (transformed != subExpr[i]) 645 op.setSubExpressions(i, transformed); 646 } 647 } 648 return expr; 649 } 650 651 public void removeSynthInitializers() { 652 if ((Options.options & Options.OPTION_CONTRAFO) == 0 653 || isStatic || type01Count == 0) 654 return; 655 656 checkAnonymousConstructor(); 657 658 if ((GlobalOptions.debuggingFlags 659 & GlobalOptions.DEBUG_CONSTRS) != 0) 660 GlobalOptions.err.println("removeSynthInitializers of " 661 +clazzAnalyzer.getClazz()); 662 663 664 StructuredBlock[] sb = new StructuredBlock[type01Count]; 665 for (int i=0; i < type01Count; i++) { 666 sb[i] = cons[i].getMethodHeader().block; 667 if (i >= type0Count) { 668 if (sb[i] instanceof SequentialBlock) 669 sb[i] = sb[i].getSubBlocks()[1]; 670 else 671 672 return; 673 } 674 } 675 676 big_loop: 677 for (;;) { 678 StructuredBlock ib = 679 (sb[0] instanceof SequentialBlock) 680 ? sb[0].getSubBlocks()[0] 681 : sb[0]; 682 683 if (!(ib instanceof InstructionBlock)) 684 break big_loop; 685 686 Expression instr 687 = ((InstructionBlock) ib).getInstruction().simplify(); 688 689 if (!(instr instanceof StoreInstruction) 690 || instr.getFreeOperandCount() != 0) 691 break big_loop; 692 693 StoreInstruction store = (StoreInstruction) instr; 694 if (!(store.getLValue() instanceof PutFieldOperator)) 695 break big_loop; 696 697 PutFieldOperator pfo = (PutFieldOperator) store.getLValue(); 698 if (pfo.isStatic() != isStatic 699 || pfo.getClassInfo() != clazzAnalyzer.getClazz()) 700 break big_loop; 701 702 if (!isThis(pfo.getSubExpressions()[0], 703 clazzAnalyzer.getClazz())) 704 break big_loop; 705 706 int field = clazzAnalyzer.getFieldIndex(pfo.getFieldName(), 707 pfo.getFieldType()); 708 if (field < 0) 709 break big_loop; 710 FieldAnalyzer fieldAna = clazzAnalyzer.getField(field); 711 712 714 if (!fieldAna.isSynthetic()) 715 break big_loop; 716 717 Expression expr = store.getSubExpressions()[1]; 718 expr = transformFieldInitializer(field, expr); 719 if (expr == null) 720 break big_loop; 721 722 for (int i=1; i< type01Count; i++) { 723 ib = (sb[i] instanceof SequentialBlock) 724 ? sb[i].getSubBlocks()[0] 725 : sb[i]; 726 if (!(ib instanceof InstructionBlock) 727 || !(((InstructionBlock)ib).getInstruction().simplify() 728 .equals(instr))) { 729 if ((GlobalOptions.debuggingFlags 730 & GlobalOptions.DEBUG_CONSTRS) != 0) 731 GlobalOptions.err.println(" constr 0 and "+i 732 +" differ: " 733 +instr+"<-/->"+ib); 734 break big_loop; 735 } 736 } 737 738 739 if ((GlobalOptions.debuggingFlags 740 & GlobalOptions.DEBUG_CONSTRS) != 0) 741 GlobalOptions.err.println(" field " + pfo.getFieldName() 742 + " = " + expr); 743 744 if (!(fieldAna.setInitializer(expr))) { 745 if ((GlobalOptions.debuggingFlags 746 & GlobalOptions.DEBUG_CONSTRS) != 0) 747 GlobalOptions.err.println(" setField failed"); 748 break big_loop; 749 } 750 751 752 boolean done = false; 753 for (int i=0; i< type01Count; i++) { 754 if (sb[i] instanceof SequentialBlock) { 755 StructuredBlock next = sb[i].getSubBlocks()[1]; 756 next.replace(sb[i]); 757 sb[i] = next; 758 } else { 759 sb[i].removeBlock(); 760 sb[i] = null; 761 done = true; 762 } 763 } 764 765 if (done) { 766 if ((GlobalOptions.debuggingFlags 767 & GlobalOptions.DEBUG_CONSTRS) != 0) 768 GlobalOptions.err.println("one constr is over"); 769 break; 770 } 771 } 772 } 773 774 775 public int transformOneField(int lastField, StructuredBlock ib) { 776 777 if (!(ib instanceof InstructionBlock)) 778 return -1; 779 780 Expression instr = ((InstructionBlock) ib).getInstruction().simplify(); 781 782 if (!(instr instanceof StoreInstruction) 783 || instr.getFreeOperandCount() != 0) 784 return -1; 785 786 StoreInstruction store = (StoreInstruction) instr; 787 if (!(store.getLValue() instanceof PutFieldOperator)) 788 return -1; 789 790 PutFieldOperator pfo = (PutFieldOperator) store.getLValue(); 791 if (pfo.isStatic() != isStatic 792 || pfo.getClassInfo() != clazzAnalyzer.getClazz()) 793 return -1; 794 795 if (!isStatic) { 796 if (!isThis(pfo.getSubExpressions()[0], 797 clazzAnalyzer.getClazz())) { 798 if ((GlobalOptions.debuggingFlags 799 & GlobalOptions.DEBUG_CONSTRS) != 0) 800 GlobalOptions.err.println(" not this: "+instr); 801 return -1; 802 } 803 } 804 805 int field = clazzAnalyzer.getFieldIndex(pfo.getFieldName(), 806 pfo.getFieldType()); 807 808 if (field <= lastField) 809 return -1; 810 811 Expression expr = store.getSubExpressions()[1]; 812 expr = transformFieldInitializer(field, expr); 813 if (expr == null) 814 return -1; 815 816 if ((GlobalOptions.debuggingFlags 817 & GlobalOptions.DEBUG_CONSTRS) != 0) 818 GlobalOptions.err.println(" field " + pfo.getFieldName() 819 + " = " + expr); 820 821 if (field <= lastField 823 || !(clazzAnalyzer.getField(field).setInitializer(expr))) { 824 if ((GlobalOptions.debuggingFlags 825 & GlobalOptions.DEBUG_CONSTRS) != 0) 826 GlobalOptions.err.println("set field failed"); 827 return -1; 828 } 829 return field; 830 } 831 832 public void transformBlockInitializer(StructuredBlock block) { 833 StructuredBlock start = null; 834 StructuredBlock tail = null; 835 int lastField = -1; 836 while (block instanceof SequentialBlock) { 837 StructuredBlock ib = block.getSubBlocks()[0]; 838 int field = transformOneField(lastField, ib); 839 if (field < 0) 840 clazzAnalyzer.addBlockInitializer(lastField + 1, ib); 841 else 842 lastField = field; 843 block = block.getSubBlocks()[1]; 844 } 845 if (transformOneField(lastField, block) < 0) 846 clazzAnalyzer.addBlockInitializer(lastField + 1, block); 847 } 848 849 public boolean checkBlockInitializer(InvokeOperator invoke) { 850 if (!invoke.isThis() 851 || invoke.getFreeOperandCount() != 0) 852 return false; 853 MethodAnalyzer methodAna = invoke.getMethodAnalyzer(); 854 if (methodAna == null) 855 return false; 856 FlowBlock flow = methodAna.getMethodHeader(); 857 MethodType methodType = methodAna.getType(); 858 if (!methodAna.getName().startsWith("block$") 859 || methodType.getParameterTypes().length != 0 860 || methodType.getReturnType() != Type.tVoid) 861 return false; 862 if (flow == null || !flow.hasNoJumps()) 863 return false; 864 865 if (!isThis(invoke.getSubExpressions()[0], 866 clazzAnalyzer.getClazz())) 867 return false; 868 869 methodAna.setJikesBlockInitializer(true); 870 transformBlockInitializer(flow.block); 871 return true; 872 } 873 874 private void removeDefaultSuper() { 875 if ((GlobalOptions.debuggingFlags 876 & GlobalOptions.DEBUG_CONSTRS) != 0) 877 GlobalOptions.err.println("removeDefaultSuper of " 878 + clazzAnalyzer.getClazz()); 879 882 for (int i=type0Count; i< type01Count; i++) { 883 MethodAnalyzer current = cons[i]; 884 FlowBlock header = cons[i].getMethodHeader(); 885 StructuredBlock body = header.block; 886 887 if ((GlobalOptions.debuggingFlags 888 & GlobalOptions.DEBUG_CONSTRS) != 0) 889 GlobalOptions.err.println("constr "+i+": "+body); 890 891 InstructionBlock ib; 892 if (body instanceof InstructionBlock) 893 ib = (InstructionBlock) body; 894 else 895 ib = (InstructionBlock) body.getSubBlocks()[0]; 896 897 InvokeOperator superInvoke = (InvokeOperator) 898 ib.getInstruction().simplify(); 899 ClassInfo superClazz = superInvoke.getClassInfo(); 900 InnerClassInfo[] outers = superClazz.getOuterClasses(); 901 int superParamCount = superInvoke.getSubExpressions().length - 1; 902 903 if ((Options.options & Options.OPTION_INNER) != 0 904 && outers != null 905 && outers[0].outer != null 906 && outers[0].name != null 907 && !Modifier.isStatic(outers[0].modifiers)) { 908 909 if (superParamCount != 1 910 || !(superInvoke.getSubExpressions()[1] 911 instanceof ThisOperator)) 912 continue; 913 } else { 914 918 ClassAnalyzer superClazzAna = superInvoke.getClassAnalyzer(); 919 OuterValues superOV = null; 920 if (superClazzAna != null) 921 superOV = superClazzAna.getOuterValues(); 922 if (superParamCount > 0 923 && (superOV == null 924 || superParamCount > superOV.getCount())) 925 continue; 926 } 927 ib.removeBlock(); 928 if (i > type0Count) { 929 cons[i] = cons[type0Count]; 930 cons[type0Count] = current; 931 } 932 type0Count++; 933 } 934 } 935 936 private void removeInitializers() { 937 if (type01Count == 0) 938 return; 939 940 if ((GlobalOptions.debuggingFlags 941 & GlobalOptions.DEBUG_CONSTRS) != 0) 942 GlobalOptions.err.println("removeInitializers"); 943 944 StructuredBlock[] sb = new StructuredBlock[type01Count]; 945 for (int i=0; i< type01Count; i++) { 946 FlowBlock header = cons[i].getMethodHeader(); 947 948 sb[i] = header.block; 949 if (i >= type0Count) { 950 if (sb[i] instanceof SequentialBlock) 951 sb[i] = sb[i].getSubBlocks()[1]; 952 else { 953 sb[i] = null; 954 return; 955 } 956 } 957 } 958 int lastField = -1; 959 big_loop: 960 for (;;) { 961 StructuredBlock ib = 962 (sb[0] instanceof SequentialBlock) 963 ? sb[0].getSubBlocks()[0] 964 : sb[0]; 965 966 if ((GlobalOptions.debuggingFlags 967 & GlobalOptions.DEBUG_CONSTRS) != 0) 968 GlobalOptions.err.println("Instruction: "+ib); 969 970 if (!(ib instanceof InstructionBlock)) 971 break big_loop; 972 973 Expression instr 974 = ((InstructionBlock) ib).getInstruction().simplify(); 975 976 for (int i=1; i < type01Count; i++) { 977 ib = (sb[i] instanceof SequentialBlock) 978 ? sb[i].getSubBlocks()[0] 979 : sb[i]; 980 if (!(ib instanceof InstructionBlock) 981 || !(((InstructionBlock)ib).getInstruction().simplify() 982 .equals(instr))) { 983 if ((GlobalOptions.debuggingFlags 984 & GlobalOptions.DEBUG_CONSTRS) != 0) 985 GlobalOptions.err.println("constr "+i+" differs: "+ib); 986 break big_loop; 987 } 988 } 989 990 if (instr instanceof InvokeOperator 991 && checkBlockInitializer((InvokeOperator) instr)) { 992 for (int i=0; i< type01Count; i++) { 993 if (sb[i] instanceof SequentialBlock) { 994 StructuredBlock next = sb[i].getSubBlocks()[1]; 995 next.replace(sb[i]); 996 sb[i] = next; 997 } else { 998 sb[i].removeBlock(); 999 sb[i] = null; 1000 } 1001 } 1002 break big_loop; 1003 } 1004 1005 int field = transformOneField(lastField, ib); 1006 if (field < 0) 1007 break big_loop; 1008 1009 lastField = field; 1010 1011 boolean done = false; 1012 for (int i=0; i< type01Count; i++) { 1013 if (sb[i] instanceof SequentialBlock) { 1014 StructuredBlock next = sb[i].getSubBlocks()[1]; 1015 next.replace(sb[i]); 1016 sb[i] = next; 1017 } else { 1018 sb[i].removeBlock(); 1019 sb[i] = null; 1020 done = true; 1021 } 1022 } 1023 1024 if (done) { 1025 if ((GlobalOptions.debuggingFlags 1026 & GlobalOptions.DEBUG_CONSTRS) != 0) 1027 GlobalOptions.err.println("one constr is over"); 1028 break; 1029 } 1030 } 1031 } 1032 1033 1045 public void transform() { 1046 if ((Options.options & Options.OPTION_CONTRAFO) == 0 1047 || cons.length == 0) 1048 return; 1049 1050 removeDefaultSuper(); 1051 removeInitializers(); 1052 checkJikesContinuation(); 1053 1054 if (outerValues != null) { 1055 1058 for (int i=0; i< cons.length; i++) { 1059 for (int j = 0; j < outerValues.getCount(); j++) 1060 cons[i].getParamInfo(j+1) 1061 .setExpression(outerValues.getValue(j)); 1062 cons[i].getMethodHeader().simplify(); 1066 } 1067 } 1068 } 1069} 1070 | Popular Tags |