Files
node/src/async_context_frame.cc
T
Nigro Simone 5a566ac6b9 src: cut small costs in node::MakeCallback
Enter the Environment's context only when it is not already the
entered and current one, set the async context frame only when it
changes, pass the resource variant to push_async_context() by const
reference, and grow and shrink the native resource stack with
push_back() and pop_back() instead of resize().

Refs: https://github.com/nodejs/performance/issues/24
Signed-off-by: Nigro Simone <nigro.simone@gmail.com>
PR-URL: https://github.com/nodejs/node/pull/66395
Reviewed-By: Xuguang Mei <meixuguang@gmail.com>
Reviewed-By: Yagiz Nizipli <yagiz@nizipli.com>
Reviewed-By: Chengzhong Wu <legendecas@gmail.com>
2026-10-20 14:24:33 +00:00

94 lines
2.7 KiB
C++

#include "async_context_frame.h" // NOLINT(build/include_inline)
#include "env-inl.h"
#include "node_errors.h"
#include "node_external_reference.h"
#include "tracing/traced_value.h"
#include "util-inl.h"
#include "debug_utils-inl.h"
#include "v8.h"
using v8::Context;
using v8::Isolate;
using v8::Local;
using v8::Object;
using v8::String;
using v8::Value;
namespace node {
namespace async_context_frame {
//
// Scope helper
//
Scope::Scope(Isolate* isolate, Local<Value> object) : isolate_(isolate) {
auto prior = exchange(isolate, object);
prior_.Reset(isolate, prior);
}
Scope::~Scope() {
auto value = prior_.Get(isolate_);
set(isolate_, value);
}
Local<Value> current(Isolate* isolate) {
return isolate->GetContinuationPreservedEmbedderDataV2().As<Value>();
}
void set(Environment* env, Local<Value> value) {
env->isolate()->SetContinuationPreservedEmbedderDataV2(value);
}
void set(Isolate* isolate, Local<Value> value) {
set(Environment::GetCurrent(isolate), value);
}
// NOTE: It's generally recommended to use async_context_frame::Scope
// but sometimes (such as enterWith) a direct exchange is needed.
Local<Value> exchange(Environment* env, Local<Value> value) {
auto prior = current(env->isolate());
// Usually the frame does not change, and there is nothing to set.
if (prior != value) set(env, value);
return prior;
}
Local<Value> exchange(Isolate* isolate, Local<Value> value) {
return exchange(Environment::GetCurrent(isolate), value);
}
void CreatePerContextProperties(Local<Object> target,
Local<Value> unused,
Local<Context> context,
void* priv) {
Environment* env = Environment::GetCurrent(context);
Local<String> getContinuationPreservedEmbedderData = FIXED_ONE_BYTE_STRING(
env->isolate(), "getContinuationPreservedEmbedderData");
Local<String> setContinuationPreservedEmbedderData = FIXED_ONE_BYTE_STRING(
env->isolate(), "setContinuationPreservedEmbedderData");
// Grab the intrinsics from the binding object and expose those to our
// binding layer.
Local<Object> binding = context->GetExtrasBindingObject();
target
->Set(context,
getContinuationPreservedEmbedderData,
binding->Get(context, getContinuationPreservedEmbedderData)
.ToLocalChecked())
.Check();
target
->Set(context,
setContinuationPreservedEmbedderData,
binding->Get(context, setContinuationPreservedEmbedderData)
.ToLocalChecked())
.Check();
}
} // namespace async_context_frame
} // namespace node
NODE_BINDING_CONTEXT_AWARE_INTERNAL(
async_context_frame, node::async_context_frame::CreatePerContextProperties)