Skip to content

Conversation

davidungar
Copy link
Contributor

Based on my own investigation, and conversations with Jordan, have added some comments. Zero changes to actual code. Pay particular attention to the comment for InitialOutOfDateCommands, where (if I read the code right) I had to reverse the sense of a comment. Either the code or the comment was wrong before.

@@ -230,9 +230,17 @@ class CommandOutput {
class Job {
public:
enum class Condition {
// There was no input map, or the map makred this Job as dirty
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Typo: marked

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks!

Copy link
Contributor

@jrose-apple jrose-apple left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for doing this!

///
/// "Marked" does NOT mean that any successors in the graph have been
/// processed. The traversal routines use "Visited" to avoid endless
/// "recursion".
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This last bit doesn't seem like it belongs here, since "Visited" isn't persistent state.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reworded and moved to markTransitive.

/// Assume that the starting node is "cascading"; that all dependencies must
/// be dirty if the start is dirty. Therefore, mark the start. For each
/// visited node, add it to visited, and mark it if it cascades. The start
/// node is NOT added to visited.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There's no comment here because there is a comment on the templated version. Can you keep them all together?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes! Moved this comment and added an attempt at a cross-reference.

CheckDependencies,
// Pessimal: run no matter what.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is actually not the worst case; a newly-added file doesn't necessarily cascade.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Clarified, thanks.

Always,
// The input changed, or this job was private or [it was not dirty but
// primary output was missing].
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's stick to "non-cascading" as the terminology, but even then it's something more like "this job was scheduled as non-cascading in the last build but didn't get to run".

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Changed the term "private". I didn't want to remove the lower-level predicate, so I added your sentence to the comment.

@@ -230,9 +230,17 @@ class CommandOutput {
class Job {
public:
enum class Condition {
// There was no input map, or the map makred this Job as dirty
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think it's obvious what "input map" means here. Maybe something like "we have no information about any previous build"?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good catch! Fixed it to say both.

@@ -206,8 +206,9 @@ namespace driver {
/// Jobs that incremental-mode has decided it can skip.
CommandSet DeferredCommands;

/// Jobs in the initial set with Condition::Always, or lacking existing
/// Jobs in the initial set with Condition::Always, and having an existing
/// .swiftdeps files.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This change seems incorrect. NewlyAdded files would also show up here (at least they should).

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

On second thought, maybe not. Maybe the variable name just needs to change.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here is the code from Compilation.cpp:

       case Job::Condition::Always:
          if (Comp.getIncrementalBuildEnabled() && !DependenciesFile.empty()) {
            // Ensure dependents will get recompiled.
            InitialOutOfDateCommands.push_back(Cmd);
            // Mark this job as cascading.
            DepGraph.markIntransitive(Cmd);
          }
          LLVM_FALLTHROUGH;

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please look at the code above and see if the code is wrong, or I'm reading it wrong, or what? Am I missing another place where jobs get added?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oops, didn't see your second thought, messages crossed in progress. Happy to change the name if you like. Let me know.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, given that this is the only place this gets set, I suggest "InitialCascadingCommands" or something.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

OK, will do!

/// It would probably be safe and simpler to markTransitive on the start
/// nodes in the "Always" condition from the start instead of using
/// markIntransitive and having later functions call markTransitive. That
/// way markInstransitive would be an implemenation detail.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This does not belong in a doc comment because it's not relevant to callers. Maybe it belongs next to markIntransitive instead?

(Also typo: "implemenation".)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Great! Done.

@davidungar
Copy link
Contributor Author

@jrose-apple Thank you for take the time to look at these comments. So helpful to get a review!

@@ -121,6 +121,13 @@ class DependencyGraphImpl {
llvm::StringMap<std::pair<std::vector<DependencyEntryTy>, DependencyMaskTy>> Dependencies;

/// The set of marked nodes.
/// "Marked" means that everything provided by this node (i.e. Job) is
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nitpick: Can you put an extra newline in here? We're formatting our comments as Doxygen (even if we never actually run the generator) and so the first "paragraph" is taken as a short summary.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done!

@@ -121,6 +121,13 @@ class DependencyGraphImpl {
llvm::StringMap<std::pair<std::vector<DependencyEntryTy>, DependencyMaskTy>> Dependencies;

/// The set of marked nodes.
/// "Marked" means that everything provided by this node (i.e. Job) is
/// dirty. Thus any file using any of these provides must be recompiled.
/// (Only non-private entities are output as provides.)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This particular note doesn't really belong here. The dependency graph (and the driver in general) doesn't know about what in a file gives rise to links in the graph, and if the logic did output private entities as "provides", they'd be marked differently somehow anyway.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hard to figure out where to put it, as there is no central declaration I found besides this one.
However, I've moved it into reloadAndRemarkDeps. If you have a better idea, please let me know!

/// (Only non-private entities are output as provides.)
/// In other words, this Job "cascades"; the need to recompile it causes other
/// recompilations. It is possible that the current code marks things that do
/// not need to be marked. Nothing would break if that were the case.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"Nothing would break" seems a bit too generic; the effect of over-marking is unnecessary recompilation.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed.

///
/// Do not confused "Marked" with "Visited".
/// "Marked" does NOT influence the traversal. The traversal routines use
/// "Visited" to avoid endless "recursion".
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This isn't correct; already-marked nodes do not end up in visited, and it's not just to avoid endless recursion. I got that wrong.

(Also, another Doxygen note: parameters can be referred to inline with \p visited.)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good catch! Fixed.

@@ -230,9 +230,20 @@ class CommandOutput {
class Job {
public:
enum class Condition {
// There was no information about the previous build (i.e., an input map),
// or the map marked this Job as dirty
// but the input didn't change.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This isn't correct; the job being marked as "dirty + cascading" takes priority over whether or not the input changed. (At least, I hope it does.)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you. Fixed!

CheckDependencies,
// Pessimal: Run no matter what (but may or may not cascade).
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think "pessimal" is appropriate. As mentioned before, this is usually equivalent to RunWithoutCascading; it just means we don't compare against a previous swiftdeps file.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

OK

@@ -206,8 +206,9 @@ namespace driver {
/// Jobs that incremental-mode has decided it can skip.
CommandSet DeferredCommands;

/// Jobs in the initial set with Condition::Always, or lacking existing
/// Jobs in the initial set with Condition::Always, and having an existing
/// .swiftdeps files.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, given that this is the only place this gets set, I suggest "InitialCascadingCommands" or something.

// It would probably be safe and simpler to markTransitive on the
// start nodes in the "Always" condition from the start instead of
// using markIntransitive and having later functions call
// markTransitive. That way markInstransitive would be an
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Typo: "markInstransitive". Also, it's probably worth saying saying that it would be an implementation detail of DependencyGraph, since the comment is no longer in DependencyGraph.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks. Fixed.

@davidungar
Copy link
Contributor Author

@swift-ci please smoke test

@davidungar
Copy link
Contributor Author

@jrose-apple @graydon I'd like to land this if it's OK with you. Any more suggestions? TIA.

/// Assumes that the starting node is "cascading"; that all dependencies must
/// be dirty if the start is dirty. Therefore, mark the start. For each
/// visited node, add it to visited, and mark it if it cascades. The start
/// node is NOT added to visited.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In this graph model, nodes aren't cascading or not; edges are. (Also, please be consistent about use of \p visited!)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good catch on "visited!" I've fixed that.

// build
// but didn't get to run.
// The scheduled-but-didn't-run condition is detected when the job was not
// dirty but its primary output was missing.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This isn't the only such case, so I'm not sure why you're calling it out here.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Seemed to be worthwhile for the sake of clarity. I can delete it if you prefer. (Not exactly sure what the antecedent for "this" was in your comment.)

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I keep doing that. "the job is not dirty but the primary output is missing" is one case where RunWithoutCascading can happen, but it's not the only one.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks! I get it and removed that sentence.

/// be dirty if the start is dirty. Therefore, mark the start. For each
/// visited node, add it to visited, and mark it if it cascades. The start
/// node is NOT added to visited.
/// Assumes that some edge into the starting node is "cascading."
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I like this better, but since no such edge has to actually exist maybe there's still another way to phrase it?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good point! I've reworded.

@davidungar
Copy link
Contributor Author

@jrose-apple @graydon Thanks for your comments. I'd like to land this. Anything else before I do?

Copy link
Contributor

@jrose-apple jrose-apple left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah, yep! Looks good.

@davidungar
Copy link
Contributor Author

Thanks, @jrose-apple . I'll go ahead and test and land, but if @graydon has any more, I'll put it in in another PR.

@davidungar
Copy link
Contributor Author

@swift-ci please smoke test

@davidungar davidungar merged commit 7ae7038 into swiftlang:master Dec 15, 2018
@davidungar davidungar deleted the master-with-comments branch June 14, 2019 18:03
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants