Skip to content

Commit 9567958

Browse files
committed
fixup! timers: use V8 fast API calls
1 parent 92a77aa commit 9567958

File tree

6 files changed

+39
-22
lines changed

6 files changed

+39
-22
lines changed

lib/internal/timers.js

+18-5
Original file line numberDiff line numberDiff line change
@@ -303,13 +303,17 @@ class ImmediateList {
303303
const immediateQueue = new ImmediateList();
304304

305305
function incRefCount() {
306-
if (timeoutInfo[0]++ === 0)
306+
if (timeoutInfo[0]++ === 0) {
307+
// We need to use the binding as the receiver for fast API calls.
307308
binding.toggleTimerRef(true);
309+
}
308310
}
309311

310312
function decRefCount() {
311-
if (--timeoutInfo[0] === 0)
313+
if (--timeoutInfo[0] === 0) {
314+
// We need to use the binding as the receiver for fast API calls.
312315
binding.toggleTimerRef(false);
316+
}
313317
}
314318

315319
// Schedule or re-schedule a timer.
@@ -353,6 +357,7 @@ function insertGuarded(item, refed, start) {
353357
item[kRefed] = refed;
354358
}
355359

360+
// We need to use the binding as the receiver for fast API calls.
356361
function insert(item, msecs, start = binding.getLibuvNow()) {
357362
// Truncate so that accuracy of sub-millisecond timers is not assumed.
358363
msecs = MathTrunc(msecs);
@@ -367,6 +372,7 @@ function insert(item, msecs, start = binding.getLibuvNow()) {
367372
timerListQueue.insert(list);
368373

369374
if (nextExpiry > expiry) {
375+
// We need to use the binding as the receiver for fast API calls.
370376
binding.scheduleTimer(msecs);
371377
nextExpiry = expiry;
372378
}
@@ -556,8 +562,10 @@ function getTimerCallbacks(runNextTicks) {
556562
emitBefore(asyncId, timer[trigger_async_id_symbol], timer);
557563

558564
let start;
559-
if (timer._repeat)
565+
if (timer._repeat) {
566+
// We need to use the binding as the receiver for fast API calls.
560567
start = binding.getLibuvNow();
568+
}
561569

562570
try {
563571
const args = timer._timerArgs;
@@ -624,17 +632,22 @@ class Immediate {
624632
ref() {
625633
if (this[kRefed] === false) {
626634
this[kRefed] = true;
627-
if (immediateInfo[kRefCount]++ === 0)
635+
636+
if (immediateInfo[kRefCount]++ === 0) {
637+
// We need to use the binding as the receiver for fast API calls.
628638
binding.toggleImmediateRef(true);
639+
}
629640
}
630641
return this;
631642
}
632643

633644
unref() {
634645
if (this[kRefed] === true) {
635646
this[kRefed] = false;
636-
if (--immediateInfo[kRefCount] === 0)
647+
if (--immediateInfo[kRefCount] === 0) {
648+
// We need to use the binding as the receiver for fast API calls.
637649
binding.toggleImmediateRef(false);
650+
}
638651
}
639652
return this;
640653
}

lib/timers.js

+3-1
Original file line numberDiff line numberDiff line change
@@ -323,8 +323,10 @@ function clearImmediate(immediate) {
323323
immediateInfo[kCount]--;
324324
immediate._destroyed = true;
325325

326-
if (immediate[kRefed] && --immediateInfo[kRefCount] === 0)
326+
if (immediate[kRefed] && --immediateInfo[kRefCount] === 0) {
327+
// We need to use the binding as the receiver for fast API calls.
327328
binding.toggleImmediateRef(false);
329+
}
328330
immediate[kRefed] = null;
329331

330332
if (destroyHooksExist() && immediate[async_id_symbol] !== undefined) {

src/timers.cc

+9-9
Original file line numberDiff line numberDiff line change
@@ -39,17 +39,17 @@ double BindingData::GetLibuvNowImpl(BindingData* data) {
3939
return static_cast<double>(data->env()->GetNowUint64());
4040
}
4141

42-
void BindingData::SlowScheduleTimers(const FunctionCallbackInfo<Value>& args) {
42+
void BindingData::SlowScheduleTimer(const FunctionCallbackInfo<Value>& args) {
4343
int64_t duration =
4444
args[0]->IntegerValue(args.GetIsolate()->GetCurrentContext()).FromJust();
45-
ScheduleTimersImpl(Environment::GetBindingData<BindingData>(args), duration);
45+
ScheduleTimerImpl(Environment::GetBindingData<BindingData>(args), duration);
4646
}
4747

48-
void BindingData::FastScheduleTimers(Local<Object> receiver, int64_t duration) {
49-
ScheduleTimersImpl(FromJSObject<BindingData>(receiver), duration);
48+
void BindingData::FastScheduleTimer(Local<Object> receiver, int64_t duration) {
49+
ScheduleTimerImpl(FromJSObject<BindingData>(receiver), duration);
5050
}
5151

52-
void BindingData::ScheduleTimersImpl(BindingData* data, int64_t duration) {
52+
void BindingData::ScheduleTimerImpl(BindingData* data, int64_t duration) {
5353
data->env()->ScheduleTimer(duration);
5454
}
5555

@@ -113,7 +113,7 @@ void BindingData::Deserialize(Local<Context> context,
113113
v8::CFunction BindingData::fast_get_libuv_now_(
114114
v8::CFunction::Make(FastGetLibuvNow));
115115
v8::CFunction BindingData::fast_schedule_timers_(
116-
v8::CFunction::Make(FastScheduleTimers));
116+
v8::CFunction::Make(FastScheduleTimer));
117117
v8::CFunction BindingData::fast_toggle_timer_ref_(
118118
v8::CFunction::Make(FastToggleTimerRef));
119119
v8::CFunction BindingData::fast_toggle_immediate_ref_(
@@ -134,7 +134,7 @@ void BindingData::Initialize(Local<Object> target,
134134
SetFastMethod(context,
135135
target,
136136
"scheduleTimer",
137-
SlowScheduleTimers,
137+
SlowScheduleTimer,
138138
&fast_schedule_timers_);
139139
SetFastMethod(context,
140140
target,
@@ -169,8 +169,8 @@ void BindingData::RegisterTimerExternalReferences(
169169
registry->Register(FastGetLibuvNow);
170170
registry->Register(fast_get_libuv_now_.GetTypeInfo());
171171

172-
registry->Register(SlowScheduleTimers);
173-
registry->Register(FastScheduleTimers);
172+
registry->Register(SlowScheduleTimer);
173+
registry->Register(FastScheduleTimer);
174174
registry->Register(fast_schedule_timers_.GetTypeInfo());
175175

176176
registry->Register(SlowToggleTimerRef);

src/timers.h

+7-7
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
#ifndef SRC_NODE_TIMERS_H_
2-
#define SRC_NODE_TIMERS_H_
1+
#ifndef SRC_TIMERS_H_
2+
#define SRC_TIMERS_H_
33

44
#if defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS
55

@@ -31,11 +31,11 @@ class BindingData : public SnapshotableObject {
3131
static double FastGetLibuvNow(v8::Local<v8::Object> receiver);
3232
static double GetLibuvNowImpl(BindingData* data);
3333

34-
static void SlowScheduleTimers(
34+
static void SlowScheduleTimer(
3535
const v8::FunctionCallbackInfo<v8::Value>& args);
36-
static void FastScheduleTimers(v8::Local<v8::Object> receiver,
37-
int64_t duration);
38-
static void ScheduleTimersImpl(BindingData* data, int64_t duration);
36+
static void FastScheduleTimer(v8::Local<v8::Object> receiver,
37+
int64_t duration);
38+
static void ScheduleTimerImpl(BindingData* data, int64_t duration);
3939

4040
static void SlowToggleTimerRef(
4141
const v8::FunctionCallbackInfo<v8::Value>& args);
@@ -67,4 +67,4 @@ class BindingData : public SnapshotableObject {
6767

6868
#endif // defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS
6969

70-
#endif // SRC_NODE_TIMERS_H_
70+
#endif // SRC_TIMERS_H_

test/parallel/test-timers-now.js

+1
Original file line numberDiff line numberDiff line change
@@ -7,4 +7,5 @@ const { internalBinding } = require('internal/test/binding');
77
const binding = internalBinding('timers');
88

99
// Return value of getLibuvNow() should easily fit in a SMI after start-up.
10+
// We need to use the binding as the receiver for fast API calls.
1011
assert(binding.getLibuvNow() < 0x3ffffff);

test/parallel/test-timers-ordering.js

+1
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ function f(i) {
3939
last_i = i;
4040

4141
// Check that this iteration is fired at least 1ms later than the previous
42+
// We need to use the binding as the receiver for fast API calls.
4243
const now = binding.getLibuvNow();
4344
assert(now >= last_ts + 1,
4445
`current ts ${now} < prev ts ${last_ts} + 1`);

0 commit comments

Comments
 (0)