# HG changeset patch # User jlahoda # Date 1589810185 -7200 # Mon May 18 15:56:25 2020 +0200 # Node ID 9bd428c73f8c3cd52f6e94391d363c332bba9e5b # Parent f1f88e6fad021cc479237f6eab6d0812b66b23cc [mq]: 8244763-create-symbols diff --git a/make/langtools/src/classes/build/tools/symbolgenerator/CreateSymbols.java b/make/langtools/src/classes/build/tools/symbolgenerator/CreateSymbols.java --- a/make/langtools/src/classes/build/tools/symbolgenerator/CreateSymbols.java +++ b/make/langtools/src/classes/build/tools/symbolgenerator/CreateSymbols.java @@ -31,6 +31,7 @@ import build.tools.symbolgenerator.CreateSymbols .ModuleHeaderDescription .RequiresDescription; + import java.io.BufferedInputStream; import java.io.BufferedReader; import java.io.BufferedOutputStream; @@ -43,6 +44,7 @@ import java.io.OutputStream; import java.io.StringWriter; import java.io.Writer; +import java.nio.charset.StandardCharsets; import java.nio.file.Files; import java.nio.file.FileVisitResult; import java.nio.file.FileVisitor; @@ -220,7 +222,7 @@ long timestamp, String currentVersion, String systemModules) throws IOException { LoadDescriptions data = load(ctDescriptionFileExtra != null ? Paths.get(ctDescriptionFileExtra) : null, - Paths.get(ctDescriptionFile), null); + Paths.get(ctDescriptionFile)); splitHeaders(data.classes); @@ -303,7 +305,7 @@ public static String EXTENSION = ".sig"; - LoadDescriptions load(Path ctDescriptionWithExtraContent, Path ctDescriptionOpen, String deletePlatform) throws IOException { + LoadDescriptions load(Path ctDescriptionWithExtraContent, Path ctDescriptionOpen) throws IOException { Map platforms = new LinkedHashMap<>(); if (ctDescriptionWithExtraContent != null && Files.isRegularFile(ctDescriptionWithExtraContent)) { @@ -317,8 +319,7 @@ case "platform": PlatformInput platform = PlatformInput.load(ctDescriptionWithExtraContent, reader); - if (!platform.version.equals(deletePlatform)) - platforms.put(platform.version, platform); + platforms.put(platform.version, platform); reader.moveNext(); break; default: @@ -336,13 +337,11 @@ case "generate": String[] platformsAttr = reader.attributes.get("platforms").split(":"); generatePlatforms = new HashSet<>(List.of(platformsAttr)); - generatePlatforms.remove(deletePlatform); reader.moveNext(); break; case "platform": PlatformInput platform = PlatformInput.load(ctDescriptionOpen, reader); - if (!platform.version.equals(deletePlatform) && - !platforms.containsKey(platform.version)) + if (!platforms.containsKey(platform.version)) platforms.put(platform.version, platform); reader.moveNext(); break; @@ -408,18 +407,28 @@ ClassList result = new ClassList(); - for (ClassDescription desc : classes.values()) { + classes.values().forEach(result::add); + return new LoadDescriptions(result, + modules, + new ArrayList<>(platforms.values())); + } + + private static void removeVersion(LoadDescriptions load, String deletePlatform) { + for (Iterator it = load.classes.iterator(); it.hasNext();) { + ClassDescription desc = it.next(); Iterator chdIt = desc.header.iterator(); while (chdIt.hasNext()) { ClassHeaderDescription chd = chdIt.next(); - chd.versions = reduce(chd.versions, generatePlatforms); - if (chd.versions.isEmpty()) + chd.versions = removeVersion(chd.versions, deletePlatform); + if (chd.versions.isEmpty()) { chdIt.remove(); + } } if (desc.header.isEmpty()) { + it.remove(); continue; } @@ -428,7 +437,7 @@ while (methodIt.hasNext()) { MethodDescription method = methodIt.next(); - method.versions = reduce(method.versions, generatePlatforms); + method.versions = removeVersion(method.versions, deletePlatform); if (method.versions.isEmpty()) methodIt.remove(); } @@ -438,37 +447,29 @@ while (fieldIt.hasNext()) { FieldDescription field = fieldIt.next(); - field.versions = reduce(field.versions, generatePlatforms); + field.versions = removeVersion(field.versions, deletePlatform); if (field.versions.isEmpty()) fieldIt.remove(); } - - result.add(desc); } - Map moduleList = new HashMap<>(); - - for (ModuleDescription desc : modules.values()) { + for (Iterator it = load.modules.values().iterator(); it.hasNext();) { + ModuleDescription desc = it.next(); Iterator mhdIt = desc.header.iterator(); while (mhdIt.hasNext()) { ModuleHeaderDescription mhd = mhdIt.next(); - mhd.versions = reduce(mhd.versions, generatePlatforms); + mhd.versions = removeVersion(mhd.versions, deletePlatform); if (mhd.versions.isEmpty()) mhdIt.remove(); } if (desc.header.isEmpty()) { + it.remove(); continue; } - - moduleList.put(desc.name, desc); } - - return new LoadDescriptions(result, - moduleList, - new ArrayList<>(platforms.values())); } static final class LoadDescriptions { @@ -550,6 +551,17 @@ return sb.toString(); } + private static String removeVersion(String original, String remove) { + StringBuilder sb = new StringBuilder(); + + for (char v : original.toCharArray()) { + if (v != remove.charAt(0)) { + sb.append(v); + } + } + return sb.toString(); + } + private static class PlatformInput { public final String version; public final String basePlatform; @@ -1258,24 +1270,9 @@ Map modules = new HashMap<>(); for (VersionDescription desc : versions) { - List classFileData = new ArrayList<>(); - - try (BufferedReader descIn = - Files.newBufferedReader(Paths.get(desc.classes))) { - String line; - while ((line = descIn.readLine()) != null) { - ByteArrayOutputStream data = new ByteArrayOutputStream(); - for (int i = 0; i < line.length(); i += 2) { - String hex = line.substring(i, i + 2); - data.write(Integer.parseInt(hex, 16)); - } - classFileData.add(data.toByteArray()); - } - } catch (IOException ex) { - throw new IllegalStateException(ex); - } - - loadVersionClasses(classes, modules, classFileData, excludesIncludes, desc.version); + Iterable classFileData = loadClassData(desc.classes); + + loadVersionClasses(classes, modules, classFileData, excludesIncludes, desc.version, null); } List platforms = @@ -1286,7 +1283,7 @@ null)) .collect(Collectors.toList()); - dumpDescriptions(classes, modules, platforms, descDest.resolve("symbols"), args); + dumpDescriptions(classes, modules, platforms, Set.of(), descDest.resolve("symbols"), args); } //where: private static final String DO_NO_MODIFY = @@ -1319,11 +1316,33 @@ "# ##########################################################\n" + "#\n"; + private Iterable loadClassData(String path) { + List classFileData = new ArrayList<>(); + + try (BufferedReader descIn = + Files.newBufferedReader(Paths.get(path))) { + String line; + while ((line = descIn.readLine()) != null) { + ByteArrayOutputStream data = new ByteArrayOutputStream(); + for (int i = 0; i < line.length(); i += 2) { + String hex = line.substring(i, i + 2); + data.write(Integer.parseInt(hex, 16)); + } + classFileData.add(data.toByteArray()); + } + } catch (IOException ex) { + throw new IllegalStateException(ex); + } + + return classFileData; + } + private void loadVersionClasses(ClassList classes, Map modules, Iterable classData, ExcludeIncludeList excludesIncludes, - String version) { + String version, + String baseline) { Map currentVersionModules = new HashMap<>(); @@ -1447,12 +1466,12 @@ ClassDescription existing = classes.find(clazz.name, true); if (existing != null) { - addClassHeader(existing, header, version); + addClassHeader(existing, header, version, baseline); for (MethodDescription currentMethod : clazz.methods) { - addMethod(existing, currentMethod, version); + addMethod(existing, currentMethod, version, baseline); } for (FieldDescription currentField : clazz.fields) { - addField(existing, currentField, version); + addField(existing, currentField, version, baseline); } } else { classes.add(clazz); @@ -1489,6 +1508,7 @@ private void dumpDescriptions(ClassList classes, Map modules, List versions, + Set forceWriteVersions, Path ctDescriptionFile, String[] args) throws IOException { classes.sort(); @@ -1555,7 +1575,7 @@ for (PlatformInput desc : versions) { List files = desc.files; - if (files == null) { + if (files == null || forceWriteVersions.contains(desc.version)) { files = new ArrayList<>(); for (Entry> e : module2Classes.entrySet()) { StringWriter data = new StringWriter(); @@ -1573,9 +1593,33 @@ String dataString = data.toString(); if (!dataString.isEmpty()) { - try (Writer out = Files.newBufferedWriter(f)) { - out.append(DO_NO_MODIFY.replace("{YEAR}", String.valueOf(year))); - out.write(dataString); + String existingYear = null; + boolean hasChange = true; + if (Files.isReadable(f)) { + String oldContent = Files.readString(f, StandardCharsets.UTF_8); + int yearPos = DO_NO_MODIFY.indexOf("{YEAR}"); + String headerPattern = + Pattern.quote(DO_NO_MODIFY.substring(0, yearPos)) + + "([0-9]+)(, [0-9]+)?" + + Pattern.quote(DO_NO_MODIFY.substring(yearPos + "{YEAR}".length())); + String pattern = headerPattern + + Pattern.quote(dataString); + Matcher m = Pattern.compile(pattern, Pattern.MULTILINE).matcher(oldContent); + if (m.matches()) { + hasChange = false; + } else { + m = Pattern.compile(headerPattern).matcher(oldContent); + if (m.find()) { + existingYear = m.group(1); + } + } + } + if (hasChange) { + try (Writer out = Files.newBufferedWriter(f, StandardCharsets.UTF_8)) { + String yearSpec = (existingYear != null ? existingYear + ", " : "") + String.valueOf(year); + out.append(DO_NO_MODIFY.replace("{YEAR}", yearSpec)); + out.write(dataString); + } } files.add(f.getFileName().toString()); } @@ -1617,15 +1661,17 @@ } } - public void createIncrementalBaseLine(String ctDescriptionFile, - String excludeFile, - String[] args) throws IOException { - String specVersion = System.getProperty("java.specification.version"); + private void incrementalUpdate(String ctDescriptionFile, + String excludeFile, + String version, + Iterable classBytes, + Function baseline, + String[] args) throws IOException { String currentVersion = - Integer.toString(Integer.parseInt(specVersion), Character.MAX_RADIX); + Integer.toString(Integer.parseInt(version), Character.MAX_RADIX); currentVersion = currentVersion.toUpperCase(Locale.ROOT); Path ctDescriptionPath = Paths.get(ctDescriptionFile).toAbsolutePath(); - LoadDescriptions data = load(null, ctDescriptionPath, currentVersion); + LoadDescriptions data = load(null, ctDescriptionPath); ClassList classes = data.classes; Map modules = data.modules; @@ -1634,23 +1680,64 @@ ExcludeIncludeList excludeList = ExcludeIncludeList.create(excludeFile); + loadVersionClasses(classes, modules, classBytes, excludeList, "$", version); + + removeVersion(data, version); + + for (ClassDescription clazzDesc : data.classes) { + for (ClassHeaderDescription header : clazzDesc.header) { + header.versions = header.versions.replace("$", version); + } + for (MethodDescription method : clazzDesc.methods) { + method.versions = method.versions.replace("$", version); + } + for (FieldDescription field : clazzDesc.fields) { + field.versions = field.versions.replace("$", version); + } + } + + if (versions.stream().noneMatch(inp -> version.equals(inp.version))) { + versions.add(new PlatformInput(null, currentVersion, baseline.apply(data), null)); + } + + Set writeVersions = new HashSet<>(); + + writeVersions.add(version); + + //re-write all platforms that have version as their basline: + versions.stream() + .filter(inp -> version.equals(inp.basePlatform)) + .map(inp -> inp.version) + .forEach(writeVersions::add); + dumpDescriptions(classes, modules, versions, writeVersions, ctDescriptionPath, args); + } + + public void createIncrementalBaseLineFromDataFile(String ctDescriptionFile, + String excludeFile, + String version, + String dataFile, + String baseline, + String[] args) throws IOException { + incrementalUpdate(ctDescriptionFile, excludeFile, version, loadClassData(dataFile), x -> baseline, args); + } + + public void createIncrementalBaseLine(String ctDescriptionFile, + String excludeFile, + String[] args) throws IOException { + String specVersion = System.getProperty("java.specification.version"); Iterable classBytes = dumpCurrentClasses(); - loadVersionClasses(classes, modules, classBytes, excludeList, currentVersion); - - String baseline; - - if (versions.isEmpty()) { - baseline = null; - } else { - baseline = versions.stream() - .sorted((v1, v2) -> v2.version.compareTo(v1.version)) - .findFirst() - .get() - .version; - } - - versions.add(new PlatformInput(null, currentVersion, baseline, null)); - dumpDescriptions(classes, modules, versions, ctDescriptionPath, args); + Function baseline = data -> { + if (data.versions.isEmpty()) { + return null; + } else { + return data.versions.stream() + .sorted((v1, v2) -> v2.version.compareTo(v1.version)) + .findFirst() + .get() + .version; + } + }; + incrementalUpdate(ctDescriptionFile, excludeFile, specVersion, classBytes, baseline, args); } private List dumpCurrentClasses() throws IOException { @@ -1744,7 +1831,7 @@ classes.add(clazzDesc); } - addClassHeader(clazzDesc, headerDesc, version); + addClassHeader(clazzDesc, headerDesc, version, null); for (Method m : cf.methods) { if (!include(m.access_flags.flags)) @@ -1756,7 +1843,7 @@ for (Attribute attr : m.attributes) { readAttribute(cf, methDesc, attr); } - addMethod(clazzDesc, methDesc, version); + addMethod(clazzDesc, methDesc, version, null); } for (Field f : cf.fields) { if (!include(f.access_flags.flags)) @@ -1768,7 +1855,7 @@ for (Attribute attr : f.attributes) { readAttribute(cf, fieldDesc, attr); } - addField(clazzDesc, fieldDesc, version); + addField(clazzDesc, fieldDesc, version, null); } } @@ -1827,11 +1914,11 @@ return (accessFlags & (AccessFlags.ACC_PUBLIC | AccessFlags.ACC_PROTECTED)) != 0; } - private void addClassHeader(ClassDescription clazzDesc, ClassHeaderDescription headerDesc, String version) { + private void addClassHeader(ClassDescription clazzDesc, ClassHeaderDescription headerDesc, String version, String baseline) { //normalize: boolean existed = false; for (ClassHeaderDescription existing : clazzDesc.header) { - if (existing.equals(headerDesc)) { + if (existing.equals(headerDesc) && (!existed || (baseline != null && existing.versions.contains(baseline)))) { headerDesc = existing; existed = true; } @@ -1867,11 +1954,11 @@ } } - private void addMethod(ClassDescription clazzDesc, MethodDescription methDesc, String version) { + private void addMethod(ClassDescription clazzDesc, MethodDescription methDesc, String version, String baseline) { //normalize: boolean methodExisted = false; for (MethodDescription existing : clazzDesc.methods) { - if (existing.equals(methDesc)) { + if (existing.equals(methDesc) && (!methodExisted || (baseline != null && existing.versions.contains(baseline)))) { methodExisted = true; methDesc = existing; break; @@ -1883,10 +1970,10 @@ } } - private void addField(ClassDescription clazzDesc, FieldDescription fieldDesc, String version) { + private void addField(ClassDescription clazzDesc, FieldDescription fieldDesc, String version, String baseline) { boolean fieldExisted = false; for (FieldDescription existing : clazzDesc.fields) { - if (existing.equals(fieldDesc)) { + if (existing.equals(fieldDesc) && (!fieldExisted || (baseline != null && existing.versions.contains(baseline)))) { fieldExisted = true; fieldDesc = existing; break; @@ -2298,6 +2385,7 @@ } static abstract class FeatureDescription { + int flagsNormalization = ~0; int flags; boolean deprecated; String signature; @@ -2362,7 +2450,7 @@ @Override public int hashCode() { int hash = 3; - hash = 89 * hash + this.flags; + hash = 89 * hash + (this.flags & flagsNormalization); hash = 89 * hash + (this.deprecated ? 1 : 0); hash = 89 * hash + Objects.hashCode(this.signature); hash = 89 * hash + listHashCode(this.classAnnotations); @@ -2379,7 +2467,7 @@ return false; } final FeatureDescription other = (FeatureDescription) obj; - if (this.flags != other.flags) { + if ((this.flags & flagsNormalization) != (other.flags & flagsNormalization)) { return false; } if (this.deprecated != other.deprecated) { @@ -3031,6 +3119,7 @@ } static class MethodDescription extends FeatureDescription { + static int METHODS_FLAGS_NORMALIZATION = ~0; String name; String descriptor; List thrownTypes; @@ -3038,6 +3127,10 @@ List> classParameterAnnotations; List> runtimeParameterAnnotations; + public MethodDescription() { + flagsNormalization = METHODS_FLAGS_NORMALIZATION; + } + @Override public int hashCode() { int hash = super.hashCode(); @@ -3762,6 +3855,24 @@ args); break; } + case "build-description-incremental-file": { + if (args.length != 6 && args.length != 7) { + help(); + return ; + } + + if (args.length == 7) { + if ("--normalize-method-flags".equals(args[6])) { + MethodDescription.METHODS_FLAGS_NORMALIZATION = ~(0x100 | 0x20); + } else { + help(); + return ; + } + } + + new CreateSymbols().createIncrementalBaseLineFromDataFile(args[1], args[2], args[3], args[4], "".equals(args[5]) ? null : args[5], args); + break; + } case "build-description-incremental": { if (args.length != 3) { help(); # HG changeset patch # User jlahoda # Date 1590996705 -7200 # Mon Jun 01 09:31:45 2020 +0200 # Node ID 70ad36e861665b7442ef043786db8a75b3fc4a14 # Parent 9bd428c73f8c3cd52f6e94391d363c332bba9e5b imported patch 8244763-v2 diff --git a/make/langtools/src/classes/build/tools/symbolgenerator/CreateSymbols.java b/make/langtools/src/classes/build/tools/symbolgenerator/CreateSymbols.java --- a/make/langtools/src/classes/build/tools/symbolgenerator/CreateSymbols.java +++ b/make/langtools/src/classes/build/tools/symbolgenerator/CreateSymbols.java @@ -1663,13 +1663,13 @@ private void incrementalUpdate(String ctDescriptionFile, String excludeFile, - String version, + String platformVersion, Iterable classBytes, Function baseline, String[] args) throws IOException { String currentVersion = - Integer.toString(Integer.parseInt(version), Character.MAX_RADIX); - currentVersion = currentVersion.toUpperCase(Locale.ROOT); + Integer.toString(Integer.parseInt(platformVersion), Character.MAX_RADIX); + String version = currentVersion.toUpperCase(Locale.ROOT); Path ctDescriptionPath = Paths.get(ctDescriptionFile).toAbsolutePath(); LoadDescriptions data = load(null, ctDescriptionPath); @@ -1684,6 +1684,12 @@ removeVersion(data, version); + for (ModuleDescription md : data.modules.values()) { + for (ModuleHeaderDescription header : md.header) { + header.versions = header.versions.replace("$", version); + } + } + for (ClassDescription clazzDesc : data.classes) { for (ClassHeaderDescription header : clazzDesc.header) { header.versions = header.versions.replace("$", version); @@ -1697,7 +1703,7 @@ } if (versions.stream().noneMatch(inp -> version.equals(inp.version))) { - versions.add(new PlatformInput(null, currentVersion, baseline.apply(data), null)); + versions.add(new PlatformInput(null, version, baseline.apply(data), null)); } Set writeVersions = new HashSet<>(); @@ -1961,7 +1967,6 @@ if (existing.equals(methDesc) && (!methodExisted || (baseline != null && existing.versions.contains(baseline)))) { methodExisted = true; methDesc = existing; - break; } } methDesc.versions += version; @@ -1976,7 +1981,6 @@ if (existing.equals(fieldDesc) && (!fieldExisted || (baseline != null && existing.versions.contains(baseline)))) { fieldExisted = true; fieldDesc = existing; - break; } } fieldDesc.versions += version; diff --git a/test/langtools/tools/javac/sym/ElementStructureTest.java b/test/langtools/tools/javac/sym/ElementStructureTest.java --- a/test/langtools/tools/javac/sym/ElementStructureTest.java +++ b/test/langtools/tools/javac/sym/ElementStructureTest.java @@ -134,10 +134,10 @@ (byte) 0x90, (byte) 0xFA, (byte) 0x98, (byte) 0xCD }; static final byte[] hash8 = new byte[] { - (byte) 0x0B, (byte) 0xEB, (byte) 0x16, (byte) 0xF5, - (byte) 0x7F, (byte) 0xB0, (byte) 0x18, (byte) 0xF1, - (byte) 0x78, (byte) 0x11, (byte) 0xED, (byte) 0x30, - (byte) 0x19, (byte) 0x4D, (byte) 0xDE, (byte) 0x8A + (byte) 0x24, (byte) 0x38, (byte) 0x52, (byte) 0x1C, + (byte) 0x5E, (byte) 0x83, (byte) 0x82, (byte) 0xE6, + (byte) 0x41, (byte) 0xC2, (byte) 0xDD, (byte) 0x2A, + (byte) 0xFD, (byte) 0xFF, (byte) 0x5E, (byte) 0x2F }; final static Map version2Hash = new HashMap<>();