@@ -7807,44 +7807,50 @@ checkMetadataDependency(MetadataDependency dependency) {
78077807void swift::blockOnMetadataDependency (MetadataDependency root,
78087808 MetadataDependency firstLink) {
78097809 std::vector<MetadataDependency> links;
7810- auto checkNewLink = [&](MetadataDependency newLink) {
7811- links.push_back (newLink);
7812- for (auto i = links.begin (), e = links.end () - 1 ; i != e; ++i) {
7813- if (i->Value == newLink.Value ) {
7814- diagnoseMetadataDependencyCycle (
7815- llvm::makeArrayRef (&*i, links.end () - i));
7816- }
7817- }
7818- };
7819-
78207810 links.push_back (root);
78217811
78227812 // Iteratively add each link, checking for a cycle, until we reach
78237813 // something without a known dependency.
7824- checkNewLink (firstLink);
7825- while (true ) {
7814+
7815+ // Start out with firstLink. The initial NewState value won't be
7816+ // used, so just initialize it to an arbitrary value.
7817+ MetadataStateWithDependency currentCheckResult{
7818+ PrivateMetadataState::Allocating, firstLink};
7819+
7820+ // If there isn't a known dependency, we can't do any more checking.
7821+ while (currentCheckResult.Dependency ) {
7822+ // Add this dependency to our links.
7823+ links.push_back (currentCheckResult.Dependency );
7824+
78267825 // Try to get a dependency for the metadata in the last link we added.
7827- auto checkResult = checkMetadataDependency (links.back ());
7828-
7829- // If there isn't a known dependency, we can't do any more checking.
7830- if (!checkResult.Dependency ) {
7831- // In the special case where it's the first link that doesn't have
7832- // a known dependency and its current metadata state now satisfies
7833- // the dependency leading to it, we can skip waiting.
7834- if (links.size () == 2 &&
7835- satisfies (checkResult.NewState , links.back ().Requirement ))
7836- return ;
7837-
7838- // Otherwise, just make a blocking request for the first link in
7839- // the chain.
7840- auto request = MetadataRequest (firstLink.Requirement );
7841- swift_checkMetadataState (request, firstLink.Value );
7842- return ;
7843- }
7826+ currentCheckResult = checkMetadataDependency (links.back ());
78447827
7845- // Check the new link.
7846- checkNewLink (checkResult.Dependency );
7828+ // Check the last link against the rest of the list.
7829+ for (auto i = links.begin (), e = links.end () - 1 ; i != e; ++i) {
7830+ if (i->Value == links.back ().Value ) {
7831+ // If there's a cycle but the new link's current state is now satisfied,
7832+ // then this is a stale dependency, not a cycle. This can happen when
7833+ // threads race to build a type in a fulfillable cycle.
7834+ if (!satisfies (currentCheckResult.NewState , links.back ().Requirement ))
7835+ diagnoseMetadataDependencyCycle (
7836+ llvm::makeArrayRef (&*i, links.end () - i));
7837+ }
7838+ }
78477839 }
7840+
7841+ // We didn't find any cycles. Make a blocking request if appropriate.
7842+
7843+ // In the special case where it's the first link that doesn't have
7844+ // a known dependency and its current metadata state now satisfies
7845+ // the dependency leading to it, we can skip waiting.
7846+ if (links.size () == 2 &&
7847+ satisfies (currentCheckResult.NewState , links.back ().Requirement ))
7848+ return ;
7849+
7850+ // Otherwise, just make a blocking request for the first link in
7851+ // the chain.
7852+ auto request = MetadataRequest (firstLink.Requirement );
7853+ swift_checkMetadataState (request, firstLink.Value );
78487854}
78497855
78507856/* **************************************************************************/
0 commit comments