From 95679580ef0ad798335f3ba3f874f69df4f674b4 Mon Sep 17 00:00:00 2001 From: Joyee Cheung Date: Thu, 9 Feb 2023 18:32:45 +0100 Subject: [PATCH] fixup! timers: use V8 fast API calls --- lib/internal/timers.js | 23 ++++++++++++++++++----- lib/timers.js | 4 +++- src/timers.cc | 18 +++++++++--------- src/timers.h | 14 +++++++------- test/parallel/test-timers-now.js | 1 + test/parallel/test-timers-ordering.js | 1 + 6 files changed, 39 insertions(+), 22 deletions(-) diff --git a/lib/internal/timers.js b/lib/internal/timers.js index 8e4daa706acd4ba..828f405aa93c218 100644 --- a/lib/internal/timers.js +++ b/lib/internal/timers.js @@ -303,13 +303,17 @@ class ImmediateList { const immediateQueue = new ImmediateList(); function incRefCount() { - if (timeoutInfo[0]++ === 0) + if (timeoutInfo[0]++ === 0) { + // We need to use the binding as the receiver for fast API calls. binding.toggleTimerRef(true); + } } function decRefCount() { - if (--timeoutInfo[0] === 0) + if (--timeoutInfo[0] === 0) { + // We need to use the binding as the receiver for fast API calls. binding.toggleTimerRef(false); + } } // Schedule or re-schedule a timer. @@ -353,6 +357,7 @@ function insertGuarded(item, refed, start) { item[kRefed] = refed; } +// We need to use the binding as the receiver for fast API calls. function insert(item, msecs, start = binding.getLibuvNow()) { // Truncate so that accuracy of sub-millisecond timers is not assumed. msecs = MathTrunc(msecs); @@ -367,6 +372,7 @@ function insert(item, msecs, start = binding.getLibuvNow()) { timerListQueue.insert(list); if (nextExpiry > expiry) { + // We need to use the binding as the receiver for fast API calls. binding.scheduleTimer(msecs); nextExpiry = expiry; } @@ -556,8 +562,10 @@ function getTimerCallbacks(runNextTicks) { emitBefore(asyncId, timer[trigger_async_id_symbol], timer); let start; - if (timer._repeat) + if (timer._repeat) { + // We need to use the binding as the receiver for fast API calls. start = binding.getLibuvNow(); + } try { const args = timer._timerArgs; @@ -624,8 +632,11 @@ class Immediate { ref() { if (this[kRefed] === false) { this[kRefed] = true; - if (immediateInfo[kRefCount]++ === 0) + + if (immediateInfo[kRefCount]++ === 0) { + // We need to use the binding as the receiver for fast API calls. binding.toggleImmediateRef(true); + } } return this; } @@ -633,8 +644,10 @@ class Immediate { unref() { if (this[kRefed] === true) { this[kRefed] = false; - if (--immediateInfo[kRefCount] === 0) + if (--immediateInfo[kRefCount] === 0) { + // We need to use the binding as the receiver for fast API calls. binding.toggleImmediateRef(false); + } } return this; } diff --git a/lib/timers.js b/lib/timers.js index fdb661f0ec00b94..ddfbeb58bb6a818 100644 --- a/lib/timers.js +++ b/lib/timers.js @@ -323,8 +323,10 @@ function clearImmediate(immediate) { immediateInfo[kCount]--; immediate._destroyed = true; - if (immediate[kRefed] && --immediateInfo[kRefCount] === 0) + if (immediate[kRefed] && --immediateInfo[kRefCount] === 0) { + // We need to use the binding as the receiver for fast API calls. binding.toggleImmediateRef(false); + } immediate[kRefed] = null; if (destroyHooksExist() && immediate[async_id_symbol] !== undefined) { diff --git a/src/timers.cc b/src/timers.cc index 2cb8a1cc72cdb0c..a55a72c8d8db25a 100644 --- a/src/timers.cc +++ b/src/timers.cc @@ -39,17 +39,17 @@ double BindingData::GetLibuvNowImpl(BindingData* data) { return static_cast(data->env()->GetNowUint64()); } -void BindingData::SlowScheduleTimers(const FunctionCallbackInfo& args) { +void BindingData::SlowScheduleTimer(const FunctionCallbackInfo& args) { int64_t duration = args[0]->IntegerValue(args.GetIsolate()->GetCurrentContext()).FromJust(); - ScheduleTimersImpl(Environment::GetBindingData(args), duration); + ScheduleTimerImpl(Environment::GetBindingData(args), duration); } -void BindingData::FastScheduleTimers(Local receiver, int64_t duration) { - ScheduleTimersImpl(FromJSObject(receiver), duration); +void BindingData::FastScheduleTimer(Local receiver, int64_t duration) { + ScheduleTimerImpl(FromJSObject(receiver), duration); } -void BindingData::ScheduleTimersImpl(BindingData* data, int64_t duration) { +void BindingData::ScheduleTimerImpl(BindingData* data, int64_t duration) { data->env()->ScheduleTimer(duration); } @@ -113,7 +113,7 @@ void BindingData::Deserialize(Local context, v8::CFunction BindingData::fast_get_libuv_now_( v8::CFunction::Make(FastGetLibuvNow)); v8::CFunction BindingData::fast_schedule_timers_( - v8::CFunction::Make(FastScheduleTimers)); + v8::CFunction::Make(FastScheduleTimer)); v8::CFunction BindingData::fast_toggle_timer_ref_( v8::CFunction::Make(FastToggleTimerRef)); v8::CFunction BindingData::fast_toggle_immediate_ref_( @@ -134,7 +134,7 @@ void BindingData::Initialize(Local target, SetFastMethod(context, target, "scheduleTimer", - SlowScheduleTimers, + SlowScheduleTimer, &fast_schedule_timers_); SetFastMethod(context, target, @@ -169,8 +169,8 @@ void BindingData::RegisterTimerExternalReferences( registry->Register(FastGetLibuvNow); registry->Register(fast_get_libuv_now_.GetTypeInfo()); - registry->Register(SlowScheduleTimers); - registry->Register(FastScheduleTimers); + registry->Register(SlowScheduleTimer); + registry->Register(FastScheduleTimer); registry->Register(fast_schedule_timers_.GetTypeInfo()); registry->Register(SlowToggleTimerRef); diff --git a/src/timers.h b/src/timers.h index 148ab53ea60e930..6821eec70f6974e 100644 --- a/src/timers.h +++ b/src/timers.h @@ -1,5 +1,5 @@ -#ifndef SRC_NODE_TIMERS_H_ -#define SRC_NODE_TIMERS_H_ +#ifndef SRC_TIMERS_H_ +#define SRC_TIMERS_H_ #if defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS @@ -31,11 +31,11 @@ class BindingData : public SnapshotableObject { static double FastGetLibuvNow(v8::Local receiver); static double GetLibuvNowImpl(BindingData* data); - static void SlowScheduleTimers( + static void SlowScheduleTimer( const v8::FunctionCallbackInfo& args); - static void FastScheduleTimers(v8::Local receiver, - int64_t duration); - static void ScheduleTimersImpl(BindingData* data, int64_t duration); + static void FastScheduleTimer(v8::Local receiver, + int64_t duration); + static void ScheduleTimerImpl(BindingData* data, int64_t duration); static void SlowToggleTimerRef( const v8::FunctionCallbackInfo& args); @@ -67,4 +67,4 @@ class BindingData : public SnapshotableObject { #endif // defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS -#endif // SRC_NODE_TIMERS_H_ +#endif // SRC_TIMERS_H_ diff --git a/test/parallel/test-timers-now.js b/test/parallel/test-timers-now.js index 3988fd6d6dba454..e5e97521f1b18f8 100644 --- a/test/parallel/test-timers-now.js +++ b/test/parallel/test-timers-now.js @@ -7,4 +7,5 @@ const { internalBinding } = require('internal/test/binding'); const binding = internalBinding('timers'); // Return value of getLibuvNow() should easily fit in a SMI after start-up. +// We need to use the binding as the receiver for fast API calls. assert(binding.getLibuvNow() < 0x3ffffff); diff --git a/test/parallel/test-timers-ordering.js b/test/parallel/test-timers-ordering.js index 89779b3ee172480..3942f358a4db17a 100644 --- a/test/parallel/test-timers-ordering.js +++ b/test/parallel/test-timers-ordering.js @@ -39,6 +39,7 @@ function f(i) { last_i = i; // Check that this iteration is fired at least 1ms later than the previous + // We need to use the binding as the receiver for fast API calls. const now = binding.getLibuvNow(); assert(now >= last_ts + 1, `current ts ${now} < prev ts ${last_ts} + 1`);