@@ -650,6 +650,7 @@ Http2Session::~Http2Session() {
650
650
stream.second ->session_ = nullptr ;
651
651
nghttp2_session_del (session_);
652
652
CHECK_EQ (current_nghttp2_memory_, 0 );
653
+ free (stream_buf_allocation_.base );
653
654
}
654
655
655
656
std::string Http2Session::diagnostic_name () const {
@@ -1259,7 +1260,17 @@ void Http2StreamListener::OnStreamRead(ssize_t nread, const uv_buf_t& buf) {
1259
1260
return ;
1260
1261
}
1261
1262
1262
- CHECK (!session->stream_buf_ab_ .IsEmpty ());
1263
+ Local<ArrayBuffer> ab;
1264
+ if (session->stream_buf_ab_ .IsEmpty ()) {
1265
+ ab = ArrayBuffer::New (env->isolate (),
1266
+ session->stream_buf_allocation_ .base ,
1267
+ session->stream_buf_allocation_ .len ,
1268
+ v8::ArrayBufferCreationMode::kInternalized );
1269
+ session->stream_buf_allocation_ = uv_buf_init (nullptr , 0 );
1270
+ session->stream_buf_ab_ .Reset (env->isolate (), ab);
1271
+ } else {
1272
+ ab = session->stream_buf_ab_ .Get (env->isolate ());
1273
+ }
1263
1274
1264
1275
// There is a single large array buffer for the entire data read from the
1265
1276
// network; create a slice of that array buffer and emit it as the
@@ -1271,7 +1282,7 @@ void Http2StreamListener::OnStreamRead(ssize_t nread, const uv_buf_t& buf) {
1271
1282
CHECK_LE (offset + buf.len , session->stream_buf_ .len );
1272
1283
1273
1284
Local<Object> buffer =
1274
- Buffer::New (env, session-> stream_buf_ab_ , offset, nread).ToLocalChecked ();
1285
+ Buffer::New (env, ab , offset, nread).ToLocalChecked ();
1275
1286
1276
1287
stream->CallJSOnreadMethod (nread, buffer);
1277
1288
}
@@ -1803,32 +1814,41 @@ Http2Stream* Http2Session::SubmitRequest(
1803
1814
}
1804
1815
1805
1816
// Callback used to receive inbound data from the i/o stream
1806
- void Http2Session::OnStreamRead (ssize_t nread, const uv_buf_t & buf ) {
1817
+ void Http2Session::OnStreamRead (ssize_t nread, const uv_buf_t & buf_ ) {
1807
1818
HandleScope handle_scope (env ()->isolate ());
1808
1819
Context::Scope context_scope (env ()->context ());
1809
1820
Http2Scope h2scope (this );
1810
1821
CHECK_NOT_NULL (stream_);
1811
1822
Debug (this , " receiving %d bytes" , nread);
1812
- IncrementCurrentSessionMemory (buf. len );
1823
+ CHECK_EQ (stream_buf_allocation_. base , nullptr );
1813
1824
CHECK (stream_buf_ab_.IsEmpty ());
1814
1825
1815
- OnScopeLeave on_scope_leave ([&]() {
1816
- // Once finished handling this write, reset the stream buffer.
1817
- // The memory has either been free()d or was handed over to V8.
1818
- DecrementCurrentSessionMemory (buf.len );
1819
- stream_buf_ab_ = Local<ArrayBuffer>();
1820
- stream_buf_ = uv_buf_init (nullptr , 0 );
1821
- });
1822
-
1823
1826
// Only pass data on if nread > 0
1824
1827
if (nread <= 0 ) {
1825
- free (buf .base );
1828
+ free (buf_ .base );
1826
1829
if (nread < 0 ) {
1827
1830
PassReadErrorToPreviousListener (nread);
1828
1831
}
1829
1832
return ;
1830
1833
}
1831
1834
1835
+ // Shrink to the actual amount of used data.
1836
+ uv_buf_t buf = buf_;
1837
+ buf.base = Realloc (buf.base , nread);
1838
+
1839
+ IncrementCurrentSessionMemory (nread);
1840
+ OnScopeLeave on_scope_leave ([&]() {
1841
+ // Once finished handling this write, reset the stream buffer.
1842
+ // The memory has either been free()d or was handed over to V8.
1843
+ // We use `nread` instead of `buf.size()` here, because the buffer is
1844
+ // cleared as part of the `.ToArrayBuffer()` call below.
1845
+ DecrementCurrentSessionMemory (nread);
1846
+ stream_buf_ab_.Reset ();
1847
+ free (stream_buf_allocation_.base );
1848
+ stream_buf_allocation_ = uv_buf_init (nullptr , 0 );
1849
+ stream_buf_ = uv_buf_init (nullptr , 0 );
1850
+ });
1851
+
1832
1852
// Make sure that there was no read previously active.
1833
1853
CHECK_NULL (stream_buf_.base );
1834
1854
CHECK_EQ (stream_buf_.len , 0 );
@@ -1845,13 +1865,10 @@ void Http2Session::OnStreamRead(ssize_t nread, const uv_buf_t& buf) {
1845
1865
1846
1866
Isolate* isolate = env ()->isolate ();
1847
1867
1848
- // Create an array buffer for the read data. DATA frames will be emitted
1849
- // as slices of this array buffer to avoid having to copy memory.
1850
- stream_buf_ab_ =
1851
- ArrayBuffer::New (isolate,
1852
- buf.base ,
1853
- nread,
1854
- v8::ArrayBufferCreationMode::kInternalized );
1868
+ // Store this so we can create an ArrayBuffer for read data from it.
1869
+ // DATA frames will be emitted as slices of that ArrayBuffer to avoid having
1870
+ // to copy memory.
1871
+ stream_buf_allocation_ = buf;
1855
1872
1856
1873
statistics_.data_received += nread;
1857
1874
ssize_t ret = Write (&stream_buf_, 1 );
0 commit comments