Skip to content
This repository was archived by the owner on Oct 12, 2022. It is now read-only.

TypeInfo_Struct: Switch to stored mangled name & demangle lazily (with per-thread cache) #3527

Merged
merged 7 commits into from
Aug 1, 2021

Conversation

kinke
Copy link
Contributor

@kinke kinke commented Jul 26, 2021

Making the TypeInfo_Struct names truly unique and more compact at the same time. Requires compiler support: dlang/dmd#12928

Caching the demangled name in the instance itself isn't possible because TypeInfo.toString() is const. I had to remove its pure in order to cache the demangled name in a per-thread AA (and using const void* as key, as const TypeInfo_Struct leads to an infinite recursion...).

@dlang-bot
Copy link
Contributor

Thanks for your pull request and interest in making D better, @kinke! We are looking forward to reviewing it, and you should be hearing from a maintainer soon.
Please verify that your PR follows this checklist:

  • My PR is fully covered with tests (you can see the coverage diff by visiting the details link of the codecov check)
  • My PR is as minimal as possible (smaller, focused PRs are easier to review than big ones)
  • I have provided a detailed rationale explaining my changes
  • New or modified functions have Ddoc comments (with Params: and Returns:)

Please see CONTRIBUTING.md for more information.


If you have addressed all reviews or aren't sure how to proceed, don't hesitate to ping us with a simple comment.

Bugzilla references

Your PR doesn't reference any Bugzilla issue.

If your PR contains non-trivial changes, please reference a Bugzilla issue or create a manual changelog.

Testing this PR locally

If you don't have a local development environment setup, you can use Digger to test this PR:

dub run digger -- build "master + druntime#3527"

kinke added a commit to dlang/dmd that referenced this pull request Jul 26, 2021
Making the TypeInfo_Struct names truly unique and more compact at the
same time. Requires dlang/druntime#3527.
@kinke kinke force-pushed the typeinfostruct_mangledName branch 3 times, most recently from 8201c3c to 1ce87d4 Compare July 26, 2021 21:13
@kinke
Copy link
Contributor Author

kinke commented Jul 26, 2021

I've run the tests locally on Linux x64 with both dmd and druntime branches; all green (dmd/druntime/phobos) except for (apparently hanging) druntime integration subtest printf of test/gc/.

@kinke kinke requested a review from rainers July 26, 2021 21:18
}
unittest
{
assert(typeid(void).toString == "void");
Copy link
Contributor Author

Choose a reason for hiding this comment

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

TypeInfo.toString() isn't pure anymore.

@rainers
Copy link
Member

rainers commented Jul 27, 2021

except for (apparently hanging) druntime integration subtest printf of test/gc/

The test is trying to print the types of allocations while the GC lock is held: this deadlocks when accessing name, see https://github.com/dlang/druntime/blob/master/src/core/internal/gc/impl/conservative/gc.d#L4061.

That also shows another subtle change: using TypeInfo_Struct.name no longer is @nogc. Could you use HashTab from core.internal.container.hashtab instead of the AA?

@PetarKirov
Copy link
Member

PetarKirov commented Jul 27, 2021

TypeInfo.toString() isn't pure

This is a breaking change (although I was expecting quite more to be broken than just atilaneves/unit-threaded), it needs a changelog entry and stronger justification.

Making the TypeInfo_Struct names truly unique

While this certainly is a good thing, can you explain why is it necessary? Are you trying to solve some bigger problem with this?

@kinke
Copy link
Contributor Author

kinke commented Jul 27, 2021

The test is trying to print the types of allocations while the GC lock is held: this deadlocks when accessing name

Cheers; worked around it for now by using mangledName there.

That also shows another subtle change: using TypeInfo_Struct.name no longer is @nogc. Could you use HashTab from core.internal.container.hashtab instead of the AA?

The AA shouldn't really matter, as core.demangle GC-allocates anyway, unless using some huge buffer that is guaranteed to suffice for all names and then malloc'ing an appropriate copy afterwards...

@kinke
Copy link
Contributor Author

kinke commented Jul 27, 2021

@PetarKirov: I haven't found an existing issue yet, so filed a new one: https://issues.dlang.org/show_bug.cgi?id=22149

This is especially bad for classes (tackled later), where it can e.g. break EH with LDC on Windows (see ldc-developers/ldc#3517), and dynamic casting in general AFAIK.

kinke added a commit to dlang/dmd that referenced this pull request Jul 27, 2021
…ched equality semantics

By storing the mangled name, making the TypeInfo_Struct names truly
unique and more compact at the same time.
Requires dlang/druntime#3527.
@kinke
Copy link
Contributor Author

kinke commented Jul 27, 2021

Testcase added to dlang/dmd#12928.

@PetarKirov
Copy link
Member

Indeed, that's a quite severe. Thanks for the explanations and linking the LDC PR!

kinke added a commit to dlang/dmd that referenced this pull request Jul 27, 2021
…ched equality semantics

By storing the mangled name, making the TypeInfo_Struct names truly
unique and more compact at the same time.
Requires dlang/druntime#3527.
@kinke kinke force-pushed the typeinfostruct_mangledName branch from c7782cd to 24ab248 Compare July 27, 2021 14:32
@rainers
Copy link
Member

rainers commented Jul 27, 2021

Cheers; worked around it for now by using mangledName there.

Fine with me, a log can be run through ddemangle if needed.

The AA shouldn't really matter, as core.demangle GC-allocates anyway

Noticed that too after commenting. An alternative could be to abort demangling if the passed buffer is too small and let the caller allocate a larger one. If only the demangler would not use exceptions (which it only needs for backward compatibilty with older ambiguous manglings IIRC). Changing the demangler would be another PR, though.

@kinke
Copy link
Contributor Author

kinke commented Jul 27, 2021

Fine with me, a log can be run through ddemangle if needed.

ddemangle unfortunately doesn't seem to support such type names (S3foo3bar).

An alternative could be to abort demangling if the passed buffer is too small and let the caller allocate a larger one.

Yeah, or passing some sink which is responsible for increasing the internal capacity as needed.

If only the demangler would not use exceptions (which it only needs for backward compatibilty with older ambiguous manglings IIRC).

Yeah, I find it also very suboptimal as demangling is used for exception backtraces, and throws at that time aren't really to be expected.

Changing the demangler would be another PR, though.

Definitely. I've just seen that there are other 'beautiful' related hacks like

druntime/src/object.d

Lines 1209 to 1210 in 3a9ede0

alias SafeDemangleFunctionType = char[] function (const(char)[] buf, char[] dst = null) @safe nothrow pure;
SafeDemangleFunctionType demangle = cast(SafeDemangleFunctionType) &demangleType;


CI doesn't seem to really work with feature branches (same-named branches directly on the official dlang repos) to tackle compiler and druntime at the same time; both PRs currently include a temporary commit to make Cirrus CI use the correct branches at least. Those commits obviously need to be removed before merging.

Restoring pure to TypeInfo_Class.toString() etc. made unit-threaded pass again for Buildkite. A changelog entry still needs to be added to emphasize that breaking change; not sure if here or in the DMD PR [edit: added here]. The latter also includes the (trivial) fix for TypeInfo_Class now.

@kinke kinke marked this pull request as ready for review July 27, 2021 18:39
{
return hashOf(this.mangledName);
}

Copy link
Contributor Author

Choose a reason for hiding this comment

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

TypeInfo.opCmp uses toString() too; I'm not convinced overriding it here to check for a TypeInfo_Struct rhs and comparing the mangledName instead is worth it.

kinke added 3 commits July 27, 2021 21:14
…h per-thread cache)

Making the TypeInfo_Struct names truly unique and more compact at the
same time. Requires compiler support.

Caching the demangled name in the instance itself isn't possible because
`TypeInfo.toString()` is const. I had to remove its `pure` in order to
cache the demangled name in a per-thread AA (and using `const void*` as
key, as `const TypeInfo_Struct` leads to an infinite recursion...).
kinke and others added 2 commits July 27, 2021 21:14
This is especially useful to make `typeid(<class ref>).toString()`
pure again (e.g., used by unit-threaded's `shouldThrow`).
@kinke kinke force-pushed the typeinfostruct_mangledName branch from 24ab248 to 9a30e97 Compare July 27, 2021 19:16
@kinke
Copy link
Contributor Author

kinke commented Jul 28, 2021

CI doesn't seem to really work with feature branches (same-named branches directly on the official dlang repos) to tackle compiler and druntime at the same time

I've made it work for Azure Pipelines now (one according commit in each PR; all Windows jobs are green); the druntime patch here is a bit of an ugly copy-pasta but does the job. So PRs originating from branches on the official dlang repos will try to use same-named branches for the other repos, and fall back to master if the branch doesn't exist. To make that work for Phobos PRs too, it would need a commit analogous to the one here, but Phobos isn't as tightly tied to the compiler as druntime, so I don't think it's really needed. So

  • useful when a change involves both compiler and druntime at the same time like this one here,
  • only for people with write access to both dlang repos,
  • preventing PRs originating from the official repo from targeting stable (due to the master fallback) - submit those from your fork instead.

Edit: Now (properly) working with Cirrus CI too and thus covering Windows/Linux/macOS/FreeBSD; the previous hack doesn't need to be removed anymore.

@PetarKirov
Copy link
Member

CI doesn't seem to really work with feature branches

We really should stop wasting everyone's time with the artificial split between dmd and druntime (and possibly phobos) and merge them in a mono repo.

@kinke
Copy link
Contributor Author

kinke commented Jul 29, 2021

[Would be nice to have this land in 2.098; Walter has approved of the DMD PR.]

@RazvanN7
Copy link
Contributor

@kinke It seems that the autotester is failing a couple of tests in dmd. Is this expected?

@kinke
Copy link
Contributor Author

kinke commented Jul 30, 2021

@RazvanN7: Yes, these 2 DMD testsuite failures are expected if DMD and druntime aren't in sync.

@RazvanN7
Copy link
Contributor

I'm gonna pull the trigger on these PRs. Let's hope everything will run smoothly.

@RazvanN7
Copy link
Contributor

Hmm, unfortunately I don't have the right to merge this unless it passes all required tests. However, I have enough permissions to merge the dmd PR.

Maybe I can do that and wait for this PR to be green? That will stall the entire pipeline. But I don't see any other way out of it.

@kinke
Copy link
Contributor Author

kinke commented Jul 30, 2021

Can't you merge manually via git cmdline? Should I try to?

@RazvanN7
Copy link
Contributor

RazvanN7 commented Aug 1, 2021

Feel free to merge both PRs. (I apparently can't merge this one)

@kinke
Copy link
Contributor Author

kinke commented Aug 1, 2021

@RazvanN7: I can't merge any one of these PRs either; looks like the GitHub branch protection rules even apply to manual pushes. So if you can indeed merge the DMD one, please go ahead.

RazvanN7 pushed a commit to dlang/dmd that referenced this pull request Aug 1, 2021
…otched equality semantics (#12928)

* Fix Issue 22149 - TypeInfo_Struct names aren't unique, leading to botched equality semantics

By storing the mangled name, making the TypeInfo_Struct names truly
unique and more compact at the same time.
Requires dlang/druntime#3527.

* Fix Issue 22150 - TypeInfo_Class names aren't unique, leading to botched equality semantics

By fully qualifying template arguments.

* [temp] Cirrus CI: Use same-named druntime branch

* Azure Pipelines: Try to use same-named druntime/Phobos branches for PRs originating from the official dlang repo

* Cirrus CI: Try to use same-named druntime/Phobos branches for PRs originating from the official dlang repo
@RazvanN7
Copy link
Contributor

RazvanN7 commented Aug 1, 2021

@kinke Merged it. Maybe re-push to restart failing tests. Autotester has restarted and buildkite can be manually restarted

@dlang-bot dlang-bot merged commit af04c94 into master Aug 1, 2021
@kinke kinke deleted the typeinfostruct_mangledName branch August 1, 2021 12:36
kinke added a commit to ldc-developers/dmd-testsuite that referenced this pull request Aug 13, 2021
…otched equality semantics (#12928)

* Fix Issue 22149 - TypeInfo_Struct names aren't unique, leading to botched equality semantics

By storing the mangled name, making the TypeInfo_Struct names truly
unique and more compact at the same time.
Requires dlang/druntime#3527.

* Fix Issue 22150 - TypeInfo_Class names aren't unique, leading to botched equality semantics

By fully qualifying template arguments.

* [temp] Cirrus CI: Use same-named druntime branch

* Azure Pipelines: Try to use same-named druntime/Phobos branches for PRs originating from the official dlang repo

* Cirrus CI: Try to use same-named druntime/Phobos branches for PRs originating from the official dlang repo
UplinkCoder pushed a commit to UplinkCoder/dmd that referenced this pull request Aug 19, 2021
…otched equality semantics (dlang#12928)

* Fix Issue 22149 - TypeInfo_Struct names aren't unique, leading to botched equality semantics

By storing the mangled name, making the TypeInfo_Struct names truly
unique and more compact at the same time.
Requires dlang/druntime#3527.

* Fix Issue 22150 - TypeInfo_Class names aren't unique, leading to botched equality semantics

By fully qualifying template arguments.

* [temp] Cirrus CI: Use same-named druntime branch

* Azure Pipelines: Try to use same-named druntime/Phobos branches for PRs originating from the official dlang repo

* Cirrus CI: Try to use same-named druntime/Phobos branches for PRs originating from the official dlang repo
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants