summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAnna Henningsen <anna@addaleax.net>2018-02-23 16:53:54 +0100
committerAnna Henningsen <anna@addaleax.net>2018-03-15 12:53:22 +0100
commitd93c48bf61d6b74bc080da8568df6f2eac44f275 (patch)
tree2c3001c36c355ad67e58753e40179d9d677fee12
parent12b9ec09b0807a0b362986c80d3c4b9a644c611e (diff)
downloadandroid-node-v8-d93c48bf61d6b74bc080da8568df6f2eac44f275.tar.gz
android-node-v8-d93c48bf61d6b74bc080da8568df6f2eac44f275.tar.bz2
android-node-v8-d93c48bf61d6b74bc080da8568df6f2eac44f275.zip
src: use ObjectTemplate for creating stream req objs
This allows V8 to avoid preparing a execution context for the constructor, to give a (kinda) small but noticeable perf gain. Benchmarks (only this commit): $ ./node benchmark/compare.js --new ./node --old ./node-master --filter net-c2s.js --set len=10 --set type=asc --runs 360 net | Rscript benchmark/compare.R [01:15:27|% 100| 1/1 files | 720/720 runs | 1/1 configs]: Done confidence improvement accuracy (*) (**) (***) net/net-c2s.js dur=5 type='asc' len=10 *** 0.69 % ±0.31% ±0.41% ±0.53% PR-URL: https://github.com/nodejs/node/pull/18936 Reviewed-By: James M Snell <jasnell@gmail.com> Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
-rw-r--r--src/env.h4
-rw-r--r--src/stream_base-inl.h15
-rw-r--r--src/stream_base.h7
-rw-r--r--src/stream_wrap.cc8
4 files changed, 25 insertions, 9 deletions
diff --git a/src/env.h b/src/env.h
index 4fc6b31ffe..868f3e9f21 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 7523b3a545..f4c228d7c5 100644
--- a/src/stream_base-inl.h
+++ b/src/stream_base-inl.h
@@ -164,8 +164,9 @@ inline int StreamBase::Shutdown(v8::Local<v8::Object> 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<v8::Object> 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 7264824265..3267e544a0 100644
--- a/src/stream_base.h
+++ b/src/stream_base.h
@@ -46,6 +46,13 @@ class StreamReq {
static StreamReq* FromObject(v8::Local<v8::Object> 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<v8::Object> req_wrap_obj);
+
protected:
virtual void OnDone(int status) = 0;
diff --git a/src/stream_wrap.cc b/src/stream_wrap.cc
index 27fe48d116..c696404849 100644
--- a/src/stream_wrap.cc
+++ b/src/stream_wrap.cc
@@ -60,9 +60,7 @@ void LibuvStreamWrap::Initialize(Local<Object> target,
auto is_construct_call_callback =
[](const FunctionCallbackInfo<Value>& args) {
CHECK(args.IsConstructCall());
- ClearWrap(args.This());
- args.This()->SetAlignedPointerInInternalField(
- StreamReq::kStreamReqField, nullptr);
+ StreamReq::ResetObject(args.This());
};
Local<FunctionTemplate> sw =
FunctionTemplate::New(env->isolate(), is_construct_call_callback);
@@ -72,7 +70,7 @@ void LibuvStreamWrap::Initialize(Local<Object> 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<FunctionTemplate> ww =
FunctionTemplate::New(env->isolate(), is_construct_call_callback);
@@ -82,7 +80,7 @@ void LibuvStreamWrap::Initialize(Local<Object> 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());
}