mirror of
https://github.com/zebrajr/node.git
synced 2025-12-06 12:20:27 +01:00
src: use a typed array internally for process._exiting
This would prevent manual writes to the _exiting JS property on the
process object by passing the data directly via a typed array for
performance.
This change partially addresses this TODO:
3d575a4f1b/src/api/hooks.cc (L68-L71)
Signed-off-by: Darshan Sen <raisinten@gmail.com>
PR-URL: https://github.com/nodejs/node/pull/43883
Reviewed-By: Anna Henningsen <anna@addaleax.net>
Reviewed-By: Joyee Cheung <joyeec9h3@gmail.com>
This commit is contained in:
parent
af0921d877
commit
42eb2e72de
|
|
@ -60,6 +60,10 @@ const {
|
||||||
deprecate,
|
deprecate,
|
||||||
exposeInterface,
|
exposeInterface,
|
||||||
} = require('internal/util');
|
} = require('internal/util');
|
||||||
|
const {
|
||||||
|
exiting_aliased_Uint32Array,
|
||||||
|
getHiddenValue,
|
||||||
|
} = internalBinding('util');
|
||||||
|
|
||||||
setupProcessObject();
|
setupProcessObject();
|
||||||
|
|
||||||
|
|
@ -67,6 +71,21 @@ setupGlobalProxy();
|
||||||
setupBuffer();
|
setupBuffer();
|
||||||
|
|
||||||
process.domain = null;
|
process.domain = null;
|
||||||
|
{
|
||||||
|
const exitingAliasedUint32Array =
|
||||||
|
getHiddenValue(process, exiting_aliased_Uint32Array);
|
||||||
|
ObjectDefineProperty(process, '_exiting', {
|
||||||
|
__proto__: null,
|
||||||
|
get() {
|
||||||
|
return exitingAliasedUint32Array[0] === 1;
|
||||||
|
},
|
||||||
|
set(value) {
|
||||||
|
exitingAliasedUint32Array[0] = value ? 1 : 0;
|
||||||
|
},
|
||||||
|
enumerable: true,
|
||||||
|
configurable: true,
|
||||||
|
});
|
||||||
|
}
|
||||||
process._exiting = false;
|
process._exiting = false;
|
||||||
|
|
||||||
// process.config is serialized config.gypi
|
// process.config is serialized config.gypi
|
||||||
|
|
|
||||||
|
|
@ -65,14 +65,11 @@ Maybe<int> EmitProcessExit(Environment* env) {
|
||||||
Context::Scope context_scope(context);
|
Context::Scope context_scope(context);
|
||||||
Local<Object> process_object = env->process_object();
|
Local<Object> process_object = env->process_object();
|
||||||
|
|
||||||
// TODO(addaleax): It might be nice to share process._exiting and
|
// TODO(addaleax): It might be nice to share process.exitCode via
|
||||||
// process.exitCode via getter/setter pairs that pass data directly to the
|
// getter/setter pairs that pass data directly to the native side, so that we
|
||||||
// native side, so that we don't manually have to read and write JS properties
|
// don't manually have to read and write JS properties here. These getters
|
||||||
// here. These getters could use e.g. a typed array for performance.
|
// could use e.g. a typed array for performance.
|
||||||
if (process_object
|
env->set_exiting(true);
|
||||||
->Set(context,
|
|
||||||
FIXED_ONE_BYTE_STRING(isolate, "_exiting"),
|
|
||||||
True(isolate)).IsNothing()) return Nothing<int>();
|
|
||||||
|
|
||||||
Local<String> exit_code = env->exit_code_string();
|
Local<String> exit_code = env->exit_code_string();
|
||||||
Local<Value> code_v;
|
Local<Value> code_v;
|
||||||
|
|
|
||||||
|
|
@ -371,6 +371,14 @@ inline bool Environment::force_context_aware() const {
|
||||||
return options_->force_context_aware;
|
return options_->force_context_aware;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline void Environment::set_exiting(bool value) {
|
||||||
|
exiting_[0] = value ? 1 : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline AliasedUint32Array& Environment::exiting() {
|
||||||
|
return exiting_;
|
||||||
|
}
|
||||||
|
|
||||||
inline void Environment::set_abort_on_uncaught_exception(bool value) {
|
inline void Environment::set_abort_on_uncaught_exception(bool value) {
|
||||||
options_->abort_on_uncaught_exception = value;
|
options_->abort_on_uncaught_exception = value;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -813,6 +813,7 @@ Environment::Environment(IsolateData* isolate_data,
|
||||||
exec_argv_(exec_args),
|
exec_argv_(exec_args),
|
||||||
argv_(args),
|
argv_(args),
|
||||||
exec_path_(GetExecPath(args)),
|
exec_path_(GetExecPath(args)),
|
||||||
|
exiting_(isolate_, 1, MAYBE_FIELD_PTR(env_info, exiting)),
|
||||||
should_abort_on_uncaught_toggle_(
|
should_abort_on_uncaught_toggle_(
|
||||||
isolate_,
|
isolate_,
|
||||||
1,
|
1,
|
||||||
|
|
@ -920,6 +921,9 @@ void Environment::InitializeMainContext(Local<Context> context,
|
||||||
// By default, always abort when --abort-on-uncaught-exception was passed.
|
// By default, always abort when --abort-on-uncaught-exception was passed.
|
||||||
should_abort_on_uncaught_toggle_[0] = 1;
|
should_abort_on_uncaught_toggle_[0] = 1;
|
||||||
|
|
||||||
|
// The process is not exiting by default.
|
||||||
|
set_exiting(false);
|
||||||
|
|
||||||
performance_state_->Mark(performance::NODE_PERFORMANCE_MILESTONE_ENVIRONMENT,
|
performance_state_->Mark(performance::NODE_PERFORMANCE_MILESTONE_ENVIRONMENT,
|
||||||
time_origin_);
|
time_origin_);
|
||||||
performance_state_->Mark(performance::NODE_PERFORMANCE_MILESTONE_NODE_START,
|
performance_state_->Mark(performance::NODE_PERFORMANCE_MILESTONE_NODE_START,
|
||||||
|
|
@ -1811,6 +1815,7 @@ EnvSerializeInfo Environment::Serialize(SnapshotCreator* creator) {
|
||||||
info.immediate_info = immediate_info_.Serialize(ctx, creator);
|
info.immediate_info = immediate_info_.Serialize(ctx, creator);
|
||||||
info.tick_info = tick_info_.Serialize(ctx, creator);
|
info.tick_info = tick_info_.Serialize(ctx, creator);
|
||||||
info.performance_state = performance_state_->Serialize(ctx, creator);
|
info.performance_state = performance_state_->Serialize(ctx, creator);
|
||||||
|
info.exiting = exiting_.Serialize(ctx, creator);
|
||||||
info.stream_base_state = stream_base_state_.Serialize(ctx, creator);
|
info.stream_base_state = stream_base_state_.Serialize(ctx, creator);
|
||||||
info.should_abort_on_uncaught_toggle =
|
info.should_abort_on_uncaught_toggle =
|
||||||
should_abort_on_uncaught_toggle_.Serialize(ctx, creator);
|
should_abort_on_uncaught_toggle_.Serialize(ctx, creator);
|
||||||
|
|
@ -1858,6 +1863,7 @@ std::ostream& operator<<(std::ostream& output, const EnvSerializeInfo& i) {
|
||||||
<< "// -- performance_state begins --\n"
|
<< "// -- performance_state begins --\n"
|
||||||
<< i.performance_state << ",\n"
|
<< i.performance_state << ",\n"
|
||||||
<< "// -- performance_state ends --\n"
|
<< "// -- performance_state ends --\n"
|
||||||
|
<< i.exiting << ", // exiting\n"
|
||||||
<< i.stream_base_state << ", // stream_base_state\n"
|
<< i.stream_base_state << ", // stream_base_state\n"
|
||||||
<< i.should_abort_on_uncaught_toggle
|
<< i.should_abort_on_uncaught_toggle
|
||||||
<< ", // should_abort_on_uncaught_toggle\n"
|
<< ", // should_abort_on_uncaught_toggle\n"
|
||||||
|
|
@ -1901,6 +1907,7 @@ void Environment::DeserializeProperties(const EnvSerializeInfo* info) {
|
||||||
immediate_info_.Deserialize(ctx);
|
immediate_info_.Deserialize(ctx);
|
||||||
tick_info_.Deserialize(ctx);
|
tick_info_.Deserialize(ctx);
|
||||||
performance_state_->Deserialize(ctx);
|
performance_state_->Deserialize(ctx);
|
||||||
|
exiting_.Deserialize(ctx);
|
||||||
stream_base_state_.Deserialize(ctx);
|
stream_base_state_.Deserialize(ctx);
|
||||||
should_abort_on_uncaught_toggle_.Deserialize(ctx);
|
should_abort_on_uncaught_toggle_.Deserialize(ctx);
|
||||||
|
|
||||||
|
|
@ -2121,6 +2128,7 @@ void Environment::MemoryInfo(MemoryTracker* tracker) const {
|
||||||
native_modules_without_cache);
|
native_modules_without_cache);
|
||||||
tracker->TrackField("destroy_async_id_list", destroy_async_id_list_);
|
tracker->TrackField("destroy_async_id_list", destroy_async_id_list_);
|
||||||
tracker->TrackField("exec_argv", exec_argv_);
|
tracker->TrackField("exec_argv", exec_argv_);
|
||||||
|
tracker->TrackField("exiting", exiting_);
|
||||||
tracker->TrackField("should_abort_on_uncaught_toggle",
|
tracker->TrackField("should_abort_on_uncaught_toggle",
|
||||||
should_abort_on_uncaught_toggle_);
|
should_abort_on_uncaught_toggle_);
|
||||||
tracker->TrackField("stream_base_state", stream_base_state_);
|
tracker->TrackField("stream_base_state", stream_base_state_);
|
||||||
|
|
|
||||||
27
src/env.h
27
src/env.h
|
|
@ -164,15 +164,16 @@ class NoArrayBufferZeroFillScope {
|
||||||
// Private symbols are per-isolate primitives but Environment proxies them
|
// Private symbols are per-isolate primitives but Environment proxies them
|
||||||
// for the sake of convenience. Strings should be ASCII-only and have a
|
// for the sake of convenience. Strings should be ASCII-only and have a
|
||||||
// "node:" prefix to avoid name clashes with third-party code.
|
// "node:" prefix to avoid name clashes with third-party code.
|
||||||
#define PER_ISOLATE_PRIVATE_SYMBOL_PROPERTIES(V) \
|
#define PER_ISOLATE_PRIVATE_SYMBOL_PROPERTIES(V) \
|
||||||
V(alpn_buffer_private_symbol, "node:alpnBuffer") \
|
V(alpn_buffer_private_symbol, "node:alpnBuffer") \
|
||||||
V(arrow_message_private_symbol, "node:arrowMessage") \
|
V(arrow_message_private_symbol, "node:arrowMessage") \
|
||||||
V(contextify_context_private_symbol, "node:contextify:context") \
|
V(contextify_context_private_symbol, "node:contextify:context") \
|
||||||
V(contextify_global_private_symbol, "node:contextify:global") \
|
V(contextify_global_private_symbol, "node:contextify:global") \
|
||||||
V(decorated_private_symbol, "node:decorated") \
|
V(decorated_private_symbol, "node:decorated") \
|
||||||
V(napi_type_tag, "node:napi:type_tag") \
|
V(napi_type_tag, "node:napi:type_tag") \
|
||||||
V(napi_wrapper, "node:napi:wrapper") \
|
V(napi_wrapper, "node:napi:wrapper") \
|
||||||
V(untransferable_object_private_symbol, "node:untransferableObject") \
|
V(untransferable_object_private_symbol, "node:untransferableObject") \
|
||||||
|
V(exiting_aliased_Uint32Array, "node:exiting_aliased_Uint32Array")
|
||||||
|
|
||||||
// Symbols are per-isolate primitives but Environment proxies them
|
// Symbols are per-isolate primitives but Environment proxies them
|
||||||
// for the sake of convenience.
|
// for the sake of convenience.
|
||||||
|
|
@ -973,6 +974,7 @@ struct EnvSerializeInfo {
|
||||||
TickInfo::SerializeInfo tick_info;
|
TickInfo::SerializeInfo tick_info;
|
||||||
ImmediateInfo::SerializeInfo immediate_info;
|
ImmediateInfo::SerializeInfo immediate_info;
|
||||||
performance::PerformanceState::SerializeInfo performance_state;
|
performance::PerformanceState::SerializeInfo performance_state;
|
||||||
|
AliasedBufferIndex exiting;
|
||||||
AliasedBufferIndex stream_base_state;
|
AliasedBufferIndex stream_base_state;
|
||||||
AliasedBufferIndex should_abort_on_uncaught_toggle;
|
AliasedBufferIndex should_abort_on_uncaught_toggle;
|
||||||
|
|
||||||
|
|
@ -1173,6 +1175,11 @@ class Environment : public MemoryRetainer {
|
||||||
inline void set_force_context_aware(bool value);
|
inline void set_force_context_aware(bool value);
|
||||||
inline bool force_context_aware() const;
|
inline bool force_context_aware() const;
|
||||||
|
|
||||||
|
// This is a pseudo-boolean that keeps track of whether the process is
|
||||||
|
// exiting.
|
||||||
|
inline void set_exiting(bool value);
|
||||||
|
inline AliasedUint32Array& exiting();
|
||||||
|
|
||||||
// This stores whether the --abort-on-uncaught-exception flag was passed
|
// This stores whether the --abort-on-uncaught-exception flag was passed
|
||||||
// to Node.
|
// to Node.
|
||||||
inline bool abort_on_uncaught_exception() const;
|
inline bool abort_on_uncaught_exception() const;
|
||||||
|
|
@ -1570,6 +1577,8 @@ class Environment : public MemoryRetainer {
|
||||||
uint32_t script_id_counter_ = 0;
|
uint32_t script_id_counter_ = 0;
|
||||||
uint32_t function_id_counter_ = 0;
|
uint32_t function_id_counter_ = 0;
|
||||||
|
|
||||||
|
AliasedUint32Array exiting_;
|
||||||
|
|
||||||
AliasedUint32Array should_abort_on_uncaught_toggle_;
|
AliasedUint32Array should_abort_on_uncaught_toggle_;
|
||||||
int should_not_abort_scope_counter_ = 0;
|
int should_not_abort_scope_counter_ = 0;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -91,6 +91,15 @@ MaybeLocal<Object> CreateProcessObject(Environment* env) {
|
||||||
return MaybeLocal<Object>();
|
return MaybeLocal<Object>();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// process[exiting_aliased_Uint32Array]
|
||||||
|
if (process
|
||||||
|
->SetPrivate(context,
|
||||||
|
env->exiting_aliased_Uint32Array(),
|
||||||
|
env->exiting().GetJSArray())
|
||||||
|
.IsNothing()) {
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
// process.version
|
// process.version
|
||||||
READONLY_PROPERTY(process,
|
READONLY_PROPERTY(process,
|
||||||
"version",
|
"version",
|
||||||
|
|
|
||||||
1
typings/internalBinding/util.d.ts
vendored
1
typings/internalBinding/util.d.ts
vendored
|
|
@ -17,6 +17,7 @@ declare function InternalBinding(binding: 'util'): {
|
||||||
napi_type_tag: 5;
|
napi_type_tag: 5;
|
||||||
napi_wrapper: 6;
|
napi_wrapper: 6;
|
||||||
untransferable_object_private_symbol: 7;
|
untransferable_object_private_symbol: 7;
|
||||||
|
exiting_aliased_Uint32Array: 8;
|
||||||
|
|
||||||
kPending: 0;
|
kPending: 0;
|
||||||
kFulfilled: 1;
|
kFulfilled: 1;
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user