diff --git a/src/env-inl.h b/src/env-inl.h index 2b000ed9ace5f7..1e85bc07a4cc29 100644 --- a/src/env-inl.h +++ b/src/env-inl.h @@ -25,6 +25,7 @@ #if defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS #include "aliased_buffer.h" +#include "allocated_buffer-inl.h" #include "callback_queue-inl.h" #include "env.h" #include "node.h" @@ -971,6 +972,29 @@ inline IsolateData* Environment::isolate_data() const { return isolate_data_; } +inline uv_buf_t Environment::allocate_managed_buffer( + const size_t suggested_size) { + NoArrayBufferZeroFillScope no_zero_fill_scope(isolate_data()); + std::unique_ptr bs = + v8::ArrayBuffer::NewBackingStore(isolate(), suggested_size); + uv_buf_t buf = uv_buf_init(static_cast(bs->Data()), bs->ByteLength()); + released_allocated_buffers()->emplace(buf.base, std::move(bs)); + return buf; +} + +inline std::unique_ptr Environment::release_managed_buffer( + const uv_buf_t& buf) { + std::unique_ptr bs; + if (buf.base != nullptr) { + auto map = released_allocated_buffers(); + auto it = map->find(buf.base); + CHECK_NE(it, map->end()); + bs = std::move(it->second); + map->erase(it); + } + return bs; +} + std::unordered_map>* Environment::released_allocated_buffers() { return &released_allocated_buffers_; diff --git a/src/env.h b/src/env.h index f055e6b45013d9..0c3715151488f4 100644 --- a/src/env.h +++ b/src/env.h @@ -1438,6 +1438,9 @@ class Environment : public MemoryRetainer { void RunAndClearNativeImmediates(bool only_refed = false); void RunAndClearInterrupts(); + inline uv_buf_t allocate_managed_buffer(const size_t suggested_size); + inline std::unique_ptr release_managed_buffer( + const uv_buf_t& buf); inline std::unordered_map>* released_allocated_buffers(); diff --git a/src/udp_wrap.cc b/src/udp_wrap.cc index 10a5fd929f6037..10c92358cc7661 100644 --- a/src/udp_wrap.cc +++ b/src/udp_wrap.cc @@ -31,12 +31,16 @@ namespace node { using v8::Array; +using v8::ArrayBuffer; +using v8::BackingStore; +using v8::Boolean; using v8::Context; using v8::DontDelete; using v8::FunctionCallbackInfo; using v8::FunctionTemplate; using v8::HandleScope; using v8::Integer; +using v8::Isolate; using v8::Local; using v8::MaybeLocal; using v8::Object; @@ -314,7 +318,7 @@ void UDPWrap::BufferSize(const FunctionCallbackInfo& args) { CHECK(args[0]->IsUint32()); CHECK(args[1]->IsBoolean()); - bool is_recv = args[1].As()->Value(); + bool is_recv = args[1].As()->Value(); const char* uv_func_name = is_recv ? "uv_recv_buffer_size" : "uv_send_buffer_size"; @@ -679,7 +683,7 @@ void UDPWrap::OnAlloc(uv_handle_t* handle, } uv_buf_t UDPWrap::OnAlloc(size_t suggested_size) { - return AllocatedBuffer::AllocateManaged(env(), suggested_size).release(); + return env()->allocate_managed_buffer(suggested_size); } void UDPWrap::OnRecv(uv_udp_t* handle, @@ -696,27 +700,32 @@ void UDPWrap::OnRecv(ssize_t nread, const sockaddr* addr, unsigned int flags) { Environment* env = this->env(); - AllocatedBuffer buf(env, buf_); + Isolate* isolate = env->isolate(); + std::unique_ptr bs = env->release_managed_buffer(buf_); if (nread == 0 && addr == nullptr) { return; } - HandleScope handle_scope(env->isolate()); + HandleScope handle_scope(isolate); Context::Scope context_scope(env->context()); Local argv[] = { - Integer::New(env->isolate(), static_cast(nread)), + Integer::New(isolate, static_cast(nread)), object(), - Undefined(env->isolate()), - Undefined(env->isolate())}; + Undefined(isolate), + Undefined(isolate)}; if (nread < 0) { MakeCallback(env->onmessage_string(), arraysize(argv), argv); return; + } else if (nread == 0) { + bs = ArrayBuffer::NewBackingStore(isolate, 0); + } else { + bs = BackingStore::Reallocate(isolate, std::move(bs), nread); } - buf.Resize(nread); - argv[2] = buf.ToBuffer().ToLocalChecked(); + Local ab = ArrayBuffer::New(isolate, std::move(bs)); + argv[2] = Buffer::New(env, ab, 0, ab->ByteLength()).ToLocalChecked(); argv[3] = AddressToJS(env, addr); MakeCallback(env->onmessage_string(), arraysize(argv), argv); }