src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/SystemModulesPlugin.java
changeset 52814 abccada595dd
parent 52515 746df0ae4fe1
child 59133 580fb715b29d
equal deleted inserted replaced
52813:767678b5e61b 52814:abccada595dd
    50 import java.util.List;
    50 import java.util.List;
    51 import java.util.Map;
    51 import java.util.Map;
    52 import java.util.Objects;
    52 import java.util.Objects;
    53 import java.util.Optional;
    53 import java.util.Optional;
    54 import java.util.Set;
    54 import java.util.Set;
       
    55 import java.util.TreeMap;
    55 import java.util.TreeSet;
    56 import java.util.TreeSet;
    56 import java.util.function.IntSupplier;
    57 import java.util.function.IntSupplier;
    57 import java.util.function.Supplier;
    58 import java.util.function.Supplier;
    58 import java.util.stream.Collectors;
    59 import java.util.stream.Collectors;
    59 
    60 
   923             // new Map$Entry[size]
   924             // new Map$Entry[size]
   924             pushInt(mv, map.size());
   925             pushInt(mv, map.size());
   925             mv.visitTypeInsn(ANEWARRAY, "java/util/Map$Entry");
   926             mv.visitTypeInsn(ANEWARRAY, "java/util/Map$Entry");
   926 
   927 
   927             int index = 0;
   928             int index = 0;
   928             for (Map.Entry<String, Set<String>> e : map.entrySet()) {
   929             for (var e : new TreeMap<>(map).entrySet()) {
   929                 String name = e.getKey();
   930                 String name = e.getKey();
   930                 Set<String> s = e.getValue();
   931                 Set<String> s = e.getValue();
   931 
   932 
   932                 mv.visitInsn(DUP);
   933                 mv.visitInsn(DUP);
   933                 pushInt(mv, index);
   934                 pushInt(mv, index);
   969             // use Set.of(Object) or Set.of(Object, Object) when fewer
   970             // use Set.of(Object) or Set.of(Object, Object) when fewer
   970             if (size > 2) {
   971             if (size > 2) {
   971                 pushInt(mv, size);
   972                 pushInt(mv, size);
   972                 mv.visitTypeInsn(ANEWARRAY, "java/lang/String");
   973                 mv.visitTypeInsn(ANEWARRAY, "java/lang/String");
   973                 int i = 0;
   974                 int i = 0;
   974                 for (String element : set) {
   975                 for (String element : sorted(set)) {
   975                     mv.visitInsn(DUP);
   976                     mv.visitInsn(DUP);
   976                     pushInt(mv, i);
   977                     pushInt(mv, i);
   977                     mv.visitLdcInsn(element);
   978                     mv.visitLdcInsn(element);
   978                     mv.visitInsn(AASTORE);
   979                     mv.visitInsn(AASTORE);
   979                     i++;
   980                     i++;
   983                         "of",
   984                         "of",
   984                         "([Ljava/lang/Object;)Ljava/util/Set;",
   985                         "([Ljava/lang/Object;)Ljava/util/Set;",
   985                         true);
   986                         true);
   986             } else {
   987             } else {
   987                 StringBuilder sb = new StringBuilder("(");
   988                 StringBuilder sb = new StringBuilder("(");
   988                 for (String element : set) {
   989                 for (String element : sorted(set)) {
   989                     mv.visitLdcInsn(element);
   990                     mv.visitLdcInsn(element);
   990                     sb.append("Ljava/lang/Object;");
   991                     sb.append("Ljava/lang/Object;");
   991                 }
   992                 }
   992                 sb.append(")Ljava/util/Set;");
   993                 sb.append(")Ljava/util/Set;");
   993                 mv.visitMethodInsn(INVOKESTATIC,
   994                 mv.visitMethodInsn(INVOKESTATIC,
  1144             void requires(Set<Requires> requires) {
  1145             void requires(Set<Requires> requires) {
  1145                 mv.visitVarInsn(ALOAD, BUILDER_VAR);
  1146                 mv.visitVarInsn(ALOAD, BUILDER_VAR);
  1146                 pushInt(mv, requires.size());
  1147                 pushInt(mv, requires.size());
  1147                 mv.visitTypeInsn(ANEWARRAY, "java/lang/module/ModuleDescriptor$Requires");
  1148                 mv.visitTypeInsn(ANEWARRAY, "java/lang/module/ModuleDescriptor$Requires");
  1148                 int arrayIndex = 0;
  1149                 int arrayIndex = 0;
  1149                 for (Requires require : requires) {
  1150                 for (Requires require : sorted(requires)) {
  1150                     String compiledVersion = null;
  1151                     String compiledVersion = null;
  1151                     if (require.compiledVersion().isPresent()) {
  1152                     if (require.compiledVersion().isPresent()) {
  1152                         compiledVersion = require.compiledVersion().get().toString();
  1153                         compiledVersion = require.compiledVersion().get().toString();
  1153                     }
  1154                     }
  1154 
  1155 
  1190             void exports(Set<Exports> exports) {
  1191             void exports(Set<Exports> exports) {
  1191                 mv.visitVarInsn(ALOAD, BUILDER_VAR);
  1192                 mv.visitVarInsn(ALOAD, BUILDER_VAR);
  1192                 pushInt(mv, exports.size());
  1193                 pushInt(mv, exports.size());
  1193                 mv.visitTypeInsn(ANEWARRAY, "java/lang/module/ModuleDescriptor$Exports");
  1194                 mv.visitTypeInsn(ANEWARRAY, "java/lang/module/ModuleDescriptor$Exports");
  1194                 int arrayIndex = 0;
  1195                 int arrayIndex = 0;
  1195                 for (Exports export : exports) {
  1196                 for (Exports export : sorted(exports)) {
  1196                     mv.visitInsn(DUP);    // arrayref
  1197                     mv.visitInsn(DUP);    // arrayref
  1197                     pushInt(mv, arrayIndex++);
  1198                     pushInt(mv, arrayIndex++);
  1198                     newExports(export.modifiers(), export.source(), export.targets());
  1199                     newExports(export.modifiers(), export.source(), export.targets());
  1199                     mv.visitInsn(AASTORE);
  1200                     mv.visitInsn(AASTORE);
  1200                 }
  1201                 }
  1243             void opens(Set<Opens> opens) {
  1244             void opens(Set<Opens> opens) {
  1244                 mv.visitVarInsn(ALOAD, BUILDER_VAR);
  1245                 mv.visitVarInsn(ALOAD, BUILDER_VAR);
  1245                 pushInt(mv, opens.size());
  1246                 pushInt(mv, opens.size());
  1246                 mv.visitTypeInsn(ANEWARRAY, "java/lang/module/ModuleDescriptor$Opens");
  1247                 mv.visitTypeInsn(ANEWARRAY, "java/lang/module/ModuleDescriptor$Opens");
  1247                 int arrayIndex = 0;
  1248                 int arrayIndex = 0;
  1248                 for (Opens open : opens) {
  1249                 for (Opens open : sorted(opens)) {
  1249                     mv.visitInsn(DUP);    // arrayref
  1250                     mv.visitInsn(DUP);    // arrayref
  1250                     pushInt(mv, arrayIndex++);
  1251                     pushInt(mv, arrayIndex++);
  1251                     newOpens(open.modifiers(), open.source(), open.targets());
  1252                     newOpens(open.modifiers(), open.source(), open.targets());
  1252                     mv.visitInsn(AASTORE);
  1253                     mv.visitInsn(AASTORE);
  1253                 }
  1254                 }
  1308             void provides(Collection<Provides> provides) {
  1309             void provides(Collection<Provides> provides) {
  1309                 mv.visitVarInsn(ALOAD, BUILDER_VAR);
  1310                 mv.visitVarInsn(ALOAD, BUILDER_VAR);
  1310                 pushInt(mv, provides.size());
  1311                 pushInt(mv, provides.size());
  1311                 mv.visitTypeInsn(ANEWARRAY, "java/lang/module/ModuleDescriptor$Provides");
  1312                 mv.visitTypeInsn(ANEWARRAY, "java/lang/module/ModuleDescriptor$Provides");
  1312                 int arrayIndex = 0;
  1313                 int arrayIndex = 0;
  1313                 for (Provides provide : provides) {
  1314                 for (Provides provide : sorted(provides)) {
  1314                     mv.visitInsn(DUP);    // arrayref
  1315                     mv.visitInsn(DUP);    // arrayref
  1315                     pushInt(mv, arrayIndex++);
  1316                     pushInt(mv, arrayIndex++);
  1316                     newProvides(provide.service(), provide.providers());
  1317                     newProvides(provide.service(), provide.providers());
  1317                     mv.visitInsn(AASTORE);
  1318                     mv.visitInsn(AASTORE);
  1318                 }
  1319                 }
  1418                 newModuleHashesBuilder();
  1419                 newModuleHashesBuilder();
  1419 
  1420 
  1420                 // Invoke ModuleHashes.Builder::hashForModule
  1421                 // Invoke ModuleHashes.Builder::hashForModule
  1421                 recordedHashes
  1422                 recordedHashes
  1422                     .names()
  1423                     .names()
       
  1424                     .stream()
       
  1425                     .sorted()
  1423                     .forEach(mn -> hashForModule(mn, recordedHashes.hashFor(mn)));
  1426                     .forEach(mn -> hashForModule(mn, recordedHashes.hashFor(mn)));
  1424 
  1427 
  1425                 // Put ModuleHashes into the hashes array
  1428                 // Put ModuleHashes into the hashes array
  1426                 pushModuleHashes();
  1429                 pushModuleHashes();
  1427             }
  1430             }
  1598          * for a given set of elements and assign to a local variable slot.
  1601          * for a given set of elements and assign to a local variable slot.
  1599          * When there is only one single reference to a Set<T>,
  1602          * When there is only one single reference to a Set<T>,
  1600          * it will reuse defaultVarIndex.  For a Set with multiple references,
  1603          * it will reuse defaultVarIndex.  For a Set with multiple references,
  1601          * it will use a new local variable retrieved from the nextLocalVar
  1604          * it will use a new local variable retrieved from the nextLocalVar
  1602          */
  1605          */
  1603         class SetBuilder<T> {
  1606         class SetBuilder<T extends Comparable<T>> {
  1604             private final Set<T> elements;
  1607             private final Set<T> elements;
  1605             private final int defaultVarIndex;
  1608             private final int defaultVarIndex;
  1606             private final IntSupplier nextLocalVar;
  1609             private final IntSupplier nextLocalVar;
  1607             private int refCount;
  1610             private int refCount;
  1608             private int localVarIndex;
  1611             private int localVarIndex;
  1658 
  1661 
  1659             private void generateSetOf(int index) {
  1662             private void generateSetOf(int index) {
  1660                 if (elements.size() <= 10) {
  1663                 if (elements.size() <= 10) {
  1661                     // call Set.of(e1, e2, ...)
  1664                     // call Set.of(e1, e2, ...)
  1662                     StringBuilder sb = new StringBuilder("(");
  1665                     StringBuilder sb = new StringBuilder("(");
  1663                     for (T t : elements) {
  1666                     for (T t : sorted(elements)) {
  1664                         sb.append("Ljava/lang/Object;");
  1667                         sb.append("Ljava/lang/Object;");
  1665                         visitElement(t, mv);
  1668                         visitElement(t, mv);
  1666                     }
  1669                     }
  1667                     sb.append(")Ljava/util/Set;");
  1670                     sb.append(")Ljava/util/Set;");
  1668                     mv.visitMethodInsn(INVOKESTATIC, "java/util/Set",
  1671                     mv.visitMethodInsn(INVOKESTATIC, "java/util/Set",
  1670                 } else {
  1673                 } else {
  1671                     // call Set.of(E... elements)
  1674                     // call Set.of(E... elements)
  1672                     pushInt(mv, elements.size());
  1675                     pushInt(mv, elements.size());
  1673                     mv.visitTypeInsn(ANEWARRAY, "java/lang/String");
  1676                     mv.visitTypeInsn(ANEWARRAY, "java/lang/String");
  1674                     int arrayIndex = 0;
  1677                     int arrayIndex = 0;
  1675                     for (T t : elements) {
  1678                     for (T t : sorted(elements)) {
  1676                         mv.visitInsn(DUP);    // arrayref
  1679                         mv.visitInsn(DUP);    // arrayref
  1677                         pushInt(mv, arrayIndex);
  1680                         pushInt(mv, arrayIndex);
  1678                         visitElement(t, mv);  // value
  1681                         visitElement(t, mv);  // value
  1679                         mv.visitInsn(AASTORE);
  1682                         mv.visitInsn(AASTORE);
  1680                         arrayIndex++;
  1683                         arrayIndex++;
  1688 
  1691 
  1689         /*
  1692         /*
  1690          * Generates bytecode to create one single instance of EnumSet
  1693          * Generates bytecode to create one single instance of EnumSet
  1691          * for a given set of modifiers and assign to a local variable slot.
  1694          * for a given set of modifiers and assign to a local variable slot.
  1692          */
  1695          */
  1693         class EnumSetBuilder<T> extends SetBuilder<T> {
  1696         class EnumSetBuilder<T extends Comparable<T>> extends SetBuilder<T> {
  1694 
  1697 
  1695             private final String className;
  1698             private final String className;
  1696 
  1699 
  1697             EnumSetBuilder(Set<T> modifiers, String className,
  1700             EnumSetBuilder(Set<T> modifiers, String className,
  1698                            int defaultVarIndex,
  1701                            int defaultVarIndex,
  1786         mv.visitCode();
  1789         mv.visitCode();
  1787         pushInt(mv, map.size());
  1790         pushInt(mv, map.size());
  1788         mv.visitTypeInsn(ANEWARRAY, "java/lang/String");
  1791         mv.visitTypeInsn(ANEWARRAY, "java/lang/String");
  1789 
  1792 
  1790         int index = 0;
  1793         int index = 0;
  1791         for (String moduleName : map.keySet()) {
  1794         for (String moduleName : sorted(map.keySet())) {
  1792             mv.visitInsn(DUP);                  // arrayref
  1795             mv.visitInsn(DUP);                  // arrayref
  1793             pushInt(mv, index);
  1796             pushInt(mv, index);
  1794             mv.visitLdcInsn(moduleName);
  1797             mv.visitLdcInsn(moduleName);
  1795             mv.visitInsn(AASTORE);
  1798             mv.visitInsn(AASTORE);
  1796             index++;
  1799             index++;
  1809         mv.visitCode();
  1812         mv.visitCode();
  1810         pushInt(mv, map.size());
  1813         pushInt(mv, map.size());
  1811         mv.visitTypeInsn(ANEWARRAY, "java/lang/String");
  1814         mv.visitTypeInsn(ANEWARRAY, "java/lang/String");
  1812 
  1815 
  1813         index = 0;
  1816         index = 0;
  1814         for (String className : map.values()) {
  1817         for (String className : sorted(map.values())) {
  1815             mv.visitInsn(DUP);                  // arrayref
  1818             mv.visitInsn(DUP);                  // arrayref
  1816             pushInt(mv, index);
  1819             pushInt(mv, index);
  1817             mv.visitLdcInsn(className.replace('/', '.'));
  1820             mv.visitLdcInsn(className.replace('/', '.'));
  1818             mv.visitInsn(AASTORE);
  1821             mv.visitInsn(AASTORE);
  1819             index++;
  1822             index++;
  1827         String rn = "/java.base/" + SYSTEM_MODULES_MAP_CLASS + ".class";
  1830         String rn = "/java.base/" + SYSTEM_MODULES_MAP_CLASS + ".class";
  1828         ResourcePoolEntry e = ResourcePoolEntry.create(rn, cw.toByteArray());
  1831         ResourcePoolEntry e = ResourcePoolEntry.create(rn, cw.toByteArray());
  1829         out.add(e);
  1832         out.add(e);
  1830 
  1833 
  1831         return rn;
  1834         return rn;
       
  1835     }
       
  1836 
       
  1837     /**
       
  1838      * Returns a sorted copy of a collection.
       
  1839      *
       
  1840      * This is useful to ensure a deterministic iteration order.
       
  1841      *
       
  1842      * @return a sorted copy of the given collection.
       
  1843      */
       
  1844     private static <T extends Comparable<T>> List<T> sorted(Collection<T> c) {
       
  1845         var l = new ArrayList<T>(c);
       
  1846         Collections.sort(l);
       
  1847         return l;
  1832     }
  1848     }
  1833 
  1849 
  1834     /**
  1850     /**
  1835      * Pushes an int constant
  1851      * Pushes an int constant
  1836      */
  1852      */