summaryrefslogtreecommitdiff
path: root/src/node_process_methods.cc
diff options
context:
space:
mode:
authorGus Caplan <me@gus.host>2020-05-28 00:10:22 -0500
committerGus Caplan <me@gus.host>2020-06-06 11:55:45 -0500
commitd8eef83757c263672832687ac7667927a7d0c059 (patch)
tree8c4a9697dc1bbfa041ae211f961a87ebcffa7b5a /src/node_process_methods.cc
parente983b1cece7d24f7b4776798916276d30b9e419a (diff)
downloadnode-new-d8eef83757c263672832687ac7667927a7d0c059.tar.gz
process: use v8 fast api calls for hrtime
Refs: https://github.com/nodejs/node/issues/33374 PR-URL: https://github.com/nodejs/node/pull/33600 Reviewed-By: Anna Henningsen <anna@addaleax.net> Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
Diffstat (limited to 'src/node_process_methods.cc')
-rw-r--r--src/node_process_methods.cc131
1 files changed, 98 insertions, 33 deletions
diff --git a/src/node_process_methods.cc b/src/node_process_methods.cc
index 6013dbb86b..d580f74478 100644
--- a/src/node_process_methods.cc
+++ b/src/node_process_methods.cc
@@ -7,6 +7,7 @@
#include "node_process.h"
#include "util-inl.h"
#include "uv.h"
+#include "v8-fast-api-calls.h"
#include "v8.h"
#include <vector>
@@ -33,7 +34,7 @@ namespace node {
using v8::Array;
using v8::ArrayBuffer;
-using v8::BigUint64Array;
+using v8::BackingStore;
using v8::Context;
using v8::Float64Array;
using v8::FunctionCallbackInfo;
@@ -46,7 +47,6 @@ using v8::Number;
using v8::Object;
using v8::String;
using v8::Uint32;
-using v8::Uint32Array;
using v8::Value;
namespace per_process {
@@ -131,35 +131,6 @@ static void Cwd(const FunctionCallbackInfo<Value>& args) {
args.GetReturnValue().Set(cwd);
}
-
-// Hrtime exposes libuv's uv_hrtime() high-resolution timer.
-
-// This is the legacy version of hrtime before BigInt was introduced in
-// JavaScript.
-// The value returned by uv_hrtime() is a 64-bit int representing nanoseconds,
-// so this function instead fills in an Uint32Array with 3 entries,
-// to avoid any integer overflow possibility.
-// The first two entries contain the second part of the value
-// broken into the upper/lower 32 bits to be converted back in JS,
-// because there is no Uint64Array in JS.
-// The third entry contains the remaining nanosecond part of the value.
-static void Hrtime(const FunctionCallbackInfo<Value>& args) {
- uint64_t t = uv_hrtime();
-
- Local<ArrayBuffer> ab = args[0].As<Uint32Array>()->Buffer();
- uint32_t* fields = static_cast<uint32_t*>(ab->GetBackingStore()->Data());
-
- fields[0] = (t / NANOS_PER_SEC) >> 32;
- fields[1] = (t / NANOS_PER_SEC) & 0xffffffff;
- fields[2] = t % NANOS_PER_SEC;
-}
-
-static void HrtimeBigInt(const FunctionCallbackInfo<Value>& args) {
- Local<ArrayBuffer> ab = args[0].As<BigUint64Array>()->Buffer();
- uint64_t* fields = static_cast<uint64_t*>(ab->GetBackingStore()->Data());
- fields[0] = uv_hrtime();
-}
-
static void Kill(const FunctionCallbackInfo<Value>& args) {
Environment* env = Environment::GetCurrent(args);
Local<Context> context = env->context();
@@ -452,6 +423,85 @@ static void ReallyExit(const FunctionCallbackInfo<Value>& args) {
env->Exit(code);
}
+class FastHrtime : public BaseObject {
+ public:
+ static Local<Object> New(Environment* env) {
+ Local<v8::ObjectTemplate> otmpl = v8::ObjectTemplate::New(env->isolate());
+ otmpl->SetInternalFieldCount(FastHrtime::kInternalFieldCount);
+
+ auto create_func = [env](auto fast_func, auto slow_func) {
+ auto cfunc = v8::CFunction::Make(fast_func);
+ return v8::FunctionTemplate::New(env->isolate(),
+ slow_func,
+ Local<Value>(),
+ Local<v8::Signature>(),
+ 0,
+ v8::ConstructorBehavior::kThrow,
+ v8::SideEffectType::kHasNoSideEffect,
+ &cfunc);
+ };
+
+ otmpl->Set(FIXED_ONE_BYTE_STRING(env->isolate(), "hrtime"),
+ create_func(FastNumber, SlowNumber));
+ otmpl->Set(FIXED_ONE_BYTE_STRING(env->isolate(), "hrtimeBigInt"),
+ create_func(FastBigInt, SlowBigInt));
+
+ Local<Object> obj = otmpl->NewInstance(env->context()).ToLocalChecked();
+
+ Local<ArrayBuffer> ab = ArrayBuffer::New(env->isolate(), 12);
+ new FastHrtime(env, obj, ab->GetBackingStore());
+ obj->Set(
+ env->context(), FIXED_ONE_BYTE_STRING(env->isolate(), "buffer"), ab)
+ .ToChecked();
+
+ return obj;
+ }
+
+ private:
+ FastHrtime(Environment* env,
+ Local<Object> object,
+ std::shared_ptr<v8::BackingStore> backing_store)
+ : BaseObject(env, object), backing_store_(backing_store) {}
+
+ void MemoryInfo(MemoryTracker* tracker) const override {}
+
+ SET_MEMORY_INFO_NAME(FastHrtime)
+ SET_SELF_SIZE(FastHrtime)
+
+ // This is the legacy version of hrtime before BigInt was introduced in
+ // JavaScript.
+ // The value returned by uv_hrtime() is a 64-bit int representing nanoseconds,
+ // so this function instead fills in an Uint32Array with 3 entries,
+ // to avoid any integer overflow possibility.
+ // The first two entries contain the second part of the value
+ // broken into the upper/lower 32 bits to be converted back in JS,
+ // because there is no Uint64Array in JS.
+ // The third entry contains the remaining nanosecond part of the value.
+ static void FastNumber(FastHrtime* receiver) {
+ uint64_t t = uv_hrtime();
+ uint32_t* fields = static_cast<uint32_t*>(receiver->backing_store_->Data());
+ fields[0] = (t / NANOS_PER_SEC) >> 32;
+ fields[1] = (t / NANOS_PER_SEC) & 0xffffffff;
+ fields[2] = t % NANOS_PER_SEC;
+ }
+
+ static void SlowNumber(const FunctionCallbackInfo<Value>& args) {
+ FastNumber(FromJSObject<FastHrtime>(args.Holder()));
+ }
+
+ static void FastBigInt(FastHrtime* receiver) {
+ uint64_t t = uv_hrtime();
+ uint64_t* fields = static_cast<uint64_t*>(receiver->backing_store_->Data());
+ fields[0] = t;
+ }
+
+ static void SlowBigInt(const FunctionCallbackInfo<Value>& args) {
+ FastBigInt(FromJSObject<FastHrtime>(args.Holder()));
+ }
+
+ std::shared_ptr<BackingStore> backing_store_;
+};
+
static void InitializeProcessMethods(Local<Object> target,
Local<Value> unused,
Local<Context> context,
@@ -475,8 +525,6 @@ static void InitializeProcessMethods(Local<Object> target,
env->SetMethod(target, "_rawDebug", RawDebug);
env->SetMethod(target, "memoryUsage", MemoryUsage);
env->SetMethod(target, "cpuUsage", CPUUsage);
- env->SetMethod(target, "hrtime", Hrtime);
- env->SetMethod(target, "hrtimeBigInt", HrtimeBigInt);
env->SetMethod(target, "resourceUsage", ResourceUsage);
env->SetMethod(target, "_getActiveRequests", GetActiveRequests);
@@ -488,9 +536,26 @@ static void InitializeProcessMethods(Local<Object> target,
env->SetMethod(target, "reallyExit", ReallyExit);
env->SetMethodNoSideEffect(target, "uptime", Uptime);
env->SetMethod(target, "patchProcessObject", PatchProcessObject);
+
+ target
+ ->Set(env->context(),
+ FIXED_ONE_BYTE_STRING(env->isolate(), "hrtime"),
+ FastHrtime::New(env))
+ .ToChecked();
}
} // namespace node
+namespace v8 {
+template <>
+class WrapperTraits<node::FastHrtime> {
+ public:
+ static const void* GetTypeInfo() {
+ static const int tag = 0;
+ return reinterpret_cast<const void*>(&tag);
+ }
+};
+} // namespace v8
+
NODE_MODULE_CONTEXT_AWARE_INTERNAL(process_methods,
node::InitializeProcessMethods)