diff --git a/src/env.h b/src/env.h index 4fc6b31ffebd21..868f3e9f212f67 100644 --- a/src/env.h +++ b/src/env.h @@ -329,7 +329,7 @@ struct PackageConfig { V(script_context_constructor_template, v8::FunctionTemplate) \ V(script_data_constructor_function, v8::Function) \ V(secure_context_constructor_template, v8::FunctionTemplate) \ - V(shutdown_wrap_constructor_function, v8::Function) \ + V(shutdown_wrap_template, v8::ObjectTemplate) \ V(tcp_constructor_template, v8::FunctionTemplate) \ V(tick_callback_function, v8::Function) \ V(timers_callback_function, v8::Function) \ @@ -338,7 +338,7 @@ struct PackageConfig { V(udp_constructor_function, v8::Function) \ V(vm_parsing_context_symbol, v8::Symbol) \ V(url_constructor_function, v8::Function) \ - V(write_wrap_constructor_function, v8::Function) \ + V(write_wrap_template, v8::ObjectTemplate) \ V(fs_use_promises_symbol, v8::Symbol) class Environment; diff --git a/src/stream_base-inl.h b/src/stream_base-inl.h index 7523b3a545355f..f4c228d7c5956f 100644 --- a/src/stream_base-inl.h +++ b/src/stream_base-inl.h @@ -164,8 +164,9 @@ inline int StreamBase::Shutdown(v8::Local req_wrap_obj) { if (req_wrap_obj.IsEmpty()) { req_wrap_obj = - env->shutdown_wrap_constructor_function() + env->shutdown_wrap_template() ->NewInstance(env->context()).ToLocalChecked(); + StreamReq::ResetObject(req_wrap_obj); } AsyncHooks::DefaultTriggerAsyncIdScope trigger_scope(GetAsyncWrap()); @@ -203,8 +204,9 @@ inline StreamWriteResult StreamBase::Write( if (req_wrap_obj.IsEmpty()) { req_wrap_obj = - env->write_wrap_constructor_function() + env->write_wrap_template() ->NewInstance(env->context()).ToLocalChecked(); + StreamReq::ResetObject(req_wrap_obj); } AsyncHooks::DefaultTriggerAsyncIdScope trigger_scope(GetAsyncWrap()); @@ -427,6 +429,15 @@ inline void StreamReq::Done(int status, const char* error_str) { OnDone(status); } +inline void StreamReq::ResetObject(v8::Local obj) { +#ifdef DEBUG + CHECK_GT(obj->InternalFieldCount(), StreamReq::kStreamReqField); +#endif + ClearWrap(obj); + obj->SetAlignedPointerInInternalField(StreamReq::kStreamReqField, nullptr); +} + + } // namespace node #endif // defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS diff --git a/src/stream_base.h b/src/stream_base.h index 7264824265a579..3267e544a04195 100644 --- a/src/stream_base.h +++ b/src/stream_base.h @@ -46,6 +46,13 @@ class StreamReq { static StreamReq* FromObject(v8::Local req_wrap_obj); + // Sets all internal fields of `req_wrap_obj` to `nullptr`. + // This is what the `WriteWrap` and `ShutdownWrap` JS constructors do, + // and what we use in C++ after creating these objects from their + // v8::ObjectTemplates, to avoid the overhead of calling the + // constructor explicitly. + static inline void ResetObject(v8::Local req_wrap_obj); + protected: virtual void OnDone(int status) = 0; diff --git a/src/stream_wrap.cc b/src/stream_wrap.cc index 27fe48d1165c75..c696404849c9cc 100644 --- a/src/stream_wrap.cc +++ b/src/stream_wrap.cc @@ -60,9 +60,7 @@ void LibuvStreamWrap::Initialize(Local target, auto is_construct_call_callback = [](const FunctionCallbackInfo& args) { CHECK(args.IsConstructCall()); - ClearWrap(args.This()); - args.This()->SetAlignedPointerInInternalField( - StreamReq::kStreamReqField, nullptr); + StreamReq::ResetObject(args.This()); }; Local sw = FunctionTemplate::New(env->isolate(), is_construct_call_callback); @@ -72,7 +70,7 @@ void LibuvStreamWrap::Initialize(Local target, sw->SetClassName(wrapString); AsyncWrap::AddWrapMethods(env, sw); target->Set(wrapString, sw->GetFunction()); - env->set_shutdown_wrap_constructor_function(sw->GetFunction()); + env->set_shutdown_wrap_template(sw->InstanceTemplate()); Local ww = FunctionTemplate::New(env->isolate(), is_construct_call_callback); @@ -82,7 +80,7 @@ void LibuvStreamWrap::Initialize(Local target, ww->SetClassName(writeWrapString); AsyncWrap::AddWrapMethods(env, ww); target->Set(writeWrapString, ww->GetFunction()); - env->set_write_wrap_constructor_function(ww->GetFunction()); + env->set_write_wrap_template(ww->InstanceTemplate()); }