Skip to content

Commit 8a46ff7

Browse files
committed
fixup! src: use an array for faster binding data lookup
1 parent c841b77 commit 8a46ff7

File tree

14 files changed

+97
-47
lines changed

14 files changed

+97
-47
lines changed

node.gyp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -569,6 +569,7 @@
569569
'src/async_wrap-inl.h',
570570
'src/base_object.h',
571571
'src/base_object-inl.h',
572+
'src/base_object_types.h',
572573
'src/base64.h',
573574
'src/base64-inl.h',
574575
'src/callback_queue.h',

src/README.md

Lines changed: 16 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -486,28 +486,32 @@ that state is through the use of `Environment::AddBindingData`, which gives
486486
binding functions access to an object for storing such state.
487487
That object is always a [`BaseObject`][].
488488

489-
If the binding should be supported in a snapshot, it needs to be in the
490-
`SERIALIZABLE_OBJECT_TYPES` list in `node_snapshotable.h` and implement the
491-
serialization and deserialization methods. See the comments of
492-
`SnapshotableObject` on how to implement them. Otherwise, the `type_int` field
493-
needs to be added to the `UNSERIALIZABLE_OBJECT_TYPES` list.
489+
In the binding, call `SET_BINDING_ID()` with an identifier for the binding
490+
type. For example, for `http_parser::BindingData`, the identifier can be
491+
`http_parser_binding_data`.
492+
493+
If the binding should be supported in a snapshot, the id and the
494+
fully-specified class name should be added to the `SERIALIZABLE_BINDING_TYPES`
495+
list in `base_object_types.h`, and the class should implement the serialization
496+
and deserialization methods. See the comments of `SnapshotableObject` on how to
497+
implement them. Otherwise, add the id and the class name to the
498+
`UNSERIALIZABLE_BINDING_TYPES` list instead.
494499

495500
```cpp
496-
// In node_snapshotable.h, add the binding to either UNSERIALIZABLE_OBJECT_TYPES
497-
// or SERIALIZABLE_OBJECT_TYPES. The second parameter is a descriptive name
498-
// of the class, which is usually the class name with the (actual or conceptual)
499-
// namespace.
501+
// In base_object_types.h, add the binding to either
502+
// UNSERIALIZABLE_BINDING_TYPES or SERIALIZABLE_BINDING_TYPES.
503+
// The second parameter is a descriptive name of the class, which is
504+
// usually the fully-specified class name.
500505

501-
#define UNSERIALIZABLE_OBJECT_TYPES(V) \
506+
#define UNSERIALIZABLE_BINDING_TYPES(V) \
502507
V(http_parser_binding_data, http_parser::BindingData)
503508

504509
// In the HTTP parser source code file:
505510
class BindingData : public BaseObject {
506511
public:
507512
BindingData(Environment* env, Local<Object> obj) : BaseObject(env, obj) {}
508513

509-
static constexpr EmbedderObjectType type_int =
510-
EmbedderObjectType::k_http_parser_binding_data;
514+
SET_BINDING_ID(http_parser_binding_data)
511515

512516
std::vector<char> parser_buffer;
513517
bool parser_buffer_in_use = false;

src/base_object.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
#if defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS
2626

2727
#include <type_traits> // std::remove_reference
28+
#include "base_object_types.h"
2829
#include "memory_tracker.h"
2930
#include "v8.h"
3031

src/base_object_types.h

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
#ifndef SRC_BASE_OBJECT_TYPES_H_
2+
#define SRC_BASE_OBJECT_TYPES_H_
3+
4+
#include <cinttypes>
5+
6+
#if defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS
7+
8+
namespace node {
9+
// List of internalBinding() data wrappers. The first argument should match
10+
// what the class passes to SET_BINDING_ID(), the second argument should match
11+
// the C++ class name.
12+
#define SERIALIZABLE_BINDING_TYPES(V) \
13+
V(fs_binding_data, fs::BindingData) \
14+
V(v8_binding_data, v8_utils::BindingData) \
15+
V(blob_binding_data, BlobBindingData) \
16+
V(process_binding_data, process::BindingData)
17+
18+
#define UNSERIALIZABLE_BINDING_TYPES(V) \
19+
V(http2_binding_data, http2::BindingData) \
20+
V(http_parser_binding_data, http_parser::BindingData)
21+
22+
// List of (non-binding) BaseObjects that are serializable in the snapshot.
23+
// The first argument should match what the type passes to
24+
// SET_OBJECT_ID(), the second argument should match the C++ class
25+
// name.
26+
#define SERIALIZABLE_NON_BINDING_TYPES(V) \
27+
V(util_weak_reference, util::WeakReference)
28+
29+
// Helper list of all binding data wrapper types.
30+
#define BINDING_TYPES(V) \
31+
SERIALIZABLE_BINDING_TYPES(V) \
32+
UNSERIALIZABLE_BINDING_TYPES(V)
33+
34+
// Helper list of all BaseObjects that implement snapshot support.
35+
#define SERIALIZABLE_OBJECT_TYPES(V) \
36+
SERIALIZABLE_BINDING_TYPES(V) \
37+
SERIALIZABLE_NON_BINDING_TYPES(V)
38+
39+
#define V(TypeId, NativeType) k_##TypeId,
40+
enum class BindingDataType : uint8_t { BINDING_TYPES(V) kBindingDataTypeCount };
41+
// Make sure that we put the bindings first so that we can also use the enums
42+
// for the bindings as index to the binding data store.
43+
enum class EmbedderObjectType : uint8_t {
44+
BINDING_TYPES(V) SERIALIZABLE_NON_BINDING_TYPES(V)
45+
// We do not need to know about all the unserializable non-binding types for
46+
// now so we do not list them.
47+
kEmbedderObjectTypeCount
48+
};
49+
#undef V
50+
51+
// For now, BaseObjects only need to call this when they implement snapshot
52+
// support.
53+
#define SET_OBJECT_ID(TypeId) \
54+
static constexpr EmbedderObjectType type_int = EmbedderObjectType::k_##TypeId;
55+
56+
// Binding data should call this so that they can be looked up from the binding
57+
// data store.
58+
#define SET_BINDING_ID(TypeId) \
59+
static constexpr BindingDataType binding_type_int = \
60+
BindingDataType::k_##TypeId; \
61+
SET_OBJECT_ID(TypeId) \
62+
static_assert(static_cast<uint8_t>(type_int) == \
63+
static_cast<uint8_t>(binding_type_int));
64+
65+
} // namespace node
66+
67+
#endif // defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS
68+
69+
#endif // SRC_BASE_OBJECT_TYPES_H_

src/env-inl.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -218,7 +218,7 @@ inline T* Environment::GetBindingData(v8::Local<v8::Context> context) {
218218
context->GetAlignedPointerFromEmbedderData(
219219
ContextEmbedderIndex::kBindingListIndex));
220220
DCHECK_NOT_NULL(map);
221-
constexpr size_t binding_index = static_cast<size_t>(T::type_int);
221+
constexpr size_t binding_index = static_cast<size_t>(T::binding_type_int);
222222
static_assert(binding_index < std::tuple_size_v<BindingDataStore>);
223223
auto ptr = (*map)[binding_index];
224224
if (UNLIKELY(!ptr)) return nullptr;
@@ -239,7 +239,7 @@ inline T* Environment::AddBindingData(
239239
context->GetAlignedPointerFromEmbedderData(
240240
ContextEmbedderIndex::kBindingListIndex));
241241
DCHECK_NOT_NULL(map);
242-
constexpr size_t binding_index = static_cast<size_t>(T::type_int);
242+
constexpr size_t binding_index = static_cast<size_t>(T::binding_type_int);
243243
static_assert(binding_index < std::tuple_size_v<BindingDataStore>);
244244
CHECK(!(*map)[binding_index]); // Should not insert the binding twice.
245245
(*map)[binding_index] = item;

src/env.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -603,7 +603,7 @@ class Environment : public MemoryRetainer {
603603

604604
typedef std::array<BaseObjectPtr<BaseObject>,
605605
static_cast<size_t>(
606-
EmbedderObjectType::kEmbedderObjectTypeCount)>
606+
BindingDataType::kBindingDataTypeCount)>
607607
BindingDataStore;
608608

609609
// Create an Environment without initializing a main Context. Use

src/node_blob.h

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -147,8 +147,7 @@ class BlobBindingData : public SnapshotableObject {
147147

148148
SERIALIZABLE_OBJECT_METHODS()
149149

150-
static constexpr EmbedderObjectType type_int =
151-
EmbedderObjectType::k_blob_binding_data;
150+
SET_BINDING_ID(blob_binding_data)
152151

153152
void MemoryInfo(MemoryTracker* tracker) const override;
154153
SET_SELF_SIZE(BlobBindingData)

src/node_file.h

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -69,8 +69,7 @@ class BindingData : public SnapshotableObject {
6969

7070
using InternalFieldInfo = InternalFieldInfoBase;
7171
SERIALIZABLE_OBJECT_METHODS()
72-
static constexpr EmbedderObjectType type_int =
73-
EmbedderObjectType::k_fs_binding_data;
72+
SET_BINDING_ID(fs_binding_data)
7473

7574
void MemoryInfo(MemoryTracker* tracker) const override;
7675
SET_SELF_SIZE(BindingData)

src/node_http2_state.h

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -127,8 +127,7 @@ class Http2State : public BaseObject {
127127
SET_SELF_SIZE(Http2State)
128128
SET_MEMORY_INFO_NAME(Http2State)
129129

130-
static constexpr EmbedderObjectType type_int =
131-
EmbedderObjectType::k_http2_binding_data;
130+
SET_BINDING_ID(http2_binding_data)
132131

133132
private:
134133
struct http2_state_internal {

src/node_http_parser.cc

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -96,8 +96,7 @@ class BindingData : public BaseObject {
9696
BindingData(Environment* env, Local<Object> obj)
9797
: BaseObject(env, obj) {}
9898

99-
static constexpr EmbedderObjectType type_int =
100-
EmbedderObjectType::k_http_parser_binding_data;
99+
SET_BINDING_ID(http_parser_binding_data)
101100

102101
std::vector<char> parser_buffer;
103102
bool parser_buffer_in_use = false;

0 commit comments

Comments
 (0)