-
Notifications
You must be signed in to change notification settings - Fork 300
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
feat: Implement Rust-side const ExternalOneByteStringResource subclass #1275
Conversation
15b30f7
to
a33049d
Compare
a33049d
to
20ed043
Compare
….com:aapoalas/rusty_v8 into exp/external-const-one-byte-rust-side-vtable
There was a problem hiding this 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).
Feel free to do it! I intend to cut a new release of |
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.
static_assert(sizeof(ExternalConstOneByteStringResource) == 24, | ||
"ExternalConstOneByteStringResource size was not 24"); | ||
static_assert(alignof(ExternalConstOneByteStringResource) == 8, | ||
"ExternalConstOneByteStringResource align was not 8"); |
There was a problem hiding this comment.
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,
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^~~~
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
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!
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.