8320716: ResolvedModule::reads includes self when configuration contains two or more automatic modules

Reviewed-by: mchung
This commit is contained in:
Alan Bateman 2023-12-01 07:31:10 +00:00
parent 4ba94ef69e
commit 2476be4590
3 changed files with 176 additions and 181 deletions

View file

@ -1,5 +1,5 @@
/*
* Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2016, 2023, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -97,6 +97,8 @@ public final class ResolvedModule {
/**
* Returns the set of resolved modules that this resolved module reads.
* The readability relation is reflexive (every module reads itself). The
* set of resolved modules returned by this method does not include itself.
*
* @return A possibly-empty unmodifiable set of resolved modules that
* this resolved module reads

View file

@ -1,5 +1,5 @@
/*
* Copyright (c) 2013, 2022, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2013, 2023, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -497,7 +497,6 @@ final class Resolver {
* and m2 reads m3.
*/
private Map<ResolvedModule, Set<ResolvedModule>> makeGraph(Configuration cf) {
int moduleCount = nameToReference.size();
// the "reads" graph starts as a module dependence graph and
@ -537,9 +536,7 @@ final class Resolver {
}
// populate g1 and g2 with the dependences from the selected modules
Map<String, ResolvedModule> nameToResolved = HashMap.newHashMap(moduleCount);
for (ModuleReference mref : nameToReference.values()) {
ModuleDescriptor descriptor = mref.descriptor();
String name = descriptor.name();
@ -595,8 +592,7 @@ final class Resolver {
String name2 = descriptor2.name();
if (!name.equals(name2)) {
ResolvedModule m2
= computeIfAbsent(nameToResolved, name2, cf, mref2);
ResolvedModule m2 = computeIfAbsent(nameToResolved, name2, cf, mref2);
reads.add(m2);
if (descriptor2.isAutomatic())
requiresTransitive.add(m2);
@ -622,29 +618,33 @@ final class Resolver {
g2.put(m1, requiresTransitive);
}
// Iteratively update g1 until there are no more requires transitive
// to propagate
// Iteratively update g1 until there are no more requires transitive to propagate
boolean changed;
List<ResolvedModule> toAdd = new ArrayList<>();
do {
changed = false;
for (Set<ResolvedModule> m1Reads : g1.values()) {
for (ResolvedModule m2 : m1Reads) {
Set<ResolvedModule> m2RequiresTransitive = g2.get(m2);
if (m2RequiresTransitive != null) {
for (ResolvedModule m3 : m2RequiresTransitive) {
if (!m1Reads.contains(m3)) {
// m1 reads m2, m2 requires transitive m3
// => need to add m1 reads m3
toAdd.add(m3);
for (Map.Entry<ResolvedModule, Set<ResolvedModule>> e : g1.entrySet()) {
ResolvedModule m1 = e.getKey();
// automatic module already reads all selected modules so nothing to propagate
if (!m1.descriptor().isAutomatic()) {
Set<ResolvedModule> m1Reads = e.getValue();
for (ResolvedModule m2 : m1Reads) {
Set<ResolvedModule> m2RequiresTransitive = g2.get(m2);
if (m2RequiresTransitive != null) {
for (ResolvedModule m3 : m2RequiresTransitive) {
if (!m1Reads.contains(m3)) {
// m1 reads m2, m2 requires transitive m3
// => need to add m1 reads m3
toAdd.add(m3);
}
}
}
}
}
if (!toAdd.isEmpty()) {
m1Reads.addAll(toAdd);
toAdd.clear();
changed = true;
if (!toAdd.isEmpty()) {
m1Reads.addAll(toAdd);
toAdd.clear();
changed = true;
}
}
}
} while (changed);