Skip to content
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

feat: Implement Rust-side const ExternalOneByteStringResource subclass #1275

Merged

Conversation

aapoalas
Copy link
Contributor

@aapoalas aapoalas commented Jul 10, 2023

MSVC and Itanium C++ ABIs agree that for simple inheritance the basic structure of a vtable contains metadata fields at a "negative offset" from the vtable pointer, and at zero or positive offsets come the virtual function pointers in the order of declaration. The only difference between the two is that MSVC only places the virtual deleting destructor in the vtable while Itanium ABI places both the deleting and the complete object destructors in it, leading to a vtable that is one pointer larger in Itanium / on Linux. Also MSVC only has a single metadata field instead of two for Itanium. Itanium inlines the base offset into the vtable while MSVC keeps it in what is essentially the entry point into the type info data.

Since the two are so similar, creating a custom vtable on Rust-side is pretty easy and can be done entirely at compile-time, meaning that instances of the class can also be created entirely at compile time. This leads to fully const external strings being possible.

The only thing that would be nice to add is some C++ side assertions for the vtable offsets but while member pointers to member functions are a thing, getting their offset is non-trivial. It's also a bit unclear to me if it's even possible to perform offset calculations with those.

@CLAassistant
Copy link

CLAassistant commented Jul 10, 2023

CLA assistant check
All committers have signed the CLA.

@aapoalas aapoalas force-pushed the exp/external-const-one-byte-rust-side-vtable branch from 15b30f7 to a33049d Compare July 10, 2023 09:11
@aapoalas aapoalas force-pushed the exp/external-const-one-byte-rust-side-vtable branch from a33049d to 20ed043 Compare July 10, 2023 09:12
src/string.rs Outdated Show resolved Hide resolved
src/string.rs Outdated Show resolved Hide resolved
@aapoalas aapoalas changed the title Rust-side OneByteConst VTABLE, const and very safe 'cause trust me feat: Implement Rust-side const ExternalOneByteStringResource subclass Jul 11, 2023
Copy link
Contributor

@mmastrac mmastrac left a comment

Choose a reason for hiding this comment

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

LGTM. @bartlomieju I think we should land and do a small experiment in Deno to confirm that it works at scale (ideally in a pretty heavily used codepath).

@bartlomieju
Copy link
Member

bartlomieju commented Jul 11, 2023

Feel free to do it! I intend to cut a new release of rusty_v8 next week.

Turns out both Itanium and MSVC ABIs agree that the meta pointer should be a nullptr if RTTI is turned off. My comment was thus wrong and unnecessarily cast doubt on the safety of this PR.
It's a good idea to document some of the expectations and reasons for why we think we can safely store OneByteConst's in 'static's and use them across isolates.
@mmastrac mmastrac merged commit 308a113 into denoland:main Jul 12, 2023
8 checks passed
@aapoalas aapoalas deleted the exp/external-const-one-byte-rust-side-vtable branch July 12, 2023 13:31
static_assert(sizeof(ExternalConstOneByteStringResource) == 24,
"ExternalConstOneByteStringResource size was not 24");
static_assert(alignof(ExternalConstOneByteStringResource) == 8,
"ExternalConstOneByteStringResource align was not 8");
Copy link
Contributor

@avindra avindra Jul 23, 2023

Choose a reason for hiding this comment

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

FWIW, the 32-bit build started failing here:

   ../../../src/binding.cc:68:1: error: static assertion failed due to requirement 'sizeof(v8::Isolate::DisallowJavascriptExecutionScope) == sizeof(unsigned int) * 2': DisallowJavascriptExecutionScope size mismatch
   static_assert(sizeof(v8::Isolate::DisallowJavascriptExecutionScope) ==
   ^             ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   ../../../src/binding.cc:68:69: note: expression evaluates to '12 == 8'
   static_assert(sizeof(v8::Isolate::DisallowJavascriptExecutionScope) ==
                 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^~
   ../../../src/binding.cc:1033:5: error: static assertion failed due to requirement '__builtin_offsetof(ExternalConstOneByteStringResource, _length) == 16': ExternalConstOneByteStringResource length was not at offset 16
       static_assert(offsetof(ExternalConstOneByteStringResource, _length) == 16,
       ^             ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   ../../../src/binding.cc:1033:73: note: expression evaluates to '8 == 16'
       static_assert(offsetof(ExternalConstOneByteStringResource, _length) == 16,
                     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^~~~~
   ../../../src/binding.cc:1035:5: error: static assertion failed due to requirement 'sizeof(ExternalConstOneByteStringResource) == 24': ExternalConstOneByteStringResource size was not 24
       static_assert(sizeof(ExternalConstOneByteStringResource) == 24,
       ^             ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   ../../../src/binding.cc:1035:62: note: expression evaluates to '12 == 24'
       static_assert(sizeof(ExternalConstOneByteStringResource) == 24,
                     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^~~~~
   ../../../src/binding.cc:1037:5: error: static assertion failed due to requirement 'alignof(ExternalConstOneByteStringResource) == 8': ExternalConstOneByteStringResource align was not 8
       static_assert(alignof(ExternalConstOneByteStringResource) == 8,
       ^             ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   ../../../src/binding.cc:1037:63: note: expression evaluates to '4 == 8'
       static_assert(alignof(ExternalConstOneByteStringResource) == 8,
                     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^~~~

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@avindra Thanks for letting us know and sorry about the break! Can you check if this PR fixes the build on 32-bit architectures? #1289

Copy link
Contributor

Choose a reason for hiding this comment

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

Can you check if this PR fixes the build on 32-bit architectures? #1289

Sorry for the late reply. The 32 bit build passes now!

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.

None yet

5 participants