Skip to content

Commit 2a672ee

Browse files
gurgundayaduh95
authored andcommitted
src: fast path empty native immediate drain
Signed-off-by: Gürgün Dayıoğlu <hey@gurgun.day> PR-URL: #62969 Reviewed-By: Anna Henningsen <anna@addaleax.net> Reviewed-By: Yagiz Nizipli <yagiz@nizipli.com>
1 parent 562b831 commit 2a672ee

3 files changed

Lines changed: 77 additions & 0 deletions

File tree

src/env.cc

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1411,9 +1411,19 @@ void Environment::RunAndClearInterrupts() {
14111411
}
14121412
}
14131413

1414+
bool Environment::HasNativeImmediates() const {
1415+
return native_immediates_.size() > 0 ||
1416+
native_immediates_threadsafe_.size() > 0 ||
1417+
native_immediates_interrupts_.size() > 0;
1418+
}
1419+
14141420
void Environment::RunAndClearNativeImmediates(bool only_refed) {
14151421
TRACE_EVENT0(TRACING_CATEGORY_NODE1(environment),
14161422
"RunAndClearNativeImmediates");
1423+
if (!HasNativeImmediates()) {
1424+
return;
1425+
}
1426+
14171427
HandleScope handle_scope(isolate_);
14181428
// In case the Isolate is no longer accessible just use an empty Local. This
14191429
// is not an issue for InternalCallbackScope as this case is already handled
@@ -1586,6 +1596,9 @@ void Environment::CheckImmediate(uv_check_t* handle) {
15861596
Environment* env = Environment::from_immediate_check_handle(handle);
15871597
TRACE_EVENT0(TRACING_CATEGORY_NODE1(environment), "CheckImmediate");
15881598

1599+
if (env->immediate_info()->count() == 0 && !env->HasNativeImmediates())
1600+
return;
1601+
15891602
HandleScope scope(env->isolate());
15901603
Context::Scope context_scope(env->context());
15911604

src/env.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1037,6 +1037,7 @@ class Environment final : public MemoryRetainer {
10371037

10381038
void RunAndClearNativeImmediates(bool only_refed = false);
10391039
void RunAndClearInterrupts();
1040+
bool HasNativeImmediates() const;
10401041

10411042
uv_buf_t allocate_managed_buffer(const size_t suggested_size);
10421043
std::unique_ptr<v8::BackingStore> release_managed_buffer(const uv_buf_t& buf);

test/cctest/test_environment.cc

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -401,6 +401,69 @@ TEST_F(EnvironmentTest, SetImmediateCleanup) {
401401
EXPECT_EQ(called_unref, 0);
402402
}
403403

404+
TEST_F(EnvironmentTest, RunAndClearNativeImmediatesSkipsEmptyScope) {
405+
const v8::HandleScope handle_scope(isolate_);
406+
const Argv argv;
407+
Env env{handle_scope, argv};
408+
v8::Local<v8::Context> context = env.context();
409+
410+
using IntVec = std::vector<int>;
411+
IntVec callback_calls;
412+
v8::Local<v8::Function> must_call =
413+
v8::Function::New(
414+
context,
415+
[](const v8::FunctionCallbackInfo<v8::Value>& info) {
416+
IntVec* callback_calls =
417+
static_cast<IntVec*>(info.Data().As<v8::External>()->Value(
418+
v8::kExternalPointerTypeTagDefault));
419+
callback_calls->push_back(info[0].As<v8::Int32>()->Value());
420+
},
421+
v8::External::New(isolate_,
422+
static_cast<void*>(&callback_calls),
423+
v8::kExternalPointerTypeTagDefault))
424+
.ToLocalChecked();
425+
context->Global()
426+
->Set(context,
427+
v8::String::NewFromUtf8Literal(isolate_, "mustCall"),
428+
must_call)
429+
.Check();
430+
431+
v8::Local<v8::Function> eval_in_env =
432+
node::LoadEnvironment(*env, "return eval;")
433+
.ToLocalChecked()
434+
.As<v8::Function>();
435+
436+
v8::Local<v8::Value> queue_microtask = v8::String::NewFromUtf8Literal(
437+
isolate_, "Promise.resolve().then(() => mustCall(1));");
438+
eval_in_env->Call(context, v8::Null(isolate_), 1, &queue_microtask)
439+
.ToLocalChecked();
440+
EXPECT_TRUE(callback_calls.empty());
441+
(*env)->RunAndClearNativeImmediates();
442+
EXPECT_TRUE(callback_calls.empty());
443+
444+
context->GetMicrotaskQueue()->PerformCheckpoint(isolate_);
445+
EXPECT_EQ(callback_calls, (IntVec{1}));
446+
callback_calls.clear();
447+
448+
queue_microtask = v8::String::NewFromUtf8Literal(
449+
isolate_, "Promise.resolve().then(() => mustCall(2));");
450+
eval_in_env->Call(context, v8::Null(isolate_), 1, &queue_microtask)
451+
.ToLocalChecked();
452+
EXPECT_TRUE(callback_calls.empty());
453+
454+
bool native_immediate_called = false;
455+
(*env)->SetImmediate(
456+
[&](node::Environment* env_arg) {
457+
EXPECT_EQ(env_arg, *env);
458+
native_immediate_called = true;
459+
},
460+
node::CallbackFlags::kRefed);
461+
462+
(*env)->RunAndClearNativeImmediates();
463+
EXPECT_TRUE(native_immediate_called);
464+
EXPECT_EQ(callback_calls, (IntVec{2}));
465+
}
466+
404467
static char hello[] = "hello";
405468

406469
TEST_F(EnvironmentTest, BufferWithFreeCallbackIsDetached) {

0 commit comments

Comments
 (0)