7
7
#include " node_process.h"
8
8
#include " util-inl.h"
9
9
#include " uv.h"
10
+ #include " v8-fast-api-calls.h"
10
11
#include " v8.h"
11
12
12
13
#include < vector>
@@ -33,7 +34,7 @@ namespace node {
33
34
34
35
using v8::Array;
35
36
using v8::ArrayBuffer;
36
- using v8::BigUint64Array ;
37
+ using v8::BackingStore ;
37
38
using v8::Context;
38
39
using v8::Float64Array;
39
40
using v8::FunctionCallbackInfo;
@@ -46,7 +47,6 @@ using v8::Number;
46
47
using v8::Object;
47
48
using v8::String;
48
49
using v8::Uint32;
49
- using v8::Uint32Array;
50
50
using v8::Value;
51
51
52
52
namespace per_process {
@@ -131,35 +131,6 @@ static void Cwd(const FunctionCallbackInfo<Value>& args) {
131
131
args.GetReturnValue ().Set (cwd);
132
132
}
133
133
134
-
135
- // Hrtime exposes libuv's uv_hrtime() high-resolution timer.
136
-
137
- // This is the legacy version of hrtime before BigInt was introduced in
138
- // JavaScript.
139
- // The value returned by uv_hrtime() is a 64-bit int representing nanoseconds,
140
- // so this function instead fills in an Uint32Array with 3 entries,
141
- // to avoid any integer overflow possibility.
142
- // The first two entries contain the second part of the value
143
- // broken into the upper/lower 32 bits to be converted back in JS,
144
- // because there is no Uint64Array in JS.
145
- // The third entry contains the remaining nanosecond part of the value.
146
- static void Hrtime (const FunctionCallbackInfo<Value>& args) {
147
- uint64_t t = uv_hrtime ();
148
-
149
- Local<ArrayBuffer> ab = args[0 ].As <Uint32Array>()->Buffer ();
150
- uint32_t * fields = static_cast <uint32_t *>(ab->GetBackingStore ()->Data ());
151
-
152
- fields[0 ] = (t / NANOS_PER_SEC) >> 32 ;
153
- fields[1 ] = (t / NANOS_PER_SEC) & 0xffffffff ;
154
- fields[2 ] = t % NANOS_PER_SEC;
155
- }
156
-
157
- static void HrtimeBigInt (const FunctionCallbackInfo<Value>& args) {
158
- Local<ArrayBuffer> ab = args[0 ].As <BigUint64Array>()->Buffer ();
159
- uint64_t * fields = static_cast <uint64_t *>(ab->GetBackingStore ()->Data ());
160
- fields[0 ] = uv_hrtime ();
161
- }
162
-
163
134
static void Kill (const FunctionCallbackInfo<Value>& args) {
164
135
Environment* env = Environment::GetCurrent (args);
165
136
Local<Context> context = env->context ();
@@ -452,6 +423,85 @@ static void ReallyExit(const FunctionCallbackInfo<Value>& args) {
452
423
env->Exit (code);
453
424
}
454
425
426
+ class FastHrtime : public BaseObject {
427
+ public:
428
+ static Local<Object> New (Environment* env) {
429
+ Local<v8::ObjectTemplate> otmpl = v8::ObjectTemplate::New (env->isolate ());
430
+ otmpl->SetInternalFieldCount (FastHrtime::kInternalFieldCount );
431
+
432
+ auto create_func = [env](auto fast_func, auto slow_func) {
433
+ auto cfunc = v8::CFunction::Make (fast_func);
434
+ return v8::FunctionTemplate::New (env->isolate (),
435
+ slow_func,
436
+ Local<Value>(),
437
+ Local<v8::Signature>(),
438
+ 0 ,
439
+ v8::ConstructorBehavior::kThrow ,
440
+ v8::SideEffectType::kHasNoSideEffect ,
441
+ &cfunc);
442
+ };
443
+
444
+ otmpl->Set (FIXED_ONE_BYTE_STRING (env->isolate (), " hrtime" ),
445
+ create_func (FastNumber, SlowNumber));
446
+ otmpl->Set (FIXED_ONE_BYTE_STRING (env->isolate (), " hrtimeBigInt" ),
447
+ create_func (FastBigInt, SlowBigInt));
448
+
449
+ Local<Object> obj = otmpl->NewInstance (env->context ()).ToLocalChecked ();
450
+
451
+ Local<ArrayBuffer> ab = ArrayBuffer::New (env->isolate (), 12 );
452
+ new FastHrtime (env, obj, ab->GetBackingStore ());
453
+ obj->Set (
454
+ env->context (), FIXED_ONE_BYTE_STRING (env->isolate (), " buffer" ), ab)
455
+ .ToChecked ();
456
+
457
+ return obj;
458
+ }
459
+
460
+ private:
461
+ FastHrtime (Environment* env,
462
+ Local<Object> object,
463
+ std::shared_ptr<v8::BackingStore> backing_store)
464
+ : BaseObject(env, object), backing_store_(backing_store) {}
465
+
466
+ void MemoryInfo (MemoryTracker* tracker) const override {}
467
+
468
+ SET_MEMORY_INFO_NAME (FastHrtime)
469
+ SET_SELF_SIZE (FastHrtime)
470
+
471
+ // This is the legacy version of hrtime before BigInt was introduced in
472
+ // JavaScript.
473
+ // The value returned by uv_hrtime() is a 64-bit int representing nanoseconds,
474
+ // so this function instead fills in an Uint32Array with 3 entries,
475
+ // to avoid any integer overflow possibility.
476
+ // The first two entries contain the second part of the value
477
+ // broken into the upper/lower 32 bits to be converted back in JS,
478
+ // because there is no Uint64Array in JS.
479
+ // The third entry contains the remaining nanosecond part of the value.
480
+ static void FastNumber (FastHrtime* receiver) {
481
+ uint64_t t = uv_hrtime ();
482
+ uint32_t * fields = static_cast <uint32_t *>(receiver->backing_store_ ->Data ());
483
+ fields[0 ] = (t / NANOS_PER_SEC) >> 32 ;
484
+ fields[1 ] = (t / NANOS_PER_SEC) & 0xffffffff ;
485
+ fields[2 ] = t % NANOS_PER_SEC;
486
+ }
487
+
488
+ static void SlowNumber (const FunctionCallbackInfo<Value>& args) {
489
+ FastNumber (FromJSObject<FastHrtime>(args.Holder ()));
490
+ }
491
+
492
+ static void FastBigInt (FastHrtime* receiver) {
493
+ uint64_t t = uv_hrtime ();
494
+ uint64_t * fields = static_cast <uint64_t *>(receiver->backing_store_ ->Data ());
495
+ fields[0 ] = t;
496
+ }
497
+
498
+ static void SlowBigInt (const FunctionCallbackInfo<Value>& args) {
499
+ FastBigInt (FromJSObject<FastHrtime>(args.Holder ()));
500
+ }
501
+
502
+ std::shared_ptr<BackingStore> backing_store_;
503
+ };
504
+
455
505
static void InitializeProcessMethods (Local<Object> target,
456
506
Local<Value> unused,
457
507
Local<Context> context,
@@ -475,8 +525,6 @@ static void InitializeProcessMethods(Local<Object> target,
475
525
env->SetMethod (target, " _rawDebug" , RawDebug);
476
526
env->SetMethod (target, " memoryUsage" , MemoryUsage);
477
527
env->SetMethod (target, " cpuUsage" , CPUUsage);
478
- env->SetMethod (target, " hrtime" , Hrtime);
479
- env->SetMethod (target, " hrtimeBigInt" , HrtimeBigInt);
480
528
env->SetMethod (target, " resourceUsage" , ResourceUsage);
481
529
482
530
env->SetMethod (target, " _getActiveRequests" , GetActiveRequests);
@@ -488,9 +536,26 @@ static void InitializeProcessMethods(Local<Object> target,
488
536
env->SetMethod (target, " reallyExit" , ReallyExit);
489
537
env->SetMethodNoSideEffect (target, " uptime" , Uptime);
490
538
env->SetMethod (target, " patchProcessObject" , PatchProcessObject);
539
+
540
+ target
541
+ ->Set (env->context (),
542
+ FIXED_ONE_BYTE_STRING (env->isolate (), " hrtime" ),
543
+ FastHrtime::New (env))
544
+ .ToChecked ();
491
545
}
492
546
493
547
} // namespace node
494
548
549
+ namespace v8 {
550
+ template <>
551
+ class WrapperTraits <node::FastHrtime> {
552
+ public:
553
+ static const void * GetTypeInfo () {
554
+ static const int tag = 0 ;
555
+ return reinterpret_cast <const void *>(&tag);
556
+ }
557
+ };
558
+ } // namespace v8
559
+
495
560
NODE_MODULE_CONTEXT_AWARE_INTERNAL (process_methods,
496
561
node::InitializeProcessMethods)
0 commit comments