1 23 24 25 package com.sun.jdo.api.persistence.enhancer.impl; 26 27 import java.util.Map ; 28 import java.util.HashMap ; 29 import java.util.Vector ; 30 import java.util.Stack ; 31 import java.util.Enumeration ; 32 33 import com.sun.jdo.api.persistence.enhancer.classfile.*; 34 35 import com.sun.jdo.api.persistence.enhancer.util.Support; 36 import com.sun.jdo.api.persistence.enhancer.util.InternalError; 37 import com.sun.jdo.api.persistence.enhancer.util.ClassFileSource; 38 39 import com.sun.jdo.api.persistence.enhancer.meta.JDOMetaData; 41 42 43 68 69 104 105 106 110 class MethodAnnotater 112 extends Support 113 implements AnnotationConstants { 114 115 private final ClassAction ca; 117 118 private final ClassMethod method; 120 121 private final ConstantPool pool; 123 124 125 private final Environment env; 128 129 130 private int annotate; 131 132 133 private Vector tmpRegisters; 134 135 136 private Vector tmpDoubleRegisters; 137 138 141 145 146 149 private short annotationStack = 0; 150 151 152 156 157 158 162 163 165 private Map insnNotes = new HashMap (11); 166 167 168 172 173 175 179 boolean needsAnnotation() { 180 return annotate != 0; 181 } 182 183 186 MethodAnnotater(ClassAction ca, 188 ClassMethod method, 189 Environment env) { 190 this.ca = ca; 191 this.method = method; 192 this.env = env; 193 this.pool = ca.classFile().pool(); 194 } 195 196 198 201 void checkMethod() { 202 env.message( 204 "checking method " + ca.userClassName() + "." + method.name().asString() + Descriptor.userMethodArgs(method.signature().asString())); 207 208 annotate = 0; 210 final CodeAttribute codeAttr = method.codeAttribute(); 211 if (codeAttr == null) { 212 return; 213 } 214 215 225 226 if (avoidAnnotation()) { 229 return; 230 } 231 checkCode(codeAttr); 232 233 242 } 243 244 248 281 282 285 296 297 298 301 309 310 313 320 321 325 private boolean avoidAnnotation() { 326 328 337 338 367 368 return false; 369 } 370 371 373 376 void checkCode(CodeAttribute codeAttr) { 378 Insn firstInsn = codeAttr.theCode(); 380 381 for (Insn markInsn = firstInsn; 385 markInsn != null; 386 markInsn = markInsn.next()) { 387 markInsn.markTargets(); 388 } 389 390 int allFlags = 0; 391 395 396 for (Insn insn = firstInsn; insn != null; insn = insn.next() ) { 397 InsnNote note = null; 398 399 switch(insn.opcode()) { 400 409 case opc_getfield: 410 note = noteGetFieldAnnotation(insn); 411 break; 412 case opc_putfield: 413 note = notePutFieldAnnotation(insn); 414 break; 415 438 default: 439 break; 440 } 441 442 if (note != null) { 443 addNoteList(note); 444 445 affirm((note.next() == null), 447 "Number of annotation notes for instruction > 1."); allFlags |= note.insnFlags; 449 450 479 } 480 481 486 } 487 488 506 507 final String methodName = method.name().asString(); 510 final String methodSig = method.signature().asString(); 511 final boolean implementsPersistence = ca.getImplementsPersistence(); 515 if (false) { 516 System.out.println(" check for annotating clone()"); System.out.println(" methodName = " + methodName); System.out.println(" methodSig = " + methodSig); System.out.println(" implementsPersistence = " + implementsPersistence); 521 } 522 if (methodName.equals("clone") && methodSig.equals("()Ljava/lang/Object;") && implementsPersistence) { 525 allFlags |= SuperClone; 528 } 529 530 539 annotate = allFlags; 540 } 541 542 543 546 591 592 595 private InsnNote noteGetFieldAnnotation(Insn insn) { 597 final InsnConstOp getFieldInsn = (InsnConstOp)insn; 599 final ConstFieldRef fieldRef = (ConstFieldRef)getFieldInsn.value(); 600 final String fieldOf = fieldRef.className().asString(); 601 602 final String fieldName 604 = fieldRef.nameAndType().name().asString(); 605 final JDOMetaData meta = env.getJDOMetaData(); 606 if (!meta.isPersistentField(fieldOf, fieldName)) 607 return null; 608 609 616 617 final boolean dfgField 619 = meta.isDefaultFetchGroupField(fieldOf, fieldName); 620 final boolean pkField 621 = meta.isPrimaryKeyField(fieldOf, fieldName); 622 final int fieldIndex 623 = meta.getFieldNo(fieldOf, fieldName); 624 final String targetPCRootClass 625 = meta.getPersistenceCapableRootClass(fieldOf); 626 627 int flags = 0; 628 final String fieldSig = fieldRef.nameAndType().signature().asString(); 630 final int stackArgSize = 0; 632 633 if (false) { 635 System.out.println(" get field " + fieldOf + "." + fieldName + "[" + fieldIndex + "]" + "<" + fieldSig + ">" + " : p" + (dfgField ? ",dfg" : ",!dfg") + (pkField ? ",pk" : ",!pk") + ";"); } 644 645 Insn dep = findArgDepositer(insn, stackArgSize); 646 if (dep != null 647 && dep.opcode() == opc_aload_0 648 && !method.isStatic()) 649 flags |= FetchThis; 651 else 652 flags |= FetchPersistent; 653 654 if (dfgField) 656 flags |= DFGField; 657 658 if (pkField) 660 flags |= PKField; 661 662 return new InsnNote(insn, flags, 664 stackArgSize, 665 fieldSig, fieldOf, fieldName, fieldIndex, 666 targetPCRootClass); 667 671 } 672 673 676 private InsnNote notePutFieldAnnotation(Insn insn) { 678 final InsnConstOp putFieldInsn = (InsnConstOp)insn; 680 final ConstFieldRef fieldRef = (ConstFieldRef)putFieldInsn.value(); 681 final String fieldOf = fieldRef.className().asString(); 682 683 final String fieldName 685 = fieldRef.nameAndType().name().asString(); 686 final JDOMetaData meta = env.getJDOMetaData(); 687 if (!meta.isPersistentField(fieldOf, fieldName)) 688 return null; 689 690 697 698 final boolean dfgField 700 = meta.isDefaultFetchGroupField(fieldOf, fieldName); 701 final boolean pkField 702 = meta.isPrimaryKeyField(fieldOf, fieldName); 703 final int fieldIndex 704 = meta.getFieldNo(fieldOf, fieldName); 705 final String targetPCRootClass 706 = meta.getPersistenceCapableRootClass(fieldOf); 707 708 int flags = 0; 709 final String fieldSig = fieldRef.nameAndType().signature().asString(); 711 final int stackArgSize 713 = (fieldSig.equals("J") || fieldSig.equals("D")) ? 2 : 1; 715 if (false) { 717 System.out.println(" put field " + fieldOf + "." + fieldName + "[" + fieldIndex + "]" + "<" + fieldSig + ">" + " : p" + (dfgField ? ",dfg" : ",!dfg") + (pkField ? ",pk" : ",!pk") + ";"); } 726 727 Insn dep = findArgDepositer(insn, stackArgSize); 728 if (dep != null 729 && dep.opcode() == opc_aload_0 730 && !method.isStatic()) 731 flags |= DirtyThis; 733 else 734 flags |= DirtyPersistent; 735 736 if (dfgField) 738 flags |= DFGField; 739 740 if (pkField) 742 flags |= PKField; 743 744 return new InsnNote(insn, flags, 746 stackArgSize, 747 fieldSig, fieldOf, fieldName, fieldIndex, 748 targetPCRootClass); 749 753 } 754 755 758 793 794 839 840 842 845 void annotateMethod() { 846 final CodeAttribute codeAttr = method.codeAttribute(); 848 if (codeAttr == null || !needsAnnotation()) 849 return; 850 851 859 860 env.message( 862 "annotating method " + ca.userClassName() + "." + method.name().asString() + Descriptor.userMethodArgs(method.signature().asString())); 865 866 871 872 Insn firstInsn = codeAttr.theCode(); 873 874 Insn insn = firstInsn.next(); 876 877 while (insn != null) { 878 switch(insn.opcode()) { 879 886 case opc_getfield: 887 case opc_putfield: 888 907 insn = insnAnnotation(insn); 908 break; 909 default: 910 break; 911 } 912 913 insn = insn.next(); 914 } 915 916 if ((annotate & SuperClone) != 0) { 918 final String superName = ca.classFile().superName().asString(); 919 annotateClone(codeAttr, superName); 920 } 921 922 1009 1010 1041 1042 if (annotationStack > 0) 1043 codeAttr.setStackUsed(codeAttr.stackUsed() + annotationStack); 1044 } 1045 1046 1048 1052 1090 1091 1097 1180 1181 1183 private void annotateClone(CodeAttribute codeAttr, 1186 String superName) { 1187 if (false) { 1188 final String methodName = method.name().asString(); 1189 final String methodSig = method.signature().asString(); 1190 System.out.println("annotateClone()"); System.out.println(" methodName = " + methodName); System.out.println(" methodSig = " + methodSig); System.out.println(" superName = " + superName); } 1195 1196 Insn insn; 1197 for (insn = codeAttr.theCode(); 1198 insn != null; 1199 insn = insn.next()) { 1200 1201 if (insn.opcode() != opc_invokespecial) 1206 continue; 1207 1208 final InsnConstOp invoke = (InsnConstOp)insn; 1209 final ConstMethodRef methodRef = (ConstMethodRef)invoke.value(); 1210 final ConstNameAndType methodNT = methodRef.nameAndType(); 1211 final String methodName = methodNT.name().asString(); 1212 final String methodSig = methodNT.signature().asString(); 1213 1214 if (!(methodName.equals("clone") && methodSig.equals("()Ljava/lang/Object;"))) continue; 1217 1218 if (false) { 1219 final ConstClass methodClass = methodRef.className(); 1220 final String methodClassName = methodClass.asString(); 1221 System.out.println(" found invocation of: " + methodClassName 1223 + "." + methodName + methodSig); } 1225 1226 final String thisClass = ca.className(); 1229 final Insn checkCastInsn = insn.next(); 1230 final boolean needCheckcast; 1231 if (checkCastInsn.opcode() != opc_checkcast) { 1232 needCheckcast = true; 1233 } else { 1234 ConstClass target = 1235 (ConstClass) ((InsnConstOp) checkCastInsn).value(); 1236 if (target.asString().equals(thisClass)) { 1237 insn = checkCastInsn; 1238 needCheckcast = false; 1239 } else { 1240 needCheckcast = true; 1241 } 1242 } 1243 1244 { 1246 final Insn newInsn = Insn.create(opc_dup); 1248 if (needCheckcast) { 1249 newInsn.append(Insn.create(opc_checkcast, 1250 pool.addClass(thisClass))); 1251 } 1252 newInsn.append(Insn.create(opc_dup)); 1253 1254 newInsn.append(Insn.create(opc_aconst_null)); 1256 newInsn.append(Insn.create( 1257 opc_putfield, 1258 pool.addFieldRef(thisClass, 1259 JDOMetaData.JDOStateManagerFieldName, 1260 JDOMetaData.JDOStateManagerFieldSig))); 1261 newInsn.append(Insn.create(opc_iconst_0)); 1262 newInsn.append(Insn.create( 1263 opc_putfield, 1264 pool.addFieldRef(thisClass, 1265 JDOMetaData.JDOFlagsFieldName, 1266 JDOMetaData.JDOFlagsFieldSig))); 1267 1268 insn.insert(newInsn); 1270 noteStack(3); 1271 } 1272 } 1273 } 1274 1275 1386 1387 1389 1396 1428 1429 1431 1434 private Insn insnAnnotation(final Insn insn) { 1435 1437 int initialSingleRegs = 0; 1438 1439 1445 InsnNote note = getNoteList(insn); 1446 if (note == null) 1447 return insn; 1448 1449 affirm(insn == note.insn); 1451 affirm((note.next() == null), 1452 "Number of annotation notes for instruction > 1."); 1454 final boolean fetch = (note.fetchPersistent() || note.fetchThis()); 1456 final boolean dirty = (note.dirtyPersistent() || note.dirtyThis()); 1457 affirm((fetch ^ dirty), 1459 "Inconsistent fetch/dirty flags."); 1461 final boolean dfgField = note.dfgFieldAccess(); 1463 final boolean pkField = note.pkFieldAccess(); 1464 1465 if (false) { 1467 final String targetClassName = note.targetClassName; 1468 final String targetFieldName = note.targetFieldName; 1469 1471 System.out.println(" build annotation: " + targetClassName 1473 + "." + targetFieldName + " : " + (pkField ? "pk," : "!pk,") + (dfgField ? "dfg," : "!dfg,") + (fetch ? "fetch " : "dirty ") + (note.fetchPersistent() 1478 ? "persistent" : "this") + ";"); } 1481 1482 if (pkField && fetch) { 1485 return insn; 1486 } 1487 1488 if (pkField || !dfgField) { 1492 final Insn prev = insn.prev(); 1497 insn.remove(); 1498 1499 final AnnotationFragment frag1 = buildAccessAnnotation(note); 1501 affirm(frag1, "Illegal annotation of PK or non-dfg field."); 1503 final Insn last = prev.insert(frag1.annotation); 1508 noteStack(frag1.stackRequired - note.arg()); 1509 return last; 1510 } 1511 1512 final AnnotationFragment frag0 = buildBasicAnnotation(note); 1515 affirm(frag0, "Illegal annotation of dfg field."); { 1519 StackState state 1522 = new StackState(note.arg(), note.sig(), insn.prev()); 1523 minimizeStack(state); 1524 1525 if (false) { 1526 System.out.println(" state.argDepth = " + state.argDepth); 1528 System.out.print(" state.insn = "); state.insn.printInsn(System.out); 1530 System.out.print(" insn = "); insn.printInsn(System.out); 1532 } 1533 1534 Insn annotation = null; 1536 if (state.argDepth == 0) { 1537 annotation = frag0.annotation; 1540 noteStack(frag0.stackRequired); 1541 } else if (state.argDepth == 1) { 1542 annotation = Insn.create(opc_swap); 1547 annotation.append(frag0.annotation); 1548 annotation.append(Insn.create(opc_swap)); 1549 1550 noteStack(frag0.stackRequired - (note.arg()-1)); 1555 } else { 1556 Stack stackTypes = state.stackTypes; 1560 int depth = state.argDepth; 1561 int elem = stackTypes.size()-1; 1562 1563 int singleRegs = initialSingleRegs; 1564 int doubleRegs = 0; 1565 int regnums[] = new int[depth]; 1566 int regtotal = 0; 1567 1568 while (depth > 0) { 1570 int elemType = 1571 ((Integer )stackTypes.elementAt(elem--)).intValue(); 1572 int elemSize = Descriptor.elementSize(elemType); 1573 depth -= elemSize; 1574 int reg = ((elemSize == 1) 1575 ? tmpReg(singleRegs++) 1576 : tmpReg2(doubleRegs++)); 1577 regnums[regtotal++] = reg; 1578 1579 Insn store = InsnUtils.store(elemType, reg, pool); 1580 if (annotation == null) 1581 annotation = store; 1582 else 1583 annotation.append(store); 1584 } 1585 affirm((depth >= 0), 1586 "Stack underflow while computing save registers"); 1588 annotation.append(frag0.annotation); 1589 1590 while (regtotal > 0) 1591 annotation.append(InsnUtils.load( 1592 ((Integer )stackTypes.elementAt(++elem)).intValue(), 1593 regnums[--regtotal], pool)); 1594 1595 noteStack(frag0.stackRequired - note.arg()); 1596 } 1597 1598 state.insn.insert(annotation); 1599 } 1600 1601 return insn; 1602 } 1603 1604 private AnnotationFragment buildAccessAnnotation(final InsnNote note) { 1607 final int requiredStack; 1608 final Insn annotation; 1609 1610 final String targetClassName = note.targetClassName; 1611 final String targetFieldName = note.targetFieldName; 1612 final String targetPCRootClass = note.targetPCRootClass; 1613 1614 final boolean fetch = (note.fetchPersistent() || note.fetchThis()); 1616 final boolean dirty = (note.dirtyPersistent() || note.dirtyThis()); 1617 affirm((fetch ^ dirty), 1619 "Inconsistent fetch/dirty flags."); 1621 if (false) { 1623 final boolean dfgField = note.dfgFieldAccess(); 1624 final boolean pkField = note.pkFieldAccess(); 1625 1626 System.out.println(" build access annotation: " + targetClassName 1628 + "." + targetFieldName + " : " + (pkField ? "pk," : "!pk,") + (dfgField ? "dfg," : "!dfg,") + (fetch ? "fetch " : "dirty ") + (note.fetchPersistent() 1633 ? "persistent" : "this") + ";"); } 1636 1637 final int argSize = note.arg(); 1638 final String fieldSig = note.sig(); 1639 final int fieldType = Descriptor.elementType(fieldSig); 1640 final int fieldIndex = note.targetFieldIndex; 1641 if (false) { 1642 System.out.println(" argSize = " + argSize); System.out.println(" fieldSig = " + fieldSig); System.out.println(" fieldType = " + fieldType); System.out.println(" fieldIndex = " + fieldIndex); } 1647 1648 if (fetch) { 1649 Insn insn = annotation = Insn.create(opc_dup); 1651 insn = insn.append( 1652 Insn.create(opc_getfield, 1653 pool.addFieldRef( 1654 targetPCRootClass, 1655 JDOMetaData.JDOStateManagerFieldName, 1656 JDOMetaData.JDOStateManagerFieldSig))); 1657 1658 InsnTarget fetchDirty = new InsnTarget(); 1661 InsnTarget afterFetchDirty = new InsnTarget(); 1662 insn = insn.append(Insn.create(opc_dup)); 1663 insn = insn.append( 1664 Insn.create(opc_ifnonnull, fetchDirty)); 1665 1666 insn = insn.append(Insn.create(opc_pop)); 1668 insn = insn.append( 1669 Insn.create(opc_goto, afterFetchDirty)); 1670 1671 insn = insn.append(fetchDirty); 1673 1674 insn = insn.append(InsnUtils.integerConstant(fieldIndex, pool)); 1676 1677 requiredStack = 2; 1679 insn = insn.append( 1680 new InsnInterfaceInvoke( 1681 pool.addInterfaceMethodRef( 1682 JDOMetaData.JDOStateManagerPath, 1683 "prepareGetField", "(I)V"), requiredStack)); 1686 1687 insn = insn.append(afterFetchDirty); 1688 insn = insn.append(note.insn); 1689 } else { 1690 int singleRegs = 0; 1692 int doubleRegs = 0; 1693 1694 affirm(argSize > 0); 1696 final int reg = ((argSize == 1) 1697 ? tmpReg(singleRegs++) 1698 : tmpReg2(doubleRegs++)); 1699 Insn insn = annotation = InsnUtils.store(fieldType, reg, pool); 1700 1701 insn = insn.append(Insn.create(opc_dup)); 1703 insn = insn.append( 1704 Insn.create(opc_getfield, 1705 pool.addFieldRef( 1706 targetPCRootClass, 1707 JDOMetaData.JDOStateManagerFieldName, 1708 JDOMetaData.JDOStateManagerFieldSig))); 1709 1710 InsnTarget fetchDirty = new InsnTarget(); 1713 InsnTarget afterFetchDirty = new InsnTarget(); 1714 insn = insn.append(Insn.create(opc_dup)); 1715 insn = insn.append( 1716 Insn.create(opc_ifnonnull, fetchDirty)); 1717 1718 insn = insn.append(Insn.create(opc_pop)); 1720 affirm(argSize > 0); 1722 insn = insn.append(InsnUtils.load(fieldType, reg, pool)); 1723 insn = insn.append(note.insn); 1725 insn = insn.append( 1726 Insn.create(opc_goto, afterFetchDirty)); 1727 1728 insn = insn.append(fetchDirty); 1730 1731 insn = insn.append(InsnUtils.integerConstant(fieldIndex, pool)); 1733 1734 affirm(argSize > 0); 1736 insn = insn.append(InsnUtils.load(fieldType, reg, pool)); 1737 1738 switch(fieldType) { 1740 case T_BOOLEAN: 1741 requiredStack = 3; 1743 insn = insn.append( 1744 new InsnInterfaceInvoke( 1745 pool.addInterfaceMethodRef( 1746 JDOMetaData.JDOStateManagerPath, 1747 "setBooleanField", "(IB)B"), requiredStack)); 1750 insn = insn.append(Insn.create(opc_pop2)); 1752 break; 1753 case T_CHAR: 1754 requiredStack = 3; 1756 insn = insn.append( 1757 new InsnInterfaceInvoke( 1758 pool.addInterfaceMethodRef( 1759 JDOMetaData.JDOStateManagerPath, 1760 "setCharField", "(IC)C"), requiredStack)); 1763 insn = insn.append(Insn.create(opc_pop2)); 1765 break; 1766 case T_BYTE: 1767 requiredStack = 3; 1769 insn = insn.append( 1770 new InsnInterfaceInvoke( 1771 pool.addInterfaceMethodRef( 1772 JDOMetaData.JDOStateManagerPath, 1773 "setByteField", "(IZ)Z"), requiredStack)); 1776 insn = insn.append(Insn.create(opc_pop2)); 1778 break; 1779 case T_SHORT: 1780 requiredStack = 3; 1782 insn = insn.append( 1783 new InsnInterfaceInvoke( 1784 pool.addInterfaceMethodRef( 1785 JDOMetaData.JDOStateManagerPath, 1786 "setShortField", "(IS)S"), requiredStack)); 1789 insn = insn.append(Insn.create(opc_pop2)); 1791 break; 1792 case T_INT: 1793 requiredStack = 3; 1795 insn = insn.append( 1796 new InsnInterfaceInvoke( 1797 pool.addInterfaceMethodRef( 1798 JDOMetaData.JDOStateManagerPath, 1799 "setIntField", "(II)I"), requiredStack)); 1802 insn = insn.append(Insn.create(opc_pop2)); 1804 break; 1805 case T_LONG: 1806 requiredStack = 4; 1808 insn = insn.append( 1809 new InsnInterfaceInvoke( 1810 pool.addInterfaceMethodRef( 1811 JDOMetaData.JDOStateManagerPath, 1812 "setLongField", "(IJ)J"), requiredStack)); 1815 insn = insn.append(Insn.create(opc_pop2)); 1817 insn = insn.append(Insn.create(opc_pop)); 1818 break; 1819 case T_FLOAT: 1820 requiredStack = 3; 1822 insn = insn.append( 1823 new InsnInterfaceInvoke( 1824 pool.addInterfaceMethodRef( 1825 JDOMetaData.JDOStateManagerPath, 1826 "setFloatField", "(IF)F"), requiredStack)); 1829 insn = insn.append(Insn.create(opc_pop2)); 1831 break; 1832 case T_DOUBLE: 1833 requiredStack = 4; 1835 insn = insn.append( 1836 new InsnInterfaceInvoke( 1837 pool.addInterfaceMethodRef( 1838 JDOMetaData.JDOStateManagerPath, 1839 "setDoubleField", "(ID)D"), requiredStack)); 1842 insn = insn.append(Insn.create(opc_pop2)); 1844 insn = insn.append(Insn.create(opc_pop)); 1845 break; 1846 case TC_OBJECT: 1847 case TC_INTERFACE: 1848 requiredStack = 3; 1850 insn = insn.append( 1851 new InsnInterfaceInvoke( 1852 pool.addInterfaceMethodRef( 1853 JDOMetaData.JDOStateManagerPath, 1854 "setObjectField", "(ILjava/lang/Object;)Ljava/lang/Object;"), requiredStack)); 1857 1858 1871 insn = insn.append(Insn.create(opc_pop2)); 1873 break; 1874 default: 1875 throw new InternalError ("Unexpected field type"); } 1877 1878 insn = insn.append(afterFetchDirty); 1879 } 1880 1881 if (false) { 1883 System.out.println(" built annotation, " + "required stack = " + requiredStack); 1886 } 1887 1888 return new AnnotationFragment(annotation, requiredStack); 1889 } 1890 1891 1896 private AnnotationFragment buildBasicAnnotation(InsnNote note) { 1898 int requiredStack = 2; 1899 Insn basicAnnotation = null; 1900 1901 final String targetClassName = note.targetClassName; 1903 final String targetFieldName = note.targetFieldName; 1904 final String targetPCRootClass = note.targetPCRootClass; 1905 1906 final boolean fetch = (note.fetchPersistent() || note.fetchThis()); 1908 final boolean dirty = (note.dirtyPersistent() || note.dirtyThis()); 1909 affirm((fetch ^ dirty), 1911 "Inconsistent fetch/dirty flags."); 1913 if (false) { 1915 final boolean dfgField = note.dfgFieldAccess(); 1916 final boolean pkField = note.pkFieldAccess(); 1917 1918 System.out.println(" build basic annotation: " + targetClassName 1920 + "." + targetFieldName + " : " + (pkField ? "pk," : "!pk,") + (dfgField ? "dfg," : "!dfg,") + (fetch ? "fetch " : "dirty ") + (note.fetchPersistent() 1925 ? "persistent" : "this") + ";"); } 1928 1929 { 1931 Insn insn = null; 1932 1933 1935 basicAnnotation = insn = Insn.create(opc_dup); 1937 insn = insn.append( 1938 Insn.create(opc_getfield, 1939 pool.addFieldRef( 1940 targetPCRootClass, 1941 JDOMetaData.JDOFlagsFieldName, 1942 JDOMetaData.JDOFlagsFieldSig))); 1943 1944 InsnTarget afterFetchDirty = new InsnTarget(); 1947 insn = insn.append( 1948 Insn.create((fetch ? opc_ifle : opc_ifeq), 1949 afterFetchDirty)); 1950 1951 insn = insn.append(Insn.create(opc_dup)); 1953 insn = insn.append( 1954 Insn.create(opc_getfield, 1955 pool.addFieldRef( 1956 targetPCRootClass, 1957 JDOMetaData.JDOStateManagerFieldName, 1958 JDOMetaData.JDOStateManagerFieldSig))); 1959 1960 insn = insn.append( 1962 new InsnInterfaceInvoke( 1963 pool.addInterfaceMethodRef( 1964 JDOMetaData.JDOStateManagerPath, 1965 (fetch ? "loadForRead" : "loadForUpdate"), "()V"), 1)); 1968 1969 insn = insn.append(afterFetchDirty); 1970 } 1971 1972 if (false) { 1974 System.out.println(" built annotation, " + "required stack = " + requiredStack); 1977 } 1978 1979 return new AnnotationFragment(basicAnnotation, requiredStack); 1980 } 1981 1982 1987 2187 2188 2192 2219 2220 2225 private int tmpReg2(int idx) { 2226 if (tmpDoubleRegisters == null) 2227 tmpDoubleRegisters = new Vector (3); 2228 2229 while (tmpDoubleRegisters.size() <= idx) { 2232 final CodeAttribute codeAttr = method.codeAttribute(); 2233 final int reg = codeAttr.localsUsed(); 2234 tmpDoubleRegisters.addElement(new Integer (reg)); 2235 codeAttr.setLocalsUsed(reg+2); 2236 } 2237 2238 return ((Integer )tmpDoubleRegisters.elementAt(idx)).intValue(); 2239 } 2240 2241 2246 private int tmpReg(int idx) { 2247 if (tmpRegisters == null) 2248 tmpRegisters = new Vector (3); 2249 2250 while (tmpRegisters.size() <= idx) { 2253 final CodeAttribute codeAttr = method.codeAttribute(); 2254 final int reg = codeAttr.localsUsed(); 2255 tmpRegisters.addElement(new Integer (reg)); 2256 codeAttr.setLocalsUsed(reg+1); 2257 } 2258 return ((Integer )tmpRegisters.elementAt(idx)).intValue(); 2259 } 2260 2261 2264 2276 2277 2280 private void noteStack(int stk) { 2281 if (stk > annotationStack) 2282 annotationStack = (short)stk; 2283 } 2284 2285 2288 2295 2296 2298 2309 private Insn findArgDepositer(Insn currInsn, int argDepth) { 2310 Insn depositer = null; 2311 for (Insn i = currInsn.prev(); argDepth >= 0; i = i.prev()) { 2312 if (i.branches() || 2315 ((i instanceof InsnTarget) && ((InsnTarget)i).isBranchTarget())) 2316 break; 2317 2318 int nArgs = i.nStackArgs(); 2319 int nResults = i.nStackResults(); 2320 2321 if (argDepth - nResults < 0) { 2322 if (nResults > 1 && i.opcode() != opc_dup) 2328 break; 2329 depositer = i; 2330 2331 switch (i.opcode()) { 2333 case opc_dup: 2334 if (argDepth == 0) 2335 argDepth++; 2337 break; 2338 case opc_checkcast: 2339 break; 2341 default: 2342 return i; 2343 } 2344 } 2345 2346 argDepth += (nArgs - nResults); 2347 } 2348 2349 return depositer; 2350 } 2351 2352 2361 private void minimizeStack(StackState state) { 2362 Insn i = state.insn; 2363 int argDepth = state.argDepth; 2364 2365 Stack argTypesStack = new Stack (); 2366 Stack resultTypesStack = new Stack (); 2367 Stack stackTypes = new Stack (); 2368 copyStack(state.stackTypes, stackTypes); 2369 2370 for (; argDepth > 0; i = i.prev()) { 2371 if (i.branches() || 2375 ((i instanceof InsnTarget) 2376 && ((InsnTarget)i).isBranchTarget())) 2377 break; 2378 2379 int nArgs = i.nStackArgs(); 2380 int nResults = i.nStackResults(); 2381 String argTypes = i.argTypes(); 2382 String resultTypes = i.resultTypes(); 2383 2384 argDepth -= nResults; 2385 if (argDepth < 0) 2390 break; 2391 argDepth += nArgs; 2392 2393 if (i.opcode() == opc_swap) { 2394 Object x = stackTypes.pop(); 2395 Object y = stackTypes.pop(); 2396 stackTypes.push(x); 2397 stackTypes.push(y); 2398 } else { 2399 while (!argTypesStack.empty()) argTypesStack.pop(); 2401 while (!resultTypesStack.empty()) resultTypesStack.pop(); 2402 2403 Descriptor.computeStackTypes(argTypes, argTypesStack); 2404 Descriptor.computeStackTypes(resultTypes, resultTypesStack); 2405 2406 int expectWords = 0; 2407 while (!resultTypesStack.empty()) 2408 expectWords += Descriptor.elementSize( 2409 ((Integer ) resultTypesStack.pop()).intValue()); 2410 2411 while (expectWords > 0) 2412 expectWords -= Descriptor.elementSize( 2413 ((Integer ) stackTypes.pop()).intValue()); 2414 2415 if (expectWords < 0) { 2416 return; 2419 } 2420 2421 transferStackArgs(argTypesStack, stackTypes); 2422 } 2423 2424 if (argDepth >= 0 && argDepth < state.argDepth && 2425 knownTypes(stackTypes, argDepth)) { 2426 state.argDepth = argDepth; 2427 state.insn = i.prev(); 2428 copyStack(stackTypes, state.stackTypes); 2429 } 2430 } 2431 } 2432 2433 2435 private final void transferStackArgs(Stack fromStack, Stack toStack) { 2436 if (!fromStack.empty()) { 2437 Object o = fromStack.pop(); 2438 transferStackArgs(fromStack, toStack); 2439 toStack.push(o); 2440 } 2441 } 2442 2443 2444 private final void copyStack(Stack fromStack, Stack toStack) { 2445 while (!toStack.empty()) 2446 toStack.pop(); 2447 2448 for (int i=0; i<fromStack.size(); i++) 2450 toStack.addElement(fromStack.elementAt(i)); 2451 } 2452 2453 2454 private final boolean knownTypes(Stack stack, int nWords) { 2455 for (int i=stack.size()-1; i>= 0 && nWords > 0; i--) { 2457 int words = 0; 2458 switch (((Integer )stack.elementAt(i)).intValue()) { 2459 case T_UNKNOWN: 2460 case T_WORD: 2461 case T_TWOWORD: 2462 return false; 2463 2464 case T_BOOLEAN: 2465 case T_CHAR: 2466 case T_FLOAT: 2467 case T_BYTE: 2468 case T_SHORT: 2469 case T_INT: 2470 case TC_OBJECT: 2471 case TC_INTERFACE: 2472 case TC_STRING: 2473 words = 1; 2474 2475 case T_DOUBLE: 2476 case T_LONG: 2477 words = 2; 2478 2479 default: 2480 break; 2481 } 2482 nWords -= words; 2483 } 2484 return true; 2485 } 2486 2487 2489 2492 private final void addNoteList(InsnNote note) { 2494 insnNotes.put(note.insn, note); 2495 } 2496 2497 2500 private final InsnNote getNoteList(Insn insn) { 2502 return (InsnNote)insnNotes.get(insn); 2503 } 2504} 2505 2506 2508 2512 2523 2524 2529 2555 2556 2561 2568 2569 2571 2575class InsnNote 2576 extends Support 2577 implements AnnotationConstants { 2578 final Insn insn; 2580 int insnFlags; 2581 final int argWord; 2582 2586 final String stackSig; 2587 2588 final String targetClassName; 2590 final String targetFieldName; 2591 final int targetFieldIndex; 2592 final String targetPCRootClass; 2593 2597 2598 2603 InsnNote next() { 2604 return null; 2605 } 2606 2607 2617 final String sig() { 2618 return stackSig; 2619 } 2620 2621 2627 2628 2631 final int arg() { 2632 return argWord; 2633 } 2634 2635 final boolean fetchThis() { 2636 return (insnFlags & FetchThis) != 0; 2637 } 2638 2639 2645 2646 final boolean dirtyThis() { 2647 return (insnFlags & DirtyThis) != 0; 2648 } 2649 2650 2656 2657 2663 2664 2674 2675 final boolean fetchPersistent() { 2676 return (insnFlags & FetchPersistent) != 0; 2677 } 2678 2679 final boolean dirtyPersistent() { 2680 return (insnFlags & DirtyPersistent) != 0; 2681 } 2682 2683 final boolean dfgFieldAccess() { 2685 return (insnFlags & DFGField) != 0; 2686 } 2687 2688 final boolean pkFieldAccess() { 2690 return (insnFlags & PKField) != 0; 2691 } 2692 2693 2715 2716 2717 2727 2728 2735 InsnNote(Insn i, int flags, int argWord, 2736 String stackSig, 2737 String targetClassName, 2738 String targetFieldName, 2739 int targetFieldIndex, 2740 String targetPCRootClass) { 2741 2746 insn = i; 2747 insnFlags = flags; 2748 this.stackSig = stackSig; 2749 this.argWord = argWord; 2750 2754 this.targetClassName = targetClassName; 2755 this.targetFieldName = targetFieldName; 2756 this.targetFieldIndex = targetFieldIndex; 2757 this.targetPCRootClass = targetPCRootClass; 2758 2759 affirm(!(insn == null 2761 || argWord < 0 2762 || targetClassName == null 2763 || targetFieldName == null 2764 || targetFieldIndex < 0 2765 || targetPCRootClass == null), 2766 "Inconsistent instruction annotation note."); } 2768} 2769 2770 2775 2789 2790 2792 2796class StackState implements VMConstants { 2797 2798 int argDepth; 2799 2800 2801 Stack stackTypes; 2802 2803 2804 Insn insn; 2805 2806 StackState(int depth, String stackSig, Insn i) { 2807 stackTypes = new Stack (); 2808 Descriptor.computeStackTypes(stackSig, stackTypes); 2809 argDepth = depth; 2810 insn = i; 2811 } 2812} 2813 2814 2819class AnnotationFragment { 2820 Insn annotation; 2821 int stackRequired; 2822 2823 AnnotationFragment(Insn i, int stack) { 2824 annotation = i; 2825 stackRequired = stack; 2826 } 2827} 2828 2829 2831 | Popular Tags |