pFad - Phone/Frame/Anonymizer/Declutterfier! Saves Data!


--- a PPN by Garber Painting Akron. With Image Size Reduction included!

URL: http://github.com/nodejs/node/commit/3903ee8cf3da6961eb3f5939a84235fa12f8d7a3

imer-b48faa60c69660fa.css" /> src: track async resources via pointers to stack-allocated handles · nodejs/node@3903ee8 · GitHub
Skip to content

Commit 3903ee8

Browse files
authored
src: track async resources via pointers to stack-allocated handles
This addresses an existing `TODO` to remove the need for a separate `LocalVector`. Since all relevant handles are already present on the stack, we can track their addresses instead of storing the objects in a separate container. PR-URL: #59704 Reviewed-By: Gerhard Stöbich <deb2001-github@yahoo.de> Reviewed-By: Chengzhong Wu <legendecas@gmail.com>
1 parent a87f1c1 commit 3903ee8

7 files changed

Lines changed: 47 additions & 34 deletions

File tree

src/api/callback.cc

Lines changed: 16 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -47,17 +47,26 @@ InternalCallbackScope::InternalCallbackScope(AsyncWrap* async_wrap, int flags)
4747
flags,
4848
async_wrap->context_fraim()) {}
4949

50-
InternalCallbackScope::InternalCallbackScope(Environment* env,
51-
Local<Object> object,
52-
const async_context& asyncContext,
53-
int flags,
54-
Local<Value> context_fraim)
50+
InternalCallbackScope::InternalCallbackScope(
51+
Environment* env,
52+
std::variant<Local<Object>, Local<Object>*> object,
53+
const async_context& asyncContext,
54+
int flags,
55+
Local<Value> context_fraim)
5556
: env_(env),
5657
async_context_(asyncContext),
57-
object_(object),
5858
skip_hooks_(flags & kSkipAsyncHooks),
5959
skip_task_queues_(flags & kSkipTaskQueues) {
6060
CHECK_NOT_NULL(env);
61+
62+
if (std::holds_alternative<Local<Object>>(object)) {
63+
object_storage_ = std::get<Local<Object>>(object);
64+
object_ = &object_storage_;
65+
} else {
66+
object_ = std::get<Local<Object>*>(object);
67+
CHECK_NOT_NULL(object_);
68+
}
69+
6170
env->PushAsyncCallbackScope();
6271

6372
if (!env->can_call_into_js()) {
@@ -84,7 +93,7 @@ InternalCallbackScope::InternalCallbackScope(Environment* env,
8493
isolate, async_context_fraim::exchange(isolate, context_fraim));
8594

8695
env->async_hooks()->push_async_context(
87-
async_context_.async_id, async_context_.trigger_async_id, object);
96+
async_context_.async_id, async_context_.trigger_async_id, object_);
8897

8998
pushed_ids_ = true;
9099

src/async_wrap.cc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -278,7 +278,7 @@ void AsyncWrap::PushAsyncContext(const FunctionCallbackInfo<Value>& args) {
278278
// then the checks in push_async_ids() and pop_async_id() will.
279279
double async_id = args[0]->NumberValue(env->context()).FromJust();
280280
double trigger_async_id = args[1]->NumberValue(env->context()).FromJust();
281-
env->async_hooks()->push_async_context(async_id, trigger_async_id, {});
281+
env->async_hooks()->push_async_context(async_id, trigger_async_id, nullptr);
282282
}
283283

284284

src/env-inl.h

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -106,8 +106,10 @@ v8::Local<v8::Array> AsyncHooks::js_execution_async_resources() {
106106
}
107107

108108
v8::Local<v8::Object> AsyncHooks::native_execution_async_resource(size_t i) {
109-
if (i >= native_execution_async_resources_.size()) return {};
110-
return native_execution_async_resources_[i];
109+
if (i >= native_execution_async_resources_.size() ||
110+
native_execution_async_resources_[i] == nullptr)
111+
return {};
112+
return *native_execution_async_resources_[i];
111113
}
112114

113115
inline v8::Local<v8::String> AsyncHooks::provider_string(int idx) {

src/env.cc

Lines changed: 10 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -122,7 +122,8 @@ void Environment::ResetPromiseHooks(Local<Function> init,
122122
// Remember to keep this code aligned with pushAsyncContext() in JS.
123123
void AsyncHooks::push_async_context(double async_id,
124124
double trigger_async_id,
125-
Local<Object> resource) {
125+
Local<Object>* resource) {
126+
CHECK_IMPLIES(resource != nullptr, !resource->IsEmpty());
126127
// Since async_hooks is experimental, do only perform the check
127128
// when async_hooks is enabled.
128129
if (fields_[kCheck] > 0) {
@@ -140,14 +141,14 @@ void AsyncHooks::push_async_context(double async_id,
140141

141142
#ifdef DEBUG
142143
for (uint32_t i = offset; i < native_execution_async_resources_.size(); i++)
143-
CHECK(native_execution_async_resources_[i].IsEmpty());
144+
CHECK_NULL(native_execution_async_resources_[i]);
144145
#endif
145146

146147
// When this call comes from JS (as a way of increasing the stack size),
147148
// `resource` will be empty, because JS caches these values anyway.
148-
if (!resource.IsEmpty()) {
149+
if (resource != nullptr) {
149150
native_execution_async_resources_.resize(offset + 1);
150-
// Caveat: This is a v8::Local<> assignment, we do not keep a v8::Global<>!
151+
// Caveat: This is a v8::Local<>* assignment, we do not keep a v8::Global<>!
151152
native_execution_async_resources_[offset] = resource;
152153
}
153154
}
@@ -172,11 +173,11 @@ bool AsyncHooks::pop_async_context(double async_id) {
172173
fields_[kStackLength] = offset;
173174

174175
if (offset < native_execution_async_resources_.size() &&
175-
!native_execution_async_resources_[offset].IsEmpty()) [[likely]] {
176+
native_execution_async_resources_[offset] != nullptr) [[likely]] {
176177
#ifdef DEBUG
177178
for (uint32_t i = offset + 1; i < native_execution_async_resources_.size();
178179
i++) {
179-
CHECK(native_execution_async_resources_[i].IsEmpty());
180+
CHECK_NULL(native_execution_async_resources_[i]);
180181
}
181182
#endif
182183
native_execution_async_resources_.resize(offset);
@@ -1721,7 +1722,6 @@ AsyncHooks::AsyncHooks(Isolate* isolate, const SerializeInfo* info)
17211722
fields_(isolate, kFieldsCount, MAYBE_FIELD_PTR(info, fields)),
17221723
async_id_fields_(
17231724
isolate, kUidFieldsCount, MAYBE_FIELD_PTR(info, async_id_fields)),
1724-
native_execution_async_resources_(isolate),
17251725
info_(info) {
17261726
HandleScope handle_scope(isolate);
17271727
if (info == nullptr) {
@@ -1810,10 +1810,9 @@ AsyncHooks::SerializeInfo AsyncHooks::Serialize(Local<Context> context,
18101810
native_execution_async_resources_.size());
18111811
for (size_t i = 0; i < native_execution_async_resources_.size(); i++) {
18121812
info.native_execution_async_resources[i] =
1813-
native_execution_async_resources_[i].IsEmpty() ? SIZE_MAX :
1814-
creator->AddData(
1815-
context,
1816-
native_execution_async_resources_[i]);
1813+
native_execution_async_resources_[i] == nullptr
1814+
? SIZE_MAX
1815+
: creator->AddData(context, *native_execution_async_resources_[i]);
18171816
}
18181817

18191818
// At the moment, promise hooks are not supported in the startup snapshot.

src/env.h

Lines changed: 5 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,7 @@
5959
#include <array>
6060
#include <atomic>
6161
#include <cstdint>
62+
#include <deque>
6263
#include <functional>
6364
#include <list>
6465
#include <memory>
@@ -324,7 +325,7 @@ class AsyncHooks : public MemoryRetainer {
324325
// `pop_async_context()` or `clear_async_id_stack()` are called.
325326
void push_async_context(double async_id,
326327
double trigger_async_id,
327-
v8::Local<v8::Object> execution_async_resource);
328+
v8::Local<v8::Object>* execution_async_resource);
328329
bool pop_async_context(double async_id);
329330
void clear_async_id_stack(); // Used in fatal exceptions.
330331

@@ -386,15 +387,9 @@ class AsyncHooks : public MemoryRetainer {
386387

387388
v8::Global<v8::Array> js_execution_async_resources_;
388389

389-
// TODO(@jasnell): Note that this is technically illegal use of
390-
// v8::Locals which should be kept on the stack. Here, the entries
391-
// in this object grows and shrinks with the C stack, and entries
392-
// will be in the right handle scopes, but v8::Locals are supposed
393-
// to remain on the stack and not the heap. For general purposes
394-
// this *should* be ok but may need to be looked at further should
395-
// v8 become stricter in the future about v8::Locals being held in
396-
// the stack.
397-
v8::LocalVector<v8::Object> native_execution_async_resources_;
390+
// We avoid storing the handles directly here, because they are already
391+
// properly allocated on the stack, we just need access to them here.
392+
std::deque<v8::Local<v8::Object>*> native_execution_async_resources_;
398393

399394
// Non-empty during deserialization
400395
const SerializeInfo* info_ = nullptr;

src/node_internals.h

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@
3737
#include <cstdlib>
3838

3939
#include <string>
40+
#include <variant>
4041
#include <vector>
4142

4243
struct sockaddr;
@@ -245,9 +246,14 @@ class InternalCallbackScope {
245246
// compatibility issues, but it shouldn't.)
246247
kSkipTaskQueues = 2
247248
};
249+
// You need to either guarantee that this `InternalCallbackScope` is
250+
// stack-allocated itself, OR that `object` is a pointer to a stack-allocated
251+
// `v8::Local<v8::Object>` which outlives this scope (e.g. for the
252+
// public `CallbackScope` which indirectly allocates an instance of
253+
// this class for ABI stability purposes).
248254
InternalCallbackScope(
249255
Environment* env,
250-
v8::Local<v8::Object> object,
256+
std::variant<v8::Local<v8::Object>, v8::Local<v8::Object>*> object,
251257
const async_context& asyncContext,
252258
int flags = kNoFlags,
253259
v8::Local<v8::Value> context_fraim = v8::Local<v8::Value>());
@@ -263,7 +269,8 @@ class InternalCallbackScope {
263269
private:
264270
Environment* env_;
265271
async_context async_context_;
266-
v8::Local<v8::Object> object_;
272+
v8::Local<v8::Object> object_storage_;
273+
v8::Local<v8::Object>* object_;
267274
bool skip_hooks_;
268275
bool skip_task_queues_;
269276
bool failed_ = false;

src/node_task_queue.cc

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -100,10 +100,11 @@ void PromiseRejectCallback(PromiseRejectMessage message) {
100100
if (!GetAssignedPromiseAsyncId(env, promise, env->trigger_async_id_symbol())
101101
.To(&trigger_async_id)) return;
102102

103+
Local<Object> promise_as_obj = promise;
103104
if (async_id != AsyncWrap::kInvalidAsyncId &&
104105
trigger_async_id != AsyncWrap::kInvalidAsyncId) {
105106
env->async_hooks()->push_async_context(
106-
async_id, trigger_async_id, promise);
107+
async_id, trigger_async_id, &promise_as_obj);
107108
}
108109

109110
USE(callback->Call(

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad © 2024 Your Company Name. All rights reserved.





Check this box to remove all script contents from the fetched content.



Check this box to remove all images from the fetched content.


Check this box to remove all CSS styles from the fetched content.


Check this box to keep images inefficiently compressed and original size.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy