Skip to content
Closed
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
responding to PR feedback: cleaning up whitespace, snake-casing membe…
…r/variable names, adding const, some other stuff...
  • Loading branch information
Mike Kaufman committed Sep 13, 2017
commit a47238b091a476b86e22c747db9cac704afde331
107 changes: 52 additions & 55 deletions src/aliased_buffer.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Copy link
Copy Markdown
Contributor

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 == 0 then please CHECK_GT(count, 0). if we do expect that possibility then please directly assign nullptr because UncheckedCalloc() will still force an count = 1 allocation.

Copy link
Copy Markdown
Author

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)


// 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);
}

/**
Expand All @@ -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);
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The 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 backing_buffer. e.g.:

CHECK_LE(sizeof(NativeT) * count, backing_buffer.GetArrayBuffer()->ByteLength() - byte_offset);

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The 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

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The 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 Float64Array and allowed me to have a count larger than the byte length of the array buffer.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The 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();
}

/**
Expand All @@ -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_);
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The 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_);
Copy link
Copy Markdown
Member

@addaleax addaleax Sep 5, 2017

Choose a reason for hiding this comment

The 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 #if defined(DEBUG) && DEBUG?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The 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

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The 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];
}

/**
Expand All @@ -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

Expand Down
4 changes: 2 additions & 2 deletions src/env-inl.h
Original file line number Diff line number Diff line change
Expand Up @@ -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_);
}

Expand Down Expand Up @@ -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();
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

You could use a reference (AliasedBuffer<double, v8::Float64Array>&) instead, right? I think that would allow you to get rid of AliasedBuffer's copy constructor (and mark that as deleted), which seems like a good idea to me, I think

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

yeah, you're right. I'll fix...

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

fixed

double tid = uid_fields[AsyncHooks::kInitTriggerId];
uid_fields[AsyncHooks::kInitTriggerId] = 0;
Expand Down
32 changes: 16 additions & 16 deletions src/node_http2.cc
Original file line number Diff line number Diff line change
Expand Up @@ -35,8 +35,8 @@ Nghttp2Session::Callbacks Nghttp2Session::callback_struct_saved[2] = {
Http2Options::Http2Options(Environment* env) {
nghttp2_option_new(&options_);

AliasedBuffer<uint32_t, v8::Uint32Array> buffer =
env->http2_state()->options_buffer;
AliasedBuffer<uint32_t, v8::Uint32Array>& buffer =
env->http2_state()->options_buffer;
uint32_t flags = buffer[IDX_OPTIONS_FLAGS];

if (flags & (1 << IDX_OPTIONS_MAX_DEFLATE_DYNAMIC_TABLE_SIZE)) {
Expand Down Expand Up @@ -93,8 +93,8 @@ ssize_t Http2Session::OnCallbackPadding(size_t frameLen,
Context::Scope context_scope(context);

if (object()->Has(context, env()->ongetpadding_string()).FromJust()) {
AliasedBuffer<uint32_t, v8::Uint32Array> buffer =
env()->http2_state()->padding_buffer;
AliasedBuffer<uint32_t, v8::Uint32Array>& buffer =
env()->http2_state()->padding_buffer;
buffer[PADDING_BUF_FRAME_LENGTH] = frameLen;
buffer[PADDING_BUF_MAX_PAYLOAD_LENGTH] = maxPayloadLen;
MakeCallback(env()->ongetpadding_string(), 0, nullptr);
Expand Down Expand Up @@ -135,8 +135,8 @@ void PackSettings(const FunctionCallbackInfo<Value>& args) {
std::vector<nghttp2_settings_entry> entries;
entries.reserve(6);

AliasedBuffer<uint32_t, v8::Uint32Array> buffer =
env->http2_state()->settings_buffer;
AliasedBuffer<uint32_t, v8::Uint32Array>& buffer =
env->http2_state()->settings_buffer;
uint32_t flags = buffer[IDX_SETTINGS_COUNT];

if (flags & (1 << IDX_SETTINGS_HEADER_TABLE_SIZE)) {
Expand Down Expand Up @@ -196,8 +196,8 @@ void PackSettings(const FunctionCallbackInfo<Value>& args) {
void RefreshDefaultSettings(const FunctionCallbackInfo<Value>& args) {
DEBUG_HTTP2("Http2Session: refreshing default settings\n");
Environment* env = Environment::GetCurrent(args);
AliasedBuffer<uint32_t, v8::Uint32Array> buffer =
env->http2_state()->settings_buffer;
AliasedBuffer<uint32_t, v8::Uint32Array>& buffer =
env->http2_state()->settings_buffer;

buffer[IDX_SETTINGS_HEADER_TABLE_SIZE] =
DEFAULT_SETTINGS_HEADER_TABLE_SIZE;
Expand All @@ -224,8 +224,8 @@ void RefreshSettings(const FunctionCallbackInfo<Value>& args) {
ASSIGN_OR_RETURN_UNWRAP(&session, args[0].As<Object>());
nghttp2_session* s = session->session();

AliasedBuffer<uint32_t, v8::Uint32Array> buffer =
env->http2_state()->settings_buffer;
AliasedBuffer<uint32_t, v8::Uint32Array>& buffer =
env->http2_state()->settings_buffer;
buffer[IDX_SETTINGS_HEADER_TABLE_SIZE] =
fn(s, NGHTTP2_SETTINGS_HEADER_TABLE_SIZE);
buffer[IDX_SETTINGS_MAX_CONCURRENT_STREAMS] =
Expand All @@ -246,8 +246,8 @@ void RefreshSessionState(const FunctionCallbackInfo<Value>& args) {
Environment* env = Environment::GetCurrent(args);
CHECK_EQ(args.Length(), 1);
CHECK(args[0]->IsObject());
AliasedBuffer<double, v8::Float64Array> buffer =
env->http2_state()->session_state_buffer;
AliasedBuffer<double, v8::Float64Array>& buffer =
env->http2_state()->session_state_buffer;
Http2Session* session;
ASSIGN_OR_RETURN_UNWRAP(&session, args[0].As<Object>());
nghttp2_session* s = session->session();
Expand Down Expand Up @@ -284,8 +284,8 @@ void RefreshStreamState(const FunctionCallbackInfo<Value>& args) {
nghttp2_session* s = session->session();
Nghttp2Stream* stream;

AliasedBuffer<double, v8::Float64Array> buffer =
env->http2_state()->stream_state_buffer;
AliasedBuffer<double, v8::Float64Array>& buffer =
env->http2_state()->stream_state_buffer;

if ((stream = session->FindStream(id)) == nullptr) {
buffer[IDX_STREAM_STATE] = NGHTTP2_STREAM_STATE_IDLE;
Expand Down Expand Up @@ -397,8 +397,8 @@ void Http2Session::SubmitSettings(const FunctionCallbackInfo<Value>& args) {
ASSIGN_OR_RETURN_UNWRAP(&session, args.Holder());
Environment* env = session->env();

AliasedBuffer<uint32_t, v8::Uint32Array> buffer =
env->http2_state()->settings_buffer;
AliasedBuffer<uint32_t, v8::Uint32Array>& buffer =
env->http2_state()->settings_buffer;
uint32_t flags = buffer[IDX_SETTINGS_COUNT];

std::vector<nghttp2_settings_entry> entries;
Expand Down
Loading