Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit 9b4eec0

Browse filesBrowse files
committed
src: allow not materializing ArrayBuffers from C++
Where appropriate, use a helper that wraps around `ArrayBufferView::Buffer()` or `ArrayBufferView::CopyContents()` rather than `Buffer::Data()`, as that may help to avoid materializing the underlying `ArrayBuffer` when reading small typed arrays from C++. This allows keeping the performance benefits of the faster creation of heap-allocated small typed arrays in many cases. PR-URL: #26301 Reviewed-By: Matteo Collina <matteo.collina@gmail.com> Reviewed-By: James M Snell <jasnell@gmail.com>
1 parent e2baa68 commit 9b4eec0
Copy full SHA for 9b4eec0

File tree

Expand file treeCollapse file tree

8 files changed

+183
-145
lines changed
Open diff view settings
Filter options
Expand file treeCollapse file tree

8 files changed

+183
-145
lines changed
Open diff view settings
Collapse file

‎src/node_crypto.cc‎

Copy file name to clipboardExpand all lines: src/node_crypto.cc
+107-120Lines changed: 107 additions & 120 deletions
Large diffs are not rendered by default.
Collapse file

‎src/node_crypto.h‎

Copy file name to clipboardExpand all lines: src/node_crypto.h
+3-4Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -333,7 +333,7 @@ class SSLWrap {
333333

334334
ClientHelloParser hello_parser_;
335335

336-
Persistent<v8::Object> ocsp_response_;
336+
Persistent<v8::ArrayBufferView> ocsp_response_;
337337
Persistent<v8::Value> sni_context_;
338338

339339
friend class SecureContext;
@@ -462,7 +462,7 @@ class KeyObject : public BaseObject {
462462
static void New(const v8::FunctionCallbackInfo<v8::Value>& args);
463463

464464
static void Init(const v8::FunctionCallbackInfo<v8::Value>& args);
465-
void InitSecret(const char* key, size_t key_len);
465+
void InitSecret(v8::Local<v8::ArrayBufferView> abv);
466466
void InitPublic(const ManagedEVPPKey& pkey);
467467
void InitPrivate(const ManagedEVPPKey& pkey);
468468

@@ -803,8 +803,7 @@ class ECDH : public BaseObject {
803803
static void Initialize(Environment* env, v8::Local<v8::Object> target);
804804
static ECPointPointer BufferToPoint(Environment* env,
805805
const EC_GROUP* group,
806-
char* data,
807-
size_t len);
806+
v8::Local<v8::Value> buf);
808807

809808
// TODO(joyeecheung): track the memory used by OpenSSL types
810809
SET_NO_MEMORY_INFO()
Collapse file

‎src/node_http2.cc‎

Copy file name to clipboardExpand all lines: src/node_http2.cc
+12-14Lines changed: 12 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
namespace node {
1313

1414
using v8::ArrayBuffer;
15+
using v8::ArrayBufferView;
1516
using v8::Boolean;
1617
using v8::Context;
1718
using v8::Float64Array;
@@ -2483,7 +2484,7 @@ void Http2Session::Request(const FunctionCallbackInfo<Value>& args) {
24832484
// state of the Http2Session, it's simply a notification.
24842485
void Http2Session::Goaway(uint32_t code,
24852486
int32_t lastStreamID,
2486-
uint8_t* data,
2487+
const uint8_t* data,
24872488
size_t len) {
24882489
if (IsDestroyed())
24892490
return;
@@ -2508,16 +2509,13 @@ void Http2Session::Goaway(const FunctionCallbackInfo<Value>& args) {
25082509

25092510
uint32_t code = args[0]->Uint32Value(context).ToChecked();
25102511
int32_t lastStreamID = args[1]->Int32Value(context).ToChecked();
2511-
Local<Value> opaqueData = args[2];
2512-
uint8_t* data = nullptr;
2513-
size_t length = 0;
2512+
ArrayBufferViewContents<uint8_t> opaque_data;
25142513

2515-
if (Buffer::HasInstance(opaqueData)) {
2516-
data = reinterpret_cast<uint8_t*>(Buffer::Data(opaqueData));
2517-
length = Buffer::Length(opaqueData);
2514+
if (args[2]->IsArrayBufferView()) {
2515+
opaque_data.Read(args[2].As<ArrayBufferView>());
25182516
}
25192517

2520-
session->Goaway(code, lastStreamID, data, length);
2518+
session->Goaway(code, lastStreamID, opaque_data.data(), opaque_data.length());
25212519
}
25222520

25232521
// Update accounting of data chunks. This is used primarily to manage timeout
@@ -2772,10 +2770,10 @@ void Http2Session::Ping(const FunctionCallbackInfo<Value>& args) {
27722770

27732771
// A PING frame may have exactly 8 bytes of payload data. If not provided,
27742772
// then the current hrtime will be used as the payload.
2775-
uint8_t* payload = nullptr;
2776-
if (Buffer::HasInstance(args[0])) {
2777-
payload = reinterpret_cast<uint8_t*>(Buffer::Data(args[0]));
2778-
CHECK_EQ(Buffer::Length(args[0]), 8);
2773+
ArrayBufferViewContents<uint8_t, 8> payload;
2774+
if (args[0]->IsArrayBufferView()) {
2775+
payload.Read(args[0].As<ArrayBufferView>());
2776+
CHECK_EQ(payload.length(), 8);
27792777
}
27802778

27812779
Local<Object> obj;
@@ -2800,7 +2798,7 @@ void Http2Session::Ping(const FunctionCallbackInfo<Value>& args) {
28002798
// the callback will be invoked and a notification sent out to JS land. The
28012799
// notification will include the duration of the ping, allowing the round
28022800
// trip to be measured.
2803-
ping->Send(payload);
2801+
ping->Send(payload.data());
28042802
args.GetReturnValue().Set(true);
28052803
}
28062804

@@ -2872,7 +2870,7 @@ Http2Session::Http2Ping::Http2Ping(Http2Session* session, Local<Object> obj)
28722870
session_(session),
28732871
startTime_(uv_hrtime()) {}
28742872

2875-
void Http2Session::Http2Ping::Send(uint8_t* payload) {
2873+
void Http2Session::Http2Ping::Send(const uint8_t* payload) {
28762874
uint8_t data[8];
28772875
if (payload == nullptr) {
28782876
memcpy(&data, &startTime_, arraysize(data));
Collapse file

‎src/node_http2.h‎

Copy file name to clipboardExpand all lines: src/node_http2.h
+3-2Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -699,7 +699,8 @@ class Http2Session : public AsyncWrap, public StreamListener {
699699
void Close(uint32_t code = NGHTTP2_NO_ERROR,
700700
bool socket_closed = false);
701701
void Consume(Local<External> external);
702-
void Goaway(uint32_t code, int32_t lastStreamID, uint8_t* data, size_t len);
702+
void Goaway(uint32_t code, int32_t lastStreamID,
703+
const uint8_t* data, size_t len);
703704
void AltSvc(int32_t id,
704705
uint8_t* origin,
705706
size_t origin_len,
@@ -1089,7 +1090,7 @@ class Http2Session::Http2Ping : public AsyncWrap {
10891090
SET_MEMORY_INFO_NAME(Http2Ping)
10901091
SET_SELF_SIZE(Http2Ping)
10911092

1092-
void Send(uint8_t* payload);
1093+
void Send(const uint8_t* payload);
10931094
void Done(bool ack, const uint8_t* payload = nullptr);
10941095

10951096
private:
Collapse file

‎src/string_decoder.cc‎

Copy file name to clipboardExpand all lines: src/string_decoder.cc
+7-2Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
#include "string_decoder-inl.h"
55

66
using v8::Array;
7+
using v8::ArrayBufferView;
78
using v8::Context;
89
using v8::FunctionCallbackInfo;
910
using v8::Integer;
@@ -252,9 +253,13 @@ void DecodeData(const FunctionCallbackInfo<Value>& args) {
252253
StringDecoder* decoder =
253254
reinterpret_cast<StringDecoder*>(Buffer::Data(args[0]));
254255
CHECK_NOT_NULL(decoder);
255-
size_t nread = Buffer::Length(args[1]);
256+
257+
CHECK(args[1]->IsArrayBufferView());
258+
ArrayBufferViewContents<char> content(args[1].As<ArrayBufferView>());
259+
size_t length = content.length();
260+
256261
MaybeLocal<String> ret =
257-
decoder->DecodeData(args.GetIsolate(), Buffer::Data(args[1]), &nread);
262+
decoder->DecodeData(args.GetIsolate(), content.data(), &length);
258263
if (!ret.IsEmpty())
259264
args.GetReturnValue().Set(ret.ToLocalChecked());
260265
}
Collapse file

‎src/util-inl.h‎

Copy file name to clipboardExpand all lines: src/util-inl.h
+26Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -466,6 +466,32 @@ SlicedArguments::SlicedArguments(
466466
(*this)[i] = args[i + start];
467467
}
468468

469+
template <typename T, size_t S>
470+
ArrayBufferViewContents<T, S>::ArrayBufferViewContents(
471+
v8::Local<v8::Value> value) {
472+
CHECK(value->IsArrayBufferView());
473+
Read(value.As<v8::ArrayBufferView>());
474+
}
475+
476+
template <typename T, size_t S>
477+
ArrayBufferViewContents<T, S>::ArrayBufferViewContents(
478+
v8::Local<v8::ArrayBufferView> abv) {
479+
Read(abv);
480+
}
481+
482+
template <typename T, size_t S>
483+
void ArrayBufferViewContents<T, S>::Read(v8::Local<v8::ArrayBufferView> abv) {
484+
static_assert(sizeof(T) == 1, "Only supports one-byte data at the moment");
485+
length_ = abv->ByteLength();
486+
if (length_ > sizeof(stack_storage_) || abv->HasBuffer()) {
487+
data_ = static_cast<T*>(abv->Buffer()->GetContents().Data()) +
488+
abv->ByteOffset();
489+
} else {
490+
abv->CopyContents(stack_storage_, sizeof(stack_storage_));
491+
data_ = stack_storage_;
492+
}
493+
}
494+
469495
} // namespace node
470496

471497
#endif // defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS
Collapse file

‎src/util.cc‎

Copy file name to clipboardExpand all lines: src/util.cc
+4-3Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929

3030
namespace node {
3131

32+
using v8::ArrayBufferView;
3233
using v8::Isolate;
3334
using v8::Local;
3435
using v8::String;
@@ -89,11 +90,11 @@ BufferValue::BufferValue(Isolate* isolate, Local<Value> value) {
8990

9091
if (value->IsString()) {
9192
MakeUtf8String(isolate, value, this);
92-
} else if (Buffer::HasInstance(value)) {
93-
const size_t len = Buffer::Length(value);
93+
} else if (value->IsArrayBufferView()) {
94+
const size_t len = value.As<ArrayBufferView>()->ByteLength();
9495
// Leave place for the terminating '\0' byte.
9596
AllocateSufficientStorage(len + 1);
96-
memcpy(out(), Buffer::Data(value), len);
97+
value.As<ArrayBufferView>()->CopyContents(out(), len);
9798
SetLengthAndZeroTerminate(len);
9899
} else {
99100
Invalidate();
Collapse file

‎src/util.h‎

Copy file name to clipboardExpand all lines: src/util.h
+21Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -417,6 +417,27 @@ class MaybeStackBuffer {
417417
T buf_st_[kStackStorageSize];
418418
};
419419

420+
// Provides access to an ArrayBufferView's storage, either the original,
421+
// or for small data, a copy of it. This object's lifetime is bound to the
422+
// original ArrayBufferView's lifetime.
423+
template <typename T, size_t kStackStorageSize = 64>
424+
class ArrayBufferViewContents {
425+
public:
426+
ArrayBufferViewContents() {}
427+
428+
explicit inline ArrayBufferViewContents(v8::Local<v8::Value> value);
429+
explicit inline ArrayBufferViewContents(v8::Local<v8::ArrayBufferView> abv);
430+
inline void Read(v8::Local<v8::ArrayBufferView> abv);
431+
432+
inline const T* data() const { return data_; }
433+
inline size_t length() const { return length_; }
434+
435+
private:
436+
T stack_storage_[kStackStorageSize];
437+
T* data_ = nullptr;
438+
size_t length_ = 0;
439+
};
440+
420441
class Utf8Value : public MaybeStackBuffer<char> {
421442
public:
422443
explicit Utf8Value(v8::Isolate* isolate, v8::Local<v8::Value> value);

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.