Skip to content

Commit 4a8ea63

Browse files
Matt Loringjasnell
Matt Loring
authored andcommitted
async_wrap,src: wrap promises directly
Promises do not have any internal fields by default. V8 recently added the capability of configuring the number of internal fields on promises. This change adds an internal field to promises allowing promises to be wrapped directly by the PromiseWrap object. In addition to cleaner code this avoids an extra object allocation per promise and speeds up promise creation with async_hooks enabled by ~2x. PR-URL: #13242 Ref: #13224 Reviewed-By: Andreas Madsen <[email protected]> Reviewed-By: Anna Henningsen <[email protected]>
1 parent 0be029e commit 4a8ea63

File tree

3 files changed

+4
-31
lines changed

3 files changed

+4
-31
lines changed

configure

+1
Original file line numberDiff line numberDiff line change
@@ -954,6 +954,7 @@ def configure_v8(o):
954954
o['variables']['v8_no_strict_aliasing'] = 1 # Work around compiler bugs.
955955
o['variables']['v8_optimized_debug'] = 0 # Compile with -O0 in debug builds.
956956
o['variables']['v8_random_seed'] = 0 # Use a random seed for hash tables.
957+
o['variables']['v8_promise_internal_field_count'] = 1 # Add internal field to promises for async hooks.
957958
o['variables']['v8_use_snapshot'] = 'false' if options.without_snapshot else 'true'
958959
o['variables']['node_use_v8_platform'] = b(not options.without_v8_platform)
959960
o['variables']['node_use_bundled_v8'] = b(not options.without_bundled_v8)

src/async-wrap.cc

+3-28
Original file line numberDiff line numberDiff line change
@@ -294,32 +294,12 @@ static void PromiseHook(PromiseHookType type, Local<Promise> promise,
294294
Local<Context> context = promise->CreationContext();
295295
Environment* env = Environment::GetCurrent(context);
296296
if (type == PromiseHookType::kInit) {
297-
// Unfortunately, promises don't have internal fields. Need a surrogate that
298-
// async wrap can wrap.
299-
Local<Object> obj =
300-
env->async_hooks_promise_object()->NewInstance(context).ToLocalChecked();
301-
PromiseWrap* wrap = new PromiseWrap(env, obj);
302-
v8::PropertyAttribute hidden =
303-
static_cast<v8::PropertyAttribute>(v8::ReadOnly
304-
| v8::DontDelete
305-
| v8::DontEnum);
306-
promise->DefineOwnProperty(context,
307-
env->promise_wrap(),
308-
v8::External::New(env->isolate(), wrap),
309-
hidden).FromJust();
310-
// The async tag will be destroyed at the same time as the promise as the
311-
// only reference to it is held by the promise. This allows the promise
312-
// wrap instance to be notified when the promise is destroyed.
313-
promise->DefineOwnProperty(context,
314-
env->promise_async_tag(),
315-
obj, hidden).FromJust();
297+
PromiseWrap* wrap = new PromiseWrap(env, promise);
298+
wrap->MakeWeak(wrap);
316299
} else if (type == PromiseHookType::kResolve) {
317300
// TODO(matthewloring): need to expose this through the async hooks api.
318301
}
319-
Local<v8::Value> external_wrap =
320-
promise->Get(context, env->promise_wrap()).ToLocalChecked();
321-
PromiseWrap* wrap =
322-
static_cast<PromiseWrap*>(external_wrap.As<v8::External>()->Value());
302+
PromiseWrap* wrap = Unwrap<PromiseWrap>(promise);
323303
CHECK_NE(wrap, nullptr);
324304
if (type == PromiseHookType::kBefore) {
325305
PreCallbackExecution(wrap, false);
@@ -415,11 +395,6 @@ void AsyncWrap::Initialize(Local<Object> target,
415395
env->SetMethod(target, "clearIdStack", ClearIdStack);
416396
env->SetMethod(target, "addIdToDestroyList", QueueDestroyId);
417397

418-
Local<v8::ObjectTemplate> promise_object_template =
419-
v8::ObjectTemplate::New(env->isolate());
420-
promise_object_template->SetInternalFieldCount(1);
421-
env->set_async_hooks_promise_object(promise_object_template);
422-
423398
v8::PropertyAttribute ReadOnlyDontDelete =
424399
static_cast<v8::PropertyAttribute>(v8::ReadOnly | v8::DontDelete);
425400

src/env.h

-3
Original file line numberDiff line numberDiff line change
@@ -195,8 +195,6 @@ namespace node {
195195
V(preference_string, "preference") \
196196
V(priority_string, "priority") \
197197
V(produce_cached_data_string, "produceCachedData") \
198-
V(promise_wrap, "_promise_async_wrap") \
199-
V(promise_async_tag, "_promise_async_wrap_tag") \
200198
V(raw_string, "raw") \
201199
V(read_host_object_string, "_readHostObject") \
202200
V(readable_string, "readable") \
@@ -258,7 +256,6 @@ namespace node {
258256
V(async_hooks_init_function, v8::Function) \
259257
V(async_hooks_before_function, v8::Function) \
260258
V(async_hooks_after_function, v8::Function) \
261-
V(async_hooks_promise_object, v8::ObjectTemplate) \
262259
V(binding_cache_object, v8::Object) \
263260
V(buffer_constructor_function, v8::Function) \
264261
V(buffer_prototype_object, v8::Object) \

0 commit comments

Comments
 (0)