-
-
Notifications
You must be signed in to change notification settings - Fork 35.4k
http2, async-wrap: introduce AliasedBuffer class #15077
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
Changes from 1 commit
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
…r/variable names, adding const, some other stuff...
- Loading branch information
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -26,27 +26,24 @@ template <class NativeT, class V8T> | |
| class AliasedBuffer { | ||
| public: | ||
| AliasedBuffer(v8::Isolate* isolate, const size_t count) : | ||
| isolate_(isolate), | ||
| count_(count), | ||
| byte_offset_(0), | ||
| freeBuffer_(true) { | ||
| const v8::HandleScope handle_scope(this->isolate_); | ||
| isolate_(isolate), | ||
| count_(count), | ||
| byte_offset_(0), | ||
| free_buffer_(true) { | ||
| const v8::HandleScope handle_scope(isolate_); | ||
|
|
||
| const size_t sizeInBytes = sizeof(NativeT) * count; | ||
|
|
||
| // allocate native buffer | ||
| this->buffer_ = UncheckedCalloc<NativeT>(count); | ||
| if (this->buffer_ == nullptr) { | ||
| ABORT(); | ||
| } | ||
| buffer_ = Calloc<NativeT>(count); | ||
|
|
||
| // allocate v8 ArrayBuffer | ||
| v8::Local<v8::ArrayBuffer> ab = v8::ArrayBuffer::New( | ||
| this->isolate_, this->buffer_, sizeInBytes); | ||
| isolate_, buffer_, sizeInBytes); | ||
|
|
||
| // allocate v8 TypedArray | ||
| v8::Local<V8T> jsArray = V8T::New(ab, this->byte_offset_, count); | ||
| this->jsArray_ = v8::Global<V8T>(isolate, jsArray); | ||
| v8::Local<V8T> js_array = V8T::New(ab, byte_offset_, count); | ||
| js_array_ = v8::Global<V8T>(isolate, js_array); | ||
| } | ||
|
|
||
| /** | ||
|
|
@@ -58,40 +55,40 @@ class AliasedBuffer { | |
| * Note that byte_offset must by aligned by sizeof(NativeT). | ||
| */ | ||
| AliasedBuffer( | ||
| v8::Isolate* isolate, | ||
| const size_t byte_offset, | ||
| const size_t count, | ||
| const AliasedBuffer<uint8_t, | ||
| v8::Uint8Array>& backingBuffer) : | ||
| isolate_(isolate), | ||
| count_(count), | ||
| byte_offset_(byte_offset), | ||
| freeBuffer_(false) { | ||
| const v8::HandleScope handle_scope(this->isolate_); | ||
| v8::Isolate* isolate, | ||
| const size_t byte_offset, | ||
| const size_t count, | ||
| const AliasedBuffer<uint8_t, | ||
| v8::Uint8Array>& backing_buffer) : | ||
| isolate_(isolate), | ||
| count_(count), | ||
| byte_offset_(byte_offset), | ||
| free_buffer_(false) { | ||
| const v8::HandleScope handle_scope(isolate_); | ||
| // validate that the byte_offset is aligned with sizeof(NativeT) | ||
| CHECK_EQ(byte_offset & (sizeof(NativeT) - 1), 0); | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is missing a range check to make sure the byte length of this instance fits within the CHECK_LE(sizeof(NativeT) * count, backing_buffer.GetArrayBuffer()->ByteLength() - byte_offset);
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Fwiw, both that check and the existing check are also verified within V8
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @addaleax Possibly in a debug build, but I just created a module that creates a
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. added check |
||
| this->buffer_ = reinterpret_cast<NativeT*>( | ||
| const_cast<uint8_t*>(backingBuffer.GetNativeBuffer() + byte_offset)); | ||
| buffer_ = reinterpret_cast<NativeT*>( | ||
| const_cast<uint8_t*>(backing_buffer.GetNativeBuffer() + byte_offset)); | ||
|
|
||
| v8::Local<v8::ArrayBuffer> ab = backingBuffer.GetArrayBuffer(); | ||
| v8::Local<V8T> jsArray = V8T::New(ab, byte_offset, count); | ||
| this->jsArray_ = v8::Global<V8T>(isolate, jsArray); | ||
| v8::Local<v8::ArrayBuffer> ab = backing_buffer.GetArrayBuffer(); | ||
| v8::Local<V8T> js_array = V8T::New(ab, byte_offset, count); | ||
| js_array_ = v8::Global<V8T>(isolate, js_array); | ||
| } | ||
|
|
||
| AliasedBuffer(const AliasedBuffer& that) : | ||
| isolate_(that.isolate_), | ||
| count_(that.count_), | ||
| byte_offset_(that.byte_offset_), | ||
| buffer_(that.buffer_), | ||
| freeBuffer_(false) { | ||
| this->jsArray_ = v8::Global<V8T>(that.isolate_, that.GetJSArray()); | ||
| isolate_(that.isolate_), | ||
| count_(that.count_), | ||
| byte_offset_(that.byte_offset_), | ||
| buffer_(that.buffer_), | ||
| free_buffer_(false) { | ||
| js_array_ = v8::Global<V8T>(that.isolate_, that.GetJSArray()); | ||
| } | ||
|
|
||
| ~AliasedBuffer() { | ||
| if (this->freeBuffer_ && this->buffer_ != NULL) { | ||
| free(this->buffer_); | ||
| if (free_buffer_ && buffer_ != NULL) { | ||
| free(buffer_); | ||
| } | ||
| this->jsArray_.Reset(); | ||
| js_array_.Reset(); | ||
| } | ||
|
|
||
| /** | ||
|
|
@@ -100,74 +97,74 @@ class AliasedBuffer { | |
| */ | ||
| class Reference { | ||
| public: | ||
| Reference(AliasedBuffer<NativeT, V8T>* aliasedBuffer, size_t index) : | ||
| aliasedBuffer_(aliasedBuffer), | ||
| Reference(AliasedBuffer<NativeT, V8T>* aliased_buffer, size_t index) : | ||
| aliased_buffer_(aliased_buffer), | ||
| index_(index) { | ||
| } | ||
|
|
||
| Reference(const Reference& that) : | ||
| aliasedBuffer_(that.aliasedBuffer_), | ||
| aliased_buffer_(that.aliased_buffer_), | ||
| index_(that.index_) { | ||
| } | ||
|
|
||
| inline Reference& operator=(const NativeT &val) { | ||
| this->aliasedBuffer_->SetValue(this->index_, val); | ||
| aliased_buffer_->SetValue(index_, val); | ||
| return *this; | ||
| } | ||
|
|
||
| operator NativeT() { | ||
| return this->aliasedBuffer_->GetValue(this->index_); | ||
| operator NativeT() const { | ||
| return aliased_buffer_->GetValue(index_); | ||
| } | ||
|
|
||
| private: | ||
| AliasedBuffer<NativeT, V8T>* aliasedBuffer_; | ||
| AliasedBuffer<NativeT, V8T>* aliased_buffer_; | ||
| size_t index_; | ||
| }; | ||
|
|
||
| /** | ||
| * Get the underlying v8 TypedArray overlayed on top of the native buffer | ||
| */ | ||
| v8::Local<V8T> GetJSArray() const { | ||
| return this->jsArray_.Get(this->isolate_); | ||
| return js_array_.Get(isolate_); | ||
| } | ||
|
|
||
| /** | ||
| * Get the underlying v8::ArrayBuffer underlying the TypedArray and | ||
| * overlaying the native buffer | ||
| */ | ||
| v8::Local<v8::ArrayBuffer> GetArrayBuffer() const { | ||
| return this->GetJSArray()->Buffer(); | ||
| return GetJSArray()->Buffer(); | ||
| } | ||
|
|
||
| /** | ||
| * Get the underlying native buffer. Note that all reads/writes should occur | ||
| * through the GetValue/SetValue/operator[] methods | ||
| */ | ||
| inline const NativeT* GetNativeBuffer() const { | ||
| return this->buffer_; | ||
| return buffer_; | ||
| } | ||
|
|
||
| /** | ||
| * Synonym for GetBuffer() | ||
| */ | ||
| inline const NativeT* operator * () { | ||
| return this->GetNativeBuffer(); | ||
| inline const NativeT* operator * () const { | ||
| return GetNativeBuffer(); | ||
| } | ||
|
|
||
| /** | ||
| * Set position index to given value. | ||
| */ | ||
| inline void SetValue(const size_t index, NativeT value) { | ||
| CHECK_LT(index, this->count_); | ||
| this->buffer_[index] = value; | ||
| CHECK_LT(index, count_); | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. (same goes for this one, I assume) |
||
| buffer_[index] = value; | ||
| } | ||
|
|
||
| /** | ||
| * Get value at position index | ||
| */ | ||
| inline const NativeT GetValue(const size_t index) const { | ||
| CHECK_LT(index, this->count_); | ||
| return this->buffer_[index]; | ||
| CHECK_LT(index, count_); | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @trevnorris I’m pretty sure the reported performance difference is due to this check, it’s the only visible difference in the generated machine code. I’d suggest wrapping it in
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. confirmed. that is where the performance hit is coming from. wrapping it sounds good
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. this and the SetValue check are now in debug-only builds. |
||
| return buffer_[index]; | ||
| } | ||
|
|
||
| /** | ||
|
|
@@ -178,16 +175,16 @@ class AliasedBuffer { | |
| } | ||
|
|
||
| NativeT operator[](size_t index) const { | ||
| return this->GetValue(index); | ||
| return GetValue(index); | ||
| } | ||
|
|
||
| private: | ||
| v8::Isolate* const isolate_; | ||
| size_t count_; | ||
| size_t byte_offset_; | ||
| NativeT* buffer_; | ||
| v8::Global<V8T> jsArray_; | ||
| bool freeBuffer_; | ||
| v8::Global<V8T> js_array_; | ||
| bool free_buffer_; | ||
| }; | ||
| } // namespace node | ||
|
|
||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -349,7 +349,7 @@ inline Environment::~Environment() { | |
| delete[] heap_statistics_buffer_; | ||
| delete[] heap_space_statistics_buffer_; | ||
| delete[] http_parser_buffer_; | ||
| delete http2_state_; | ||
| delete http2_state_; | ||
| free(performance_state_); | ||
| } | ||
|
|
||
|
|
@@ -462,7 +462,7 @@ inline double Environment::trigger_id() { | |
| } | ||
|
|
||
| inline double Environment::get_init_trigger_id() { | ||
| AliasedBuffer<double, v8::Float64Array> uid_fields = | ||
| AliasedBuffer<double, v8::Float64Array>& uid_fields = | ||
| async_hooks()->uid_fields(); | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. You could use a reference (
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. yeah, you're right. I'll fix...
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. fixed |
||
| double tid = uid_fields[AsyncHooks::kInitTriggerId]; | ||
| uid_fields[AsyncHooks::kInitTriggerId] = 0; | ||
|
|
||
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.
if we don't expect a value of
count == 0then pleaseCHECK_GT(count, 0). if we do expect that possibility then please directly assignnullptrbecauseUncheckedCalloc()will still force ancount = 1allocation.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.
added
CHECK_GT(count, 0)