Skip to content

[libSyntax] Create SyntaxRef, which uses SyntaxDataRef internally #36350

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
Mar 12, 2021

Conversation

ahoppen
Copy link
Member

@ahoppen ahoppen commented Mar 8, 2021

Now that we have a fast SyntaxDataRef, create a corresponding SyntaxRef hierarchy. In contrast to the Syntax hierarchy, SyntaxRef does not own the backing SyntaxDataRef, but merely has a pointer to the SyntaxDataRef. In addition to the requirements imposed by SyntaxDataRef, the user of the SyntaxRef hierarchy needs to make sure that the backing SyntaxDataRef of a SyntaxRef node stays alive. While this sounds like a lot of requirements, it has performance advantages:

  • Passing a SyntaxRef node around is just passing a pointer around.
  • When casting a SyntaxRef node, we only need to create a new SyntaxRef (aka. pointer) that points to the same underlying SyntaxDataRef – there's no need to duplicate the SyntaxDataRef.
  • As SyntaxDataRef is not ref-counted, there's no ref-counting overhead involved.

Furthermore, the requirements are typically fulfilled. The getChild methods on SyntaxRef return an OwnedSyntaxRef, which stores the SyntaxDataRef. As long as this variable is stored somewhere on the stack, the corresponding SyntaxRef can safely be used for the duration of the stack frame. Even calls like the following are possible, because OwnedSyntaxRef returned by getChild stays alive for the duration of the entire statement.

useSyntaxRef(mySyntaxRef.getChild(0).getRef())

@ahoppen
Copy link
Member Author

ahoppen commented Mar 8, 2021

@swift-ci Please smoke test

ahoppen added 2 commits March 9, 2021 10:37
For syntax nodes that previously didn’t have a `validate` method, the newly added `validate` method is a no-op. This will make validation easier in upcoming generic code.
@ahoppen
Copy link
Member Author

ahoppen commented Mar 9, 2021

@swift-ci Please smoke test

@ahoppen ahoppen marked this pull request as ready for review March 9, 2021 12:10
@ahoppen ahoppen requested a review from rintaro March 9, 2021 12:10
Copy link
Member

@rintaro rintaro left a comment

Choose a reason for hiding this comment

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

Overall looks good.


virtual ~Syntax() {}
explicit Syntax(const RC<const SyntaxData> &Data) : Data(Data) {
assert(Data != nullptr && "SyntaxData must be backed by Data");
Copy link
Member

Choose a reason for hiding this comment

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

You mean "Syntax must be backed by Data"?

Copy link
Member Author

Choose a reason for hiding this comment

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

Yes

class Syntax {
protected:
RC<const SyntaxData> Data;

public:
explicit Syntax(const RC<const SyntaxData> &Data) : Data(Data) {}

virtual ~Syntax() {}
Copy link
Member

Choose a reason for hiding this comment

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

Do you know why this was there? If not, never mind. If yes, why removing this?

Copy link
Member Author

Choose a reason for hiding this comment

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

I guess that the specific Syntax nodes had their own destructors at some point and that they went away during some change (none of my recent ones anyway). I removed it, nothing broke, so I assumed it’s not necessary and removed it just to clear things up. There’s no specific reason to keep or remove it.


/// See comment on top of file.
class SyntaxRef {
const SyntaxDataRef *Data;
Copy link
Member

Choose a reason for hiding this comment

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

I found the name SyntaxDataRef is confusing. It sounds like "reference to SyntaxData", but it is actually the data itself. But I couldn't come up with a better name..

Copy link
Member Author

Choose a reason for hiding this comment

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

As discussed offline, I’ll set up a follow-up PR to change the name of SyntaxDataRef. On there, we can also discuss what a better name might be.

@ahoppen
Copy link
Member Author

ahoppen commented Mar 11, 2021

@swift-ci Please smoke test


/// See comment on top of file.
class SyntaxRef {
const SyntaxDataRef *Data;
Copy link
Member

Choose a reason for hiding this comment

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

I think the pointer itself is also never changed. So const SyntaxDataRef * const Data

Copy link
Member Author

Choose a reason for hiding this comment

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

👍 Also changed Data in Syntax to const RC<const SyntaxData> Data.

Comment on lines +120 to +121
assert(Ref.getDataRef() == getDataPtr() &&
"Ref no longer pointing to Data?");
Copy link
Member

Choose a reason for hiding this comment

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

If Data is const, this assert is not needed.

Copy link
Member Author

Choose a reason for hiding this comment

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

I ran into issues here at some point after moving OwnedSyntaxRef to a different location. The pointer stays constant but the SyntaxDataRef now lives in a different location, so the pointer isn’t valid anymore. That’s why I put the assertion in and I think it’s still useful if someone starts to fiddle around OwnedSyntaxRef.

Now that we have a fast SyntaxDataRef, create a corresponding SyntaxRef hierarchy. In contrast to the Syntax, SyntaxRef does *not* own the backing SyntaxDataRef, but merely has a pointer to the SyntaxDataRef.
In addition to the requirements imposed by SyntaxDataRef, the user of the SyntaxRef hierarchy needs to make sure that the backing SyntaxDataRef of a SyntaxRef node stays alive. While this sounds like a lot of requirements, it has performance advantages:
 - Passing a SyntaxRef node around is just passing a pointer around.
 - When casting a SyntaxRef node, we only need to create a new SyntaxRef (aka. pointer) that points to the same underlying SyntaxDataRef - there's no need to duplicate the SyntaxDataRef.
 - As SyntaxDataRef is not ref-counted, there's no ref-counting overhead involved.

Furthermore, the requirements are typically fulfilled. The getChild methods on SyntaxRef return an OwnedSyntaxRef, which stores the SyntaxDataRef. As long as this variable is stored somewhere on the stack, the corresponding SyntaxRef can safely be used for the duration of the stack frame. Even calls like the following are possible, because OwnedSyntaxRef returned by getChild stays alive for the duration of the entire statement.
```
useSyntaxRef(mySyntaxRef.getChild(0).getRef())
```
@ahoppen
Copy link
Member Author

ahoppen commented Mar 11, 2021

@swift-ci Please smoke test

@ahoppen ahoppen merged commit e1e0f54 into swiftlang:main Mar 12, 2021
@ahoppen ahoppen deleted the pr/syntaxref branch March 12, 2021 07:17
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.

2 participants