This is an archive of the discontinued LLVM Phabricator instance.

[scudo] Use MemMap in Vector
ClosedPublic

Authored by fabio-d on Sep 5 2023, 8:21 AM.

Diff Detail

Event Timeline

fabio-d created this revision.Sep 5 2023, 8:21 AM
Herald added a project: Restricted Project. · View Herald TranscriptSep 5 2023, 8:21 AM
fabio-d requested review of this revision.Sep 5 2023, 8:21 AM
Herald added a project: Restricted Project. · View Herald TranscriptSep 5 2023, 8:21 AM
Herald added a subscriber: Restricted Project. · View Herald Transcript
Chia-hungDuan added inline comments.Sep 5 2023, 11:34 AM
compiler-rt/lib/scudo/standalone/tests/vector_test.cpp
26–29

This is way too big. It'll simply increase the running time of the tests without verifying many stuff. Given the use of vector is restricted and the static buffer is hard coded and which is small. I think the original size is good enough.

compiler-rt/lib/scudo/standalone/vector.h
34

Can you move the destroy() to protected and only reset this to nullptr when it's using external buffer? Besides, we may want to call clear() before the buffer destruction

89

I think it's fine to omit the comment here and below in this function. The code is self-explained pretty clear.

106–107

I would merge the comment with the comment of VectorNoCtor and it will look like

// A low-level vector based on map. To reduce memory overhead for small vectors, it'll 
// use a local buffer when available. Otherwise, a external memory buffer will be used. 
// The current implementation supports only POD types.
fabio-d updated this revision to Diff 556006.Sep 6 2023, 4:42 AM
fabio-d marked 2 inline comments as done.Sep 6 2023, 5:08 AM
fabio-d added inline comments.
compiler-rt/lib/scudo/standalone/tests/vector_test.cpp
26–29

Thanks, the original size (1000 elements) ended up testing 4000 bytes (1 page*) or 8000 bytes (2 pages*), depending of whether the architecture is a 32 or 64 bit one. * = assuming that a page is 4096 bytes, which is not universally true

I've modified the code so that it always tests with 2 pages on all platforms to address your performance concerns. This ensures that we always test both kinds of transitions:

  • from the internal buffer to an external one
  • from an external buffer to another larger external buffer
compiler-rt/lib/scudo/standalone/vector.h
34
  1. If I make destroy() protected, direct users of VectorNoCtor will not be able to release its memory when they are done with it. On the other hand, there no such users today, as VectorNoCtor is only indirectly used through the Vector<T> class defined below, which subclasses it. That said, do you think that we should still make it protected (along with init, I'd say, for symmetry) and document that VectorNoCtor can only be used through its Vector<T> wrapper, or should we leave all the necessary methods public and available for direct usage?
  1. About resetting Data to nullptr, my intent was to poison the object to catch use-after-destroy more easily, but I realized it wouldn't have worked in all the cases, so I removed it in this new revision of the CL. On a related note, we can't clear() from here as that would set Size = 0, and this function is also called when growing the vector, and we don't want to forget its size from there. If we want to poison it properly, we can separate this code path from the path that grows the vector, and ensure that destroy() always leaves it in pre-init state (i.e. with all the fields set to zero and no external buffer). What do you think?
Chia-hungDuan added inline comments.Sep 6 2023, 9:00 AM
compiler-rt/lib/scudo/standalone/tests/vector_test.cpp
26–29

I'm not concerning the performance of this test. I'm thinking of the necessity of doing this and what's the frequency/cost of having bugs in this vector. This is not a general used vector and have very limited use cases.

The scenarios you are trying to test depend on the buffer extension policy. What if we always prepare dynamic buffer with starting size 128K? Then we won't be able to cover the scenarios as mentioned.

Again, this is not a general used vector (nor having complex functions). In addition, other tests that use this vector also verify the functions indirectly. I'm not sure what's the benefit of testing these scenarios at this moment

compiler-rt/lib/scudo/standalone/vector.h
34

You're right, we can't use clear() directly here. Please ignore that suggestion.

I'm not sure why we have to *poison* the Data. Like you said, use-after-destroy is not a case we have to worry here.

As mentioned, this is designed to be generally used. The purpose of destroy() is ambiguous now. I would suggest that only use Vector and disallow the direct use of VectorNoCtor. I'm planning some changes on this but it has lower priority now anyway.

fabio-d updated this revision to Diff 556276.Sep 8 2023, 9:31 AM
fabio-d added inline comments.Sep 8 2023, 9:37 AM
compiler-rt/lib/scudo/standalone/tests/vector_test.cpp
26–29

Done, I've removed all the changes to the test from this CL

compiler-rt/lib/scudo/standalone/vector.h
34

Done, I've made init() and destroy() protected and explained that direct usage of VectorNoCtor is disallowed in the comment at the top

This revision is now accepted and ready to land.Sep 14 2023, 10:59 AM
This revision was automatically updated to reflect the committed changes.