Skip to content

Commit ca852e3

Browse files
committed
timers: use V8 fast API calls
1 parent 3abbc38 commit ca852e3

12 files changed

+271
-59
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
@@ -677,6 +677,7 @@
677677
'src/string_decoder-inl.h',
678678
'src/string_search.h',
679679
'src/tcp_wrap.h',
680+
'src/timers.h',
680681
'src/tracing/agent.h',
681682
'src/tracing/node_trace_buffer.h',
682683
'src/tracing/node_trace_writer.h',

src/base_object_types.h

+2-1
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,8 @@ namespace node {
1313
V(fs_binding_data, fs::BindingData) \
1414
V(v8_binding_data, v8_utils::BindingData) \
1515
V(blob_binding_data, BlobBindingData) \
16-
V(process_binding_data, process::BindingData)
16+
V(process_binding_data, process::BindingData) \
17+
V(timers_binding_data, timers::BindingData)
1718

1819
#define UNSERIALIZABLE_BINDING_TYPES(V) \
1920
V(http2_binding_data, http2::BindingData) \

src/env.cc

+6-2
Original file line numberDiff line numberDiff line change
@@ -1299,12 +1299,16 @@ void Environment::ToggleImmediateRef(bool ref) {
12991299
}
13001300
}
13011301

1302-
1303-
Local<Value> Environment::GetNow() {
1302+
uint64_t Environment::GetNowUint64() {
13041303
uv_update_time(event_loop());
13051304
uint64_t now = uv_now(event_loop());
13061305
CHECK_GE(now, timer_base());
13071306
now -= timer_base();
1307+
return now;
1308+
}
1309+
1310+
Local<Value> Environment::GetNow() {
1311+
uint64_t now = GetNowUint64();
13081312
if (now <= 0xffffffff)
13091313
return Integer::NewFromUnsigned(isolate(), static_cast<uint32_t>(now));
13101314
else

src/env.h

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

893893
v8::Local<v8::Value> GetNow();
894+
uint64_t GetNowUint64();
895+
894896
void ScheduleTimer(int64_t duration);
895897
void ToggleTimerRef(bool ref);
896898

src/node_external_reference.h

+9
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,12 @@ namespace node {
1313
using CFunctionCallbackWithOneByteString =
1414
uint32_t (*)(v8::Local<v8::Value>, const v8::FastOneByteString&);
1515
using CFunctionCallback = void (*)(v8::Local<v8::Value> receiver);
16+
using CFunctionCallbackReturnDouble =
17+
double (*)(v8::Local<v8::Object> receiver);
18+
using CFunctionCallbackWithInt64 = void (*)(v8::Local<v8::Object> receiver,
19+
int64_t);
20+
using CFunctionCallbackWithBool = void (*)(v8::Local<v8::Object> receiver,
21+
bool);
1622

1723
// This class manages the external references from the V8 heap
1824
// to the C++ addresses in Node.js.
@@ -23,6 +29,9 @@ class ExternalReferenceRegistry {
2329
#define ALLOWED_EXTERNAL_REFERENCE_TYPES(V) \
2430
V(CFunctionCallback) \
2531
V(CFunctionCallbackWithOneByteString) \
32+
V(CFunctionCallbackReturnDouble) \
33+
V(CFunctionCallbackWithInt64) \
34+
V(CFunctionCallbackWithBool) \
2635
V(const v8::CFunctionInfo*) \
2736
V(v8::FunctionCallback) \
2837
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

0 commit comments

Comments
 (0)