Skip to content

Commit f1c67f6

Browse files
committed
timers: use V8 fast API calls
1 parent 9e2b036 commit f1c67f6

12 files changed

+268
-55
lines changed

lib/internal/timers.js

+27-17
Original file line numberDiff line numberDiff line change
@@ -81,14 +81,11 @@ const {
8181
Symbol,
8282
} = primordials;
8383

84+
const binding = internalBinding('timers');
8485
const {
85-
scheduleTimer,
86-
toggleTimerRef,
87-
getLibuvNow,
8886
immediateInfo,
8987
timeoutInfo,
90-
toggleImmediateRef
91-
} = internalBinding('timers');
88+
} = binding;
9289

9390
const {
9491
getDefaultTriggerAsyncId,
@@ -306,13 +303,17 @@ class ImmediateList {
306303
const immediateQueue = new ImmediateList();
307304

308305
function incRefCount() {
309-
if (timeoutInfo[0]++ === 0)
310-
toggleTimerRef(true);
306+
if (timeoutInfo[0]++ === 0) {
307+
// We need to use the binding as the receiver for fast API calls.
308+
binding.toggleTimerRef(true);
309+
}
311310
}
312311

313312
function decRefCount() {
314-
if (--timeoutInfo[0] === 0)
315-
toggleTimerRef(false);
313+
if (--timeoutInfo[0] === 0) {
314+
// We need to use the binding as the receiver for fast API calls.
315+
binding.toggleTimerRef(false);
316+
}
316317
}
317318

318319
// Schedule or re-schedule a timer.
@@ -356,7 +357,8 @@ function insertGuarded(item, refed, start) {
356357
item[kRefed] = refed;
357358
}
358359

359-
function insert(item, msecs, start = getLibuvNow()) {
360+
// We need to use the binding as the receiver for fast API calls.
361+
function insert(item, msecs, start = binding.getLibuvNow()) {
360362
// Truncate so that accuracy of sub-millisecond timers is not assumed.
361363
msecs = MathTrunc(msecs);
362364
item._idleStart = start;
@@ -370,7 +372,8 @@ function insert(item, msecs, start = getLibuvNow()) {
370372
timerListQueue.insert(list);
371373

372374
if (nextExpiry > expiry) {
373-
scheduleTimer(msecs);
375+
// We need to use the binding as the receiver for fast API calls.
376+
binding.scheduleTimer(msecs);
374377
nextExpiry = expiry;
375378
}
376379
}
@@ -559,8 +562,10 @@ function getTimerCallbacks(runNextTicks) {
559562
emitBefore(asyncId, timer[trigger_async_id_symbol], timer);
560563

561564
let start;
562-
if (timer._repeat)
563-
start = getLibuvNow();
565+
if (timer._repeat) {
566+
// We need to use the binding as the receiver for fast API calls.
567+
start = binding.getLibuvNow();
568+
}
564569

565570
try {
566571
const args = timer._timerArgs;
@@ -627,17 +632,22 @@ class Immediate {
627632
ref() {
628633
if (this[kRefed] === false) {
629634
this[kRefed] = true;
630-
if (immediateInfo[kRefCount]++ === 0)
631-
toggleImmediateRef(true);
635+
636+
if (immediateInfo[kRefCount]++ === 0) {
637+
// We need to use the binding as the receiver for fast API calls.
638+
binding.toggleImmediateRef(true);
639+
}
632640
}
633641
return this;
634642
}
635643

636644
unref() {
637645
if (this[kRefed] === true) {
638646
this[kRefed] = false;
639-
if (--immediateInfo[kRefCount] === 0)
640-
toggleImmediateRef(false);
647+
if (--immediateInfo[kRefCount] === 0) {
648+
// We need to use the binding as the receiver for fast API calls.
649+
binding.toggleImmediateRef(false);
650+
}
641651
}
642652
return this;
643653
}

lib/timers.js

+6-4
Original file line numberDiff line numberDiff line change
@@ -27,10 +27,10 @@ const {
2727
SymbolToPrimitive
2828
} = primordials;
2929

30+
const binding = internalBinding('timers');
3031
const {
3132
immediateInfo,
32-
toggleImmediateRef
33-
} = internalBinding('timers');
33+
} = binding;
3434
const L = require('internal/linkedlist');
3535
const {
3636
async_id_symbol,
@@ -323,8 +323,10 @@ function clearImmediate(immediate) {
323323
immediateInfo[kCount]--;
324324
immediate._destroyed = true;
325325

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

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

node.gyp

+1
Original file line numberDiff line numberDiff line change
@@ -661,6 +661,7 @@
661661
'src/string_decoder-inl.h',
662662
'src/string_search.h',
663663
'src/tcp_wrap.h',
664+
'src/timers.h',
664665
'src/tracing/agent.h',
665666
'src/tracing/node_trace_buffer.h',
666667
'src/tracing/node_trace_writer.h',

src/env.cc

+6-2
Original file line numberDiff line numberDiff line change
@@ -1273,12 +1273,16 @@ void Environment::ToggleImmediateRef(bool ref) {
12731273
}
12741274
}
12751275

1276-
1277-
Local<Value> Environment::GetNow() {
1276+
uint64_t Environment::GetNowUint64() {
12781277
uv_update_time(event_loop());
12791278
uint64_t now = uv_now(event_loop());
12801279
CHECK_GE(now, timer_base());
12811280
now -= timer_base();
1281+
return now;
1282+
}
1283+
1284+
Local<Value> Environment::GetNow() {
1285+
uint64_t now = GetNowUint64();
12821286
if (now <= 0xffffffff)
12831287
return Integer::NewFromUnsigned(isolate(), static_cast<uint32_t>(now));
12841288
else

src/env.h

+2
Original file line numberDiff line numberDiff line change
@@ -908,6 +908,8 @@ class Environment : public MemoryRetainer {
908908
static inline Environment* ForAsyncHooks(AsyncHooks* hooks);
909909

910910
v8::Local<v8::Value> GetNow();
911+
uint64_t GetNowUint64();
912+
911913
void ScheduleTimer(int64_t duration);
912914
void ToggleTimerRef(bool ref);
913915

src/node_external_reference.h

+9
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,12 @@
1111
namespace node {
1212

1313
using CFunctionCallback = void (*)(v8::Local<v8::Value> receiver);
14+
using CFunctionCallbackReturnDouble =
15+
double (*)(v8::Local<v8::Object> receiver);
16+
using CFunctionCallbackWithInt64 = void (*)(v8::Local<v8::Object> receiver,
17+
int64_t);
18+
using CFunctionCallbackWithBool = void (*)(v8::Local<v8::Object> receiver,
19+
bool);
1420

1521
// This class manages the external references from the V8 heap
1622
// to the C++ addresses in Node.js.
@@ -20,6 +26,9 @@ class ExternalReferenceRegistry {
2026

2127
#define ALLOWED_EXTERNAL_REFERENCE_TYPES(V) \
2228
V(CFunctionCallback) \
29+
V(CFunctionCallbackReturnDouble) \
30+
V(CFunctionCallbackWithInt64) \
31+
V(CFunctionCallbackWithBool) \
2332
V(const v8::CFunctionInfo*) \
2433
V(v8::FunctionCallback) \
2534
V(v8::AccessorGetterCallback) \

src/node_snapshotable.cc

+1
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
#include "node_util.h"
2121
#include "node_v8.h"
2222
#include "node_v8_platform-inl.h"
23+
#include "timers.h"
2324

2425
#if HAVE_INSPECTOR
2526
#include "inspector/worker_inspector.h" // ParentInspectorHandle

src/node_snapshotable.h

+1
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ struct PropInfo {
2727
V(v8_binding_data, v8_utils::BindingData) \
2828
V(blob_binding_data, BlobBindingData) \
2929
V(process_binding_data, process::BindingData) \
30+
V(timers_binding_data, timers::BindingData) \
3031
V(util_weak_reference, util::WeakReference)
3132

3233
enum class EmbedderObjectType : uint8_t {

0 commit comments

Comments
 (0)