GeezerVison is showing github.com — src: use an array for faster binding data lookup · nodejs/node@629fc77
File treeExpand file treeCollapse file tree Open diff view settings Expand file treeCollapse file tree Open diff view settings Collapse file Copy file name to clipboardExpand all lines: node.gyp +1Lines changed: 1 addition & 0 deletions | Original file line number | Diff line number | Diff line change |
|---|
| 585 | 585 | 'src/async_wrap-inl.h', | 586 | 586 | 'src/base_object.h', | 587 | 587 | 'src/base_object-inl.h', | | 588 | + 'src/base_object_types.h', | 588 | 589 | 'src/base64.h', | 589 | 590 | 'src/base64-inl.h', | 590 | 591 | 'src/callback_queue.h', | |
Collapse file Copy file name to clipboardExpand all lines: src/README.md +19-11Lines changed: 19 additions & 11 deletions - Display the source diff
- Display the rich diff
| Original file line number | Diff line number | Diff line change |
|---|
@@ -528,18 +528,32 @@ that state is through the use of `Realm::AddBindingData`, which gives | 528 | 528 | binding functions access to an object for storing such state. | 529 | 529 | That object is always a [`BaseObject`][]. | 530 | 530 |
| 531 | | -Its class needs to have a static `type_name` field based on a | 532 | | -constant string, in order to disambiguate it from other classes of this type, | 533 | | -and which could e.g. match the binding's name (in the example above, that would | 534 | | -be `cares_wrap`). | | 531 | +In the binding, call `SET_BINDING_ID()` with an identifier for the binding | | 532 | +type. For example, for `http_parser::BindingData`, the identifier can be | | 533 | +`http_parser_binding_data`. | | 534 | + | | 535 | +If the binding should be supported in a snapshot, the id and the | | 536 | +fully-specified class name should be added to the `SERIALIZABLE_BINDING_TYPES` | | 537 | +list in `base_object_types.h`, and the class should implement the serialization | | 538 | +and deserialization methods. See the comments of `SnapshotableObject` on how to | | 539 | +implement them. Otherwise, add the id and the class name to the | | 540 | +`UNSERIALIZABLE_BINDING_TYPES` list instead. | 535 | 541 |
| 536 | 542 | ```cpp | | 543 | +// In base_object_types.h, add the binding to either | | 544 | +// UNSERIALIZABLE_BINDING_TYPES or SERIALIZABLE_BINDING_TYPES. | | 545 | +// The second parameter is a descriptive name of the class, which is | | 546 | +// usually the fully-specified class name. | | 547 | + | | 548 | +#define UNSERIALIZABLE_BINDING_TYPES(V) \ | | 549 | + V(http_parser_binding_data, http_parser::BindingData) | | 550 | + | 537 | 551 | // In the HTTP parser source code file: | 538 | 552 | class BindingData : public BaseObject { | 539 | 553 | public: | 540 | 554 | BindingData(Realm* realm, Local<Object> obj) : BaseObject(realm, obj) {} | 541 | 555 |
| 542 | | - static constexpr FastStringKey type_name { "http_parser" }; | | 556 | + SET_BINDING_ID(http_parser_binding_data) | 543 | 557 |
| 544 | 558 | std::vector<char> parser_buffer; | 545 | 559 | bool parser_buffer_in_use = false; | @@ -569,12 +583,6 @@ void InitializeHttpParser(Local<Object> target, | 569 | 583 | } | 570 | 584 | ``` | 571 | 585 |
| 572 | | -If the binding is loaded during bootstrap, add it to the | 573 | | -`SERIALIZABLE_OBJECT_TYPES` list in `src/node_snapshotable.h` and | 574 | | -inherit from the `SnapshotableObject` class instead. See the comments | 575 | | -of `SnapshotableObject` on how to implement its serialization and | 576 | | -deserialization. | 577 | | -
| 578 | 586 | <a id="exception-handling"></a> | 579 | 587 |
| 580 | 588 | ### Exception handling | |
Collapse file Copy file name to clipboardExpand all lines: src/base_object.h +1Lines changed: 1 addition & 0 deletions | Original file line number | Diff line number | Diff line change |
|---|
| 25 | 25 | #if defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS | 26 | 26 |
| 27 | 27 | #include <type_traits> // std::remove_reference | | 28 | +#include "base_object_types.h" | 28 | 29 | #include "memory_tracker.h" | 29 | 30 | #include "v8.h" | 30 | 31 |
| |
Collapse file Copy file name to clipboardExpand all lines: src/base_object_types.h -2Lines changed: 0 additions & 2 deletions | Original file line number | Diff line number | Diff line change |
|---|
@@ -10,12 +10,10 @@ namespace node { | 10 | 10 | // what the class passes to SET_BINDING_ID(), the second argument should match | 11 | 11 | // the C++ class name. | 12 | 12 | #define SERIALIZABLE_BINDING_TYPES(V) \ | 13 | | - V(encoding_binding_data, encoding_binding::BindingData) \ | 14 | 13 | V(fs_binding_data, fs::BindingData) \ | 15 | 14 | V(v8_binding_data, v8_utils::BindingData) \ | 16 | 15 | V(blob_binding_data, BlobBindingData) \ | 17 | 16 | V(process_binding_data, process::BindingData) \ | 18 | | - V(timers_binding_data, timers::BindingData) \ | 19 | 17 | V(url_binding_data, url::BindingData) | 20 | 18 |
| 21 | 19 | #define UNSERIALIZABLE_BINDING_TYPES(V) \ | |
Collapse file Copy file name to clipboardExpand all lines: src/node_blob.h +1-3Lines changed: 1 addition & 3 deletions | Original file line number | Diff line number | Diff line change |
|---|
@@ -147,9 +147,7 @@ class BlobBindingData : public SnapshotableObject { | 147 | 147 |
| 148 | 148 | SERIALIZABLE_OBJECT_METHODS() | 149 | 149 |
| 150 | | - static constexpr FastStringKey type_name{"node::BlobBindingData"}; | 151 | | - static constexpr EmbedderObjectType type_int = | 152 | | - EmbedderObjectType::k_blob_binding_data; | | 150 | + SET_BINDING_ID(blob_binding_data) | 153 | 151 |
| 154 | 152 | void MemoryInfo(MemoryTracker* tracker) const override; | 155 | 153 | SET_SELF_SIZE(BlobBindingData) | |
Collapse file Copy file name to clipboardExpand all lines: src/node_file.h +1-3Lines changed: 1 addition & 3 deletions | Original file line number | Diff line number | Diff line change |
|---|
@@ -69,9 +69,7 @@ class BindingData : public SnapshotableObject { | 69 | 69 |
| 70 | 70 | using InternalFieldInfo = InternalFieldInfoBase; | 71 | 71 | SERIALIZABLE_OBJECT_METHODS() | 72 | | - static constexpr FastStringKey type_name{"node::fs::BindingData"}; | 73 | | - static constexpr EmbedderObjectType type_int = | 74 | | - EmbedderObjectType::k_fs_binding_data; | | 72 | + SET_BINDING_ID(fs_binding_data) | 75 | 73 |
| 76 | 74 | void MemoryInfo(MemoryTracker* tracker) const override; | 77 | 75 | SET_SELF_SIZE(BindingData) | |
Collapse file Copy file name to clipboardExpand all lines: src/node_http2_state.h +1-1Lines changed: 1 addition & 1 deletion | Original file line number | Diff line number | Diff line change |
|---|
@@ -125,7 +125,7 @@ class Http2State : public BaseObject { | 125 | 125 | SET_SELF_SIZE(Http2State) | 126 | 126 | SET_MEMORY_INFO_NAME(Http2State) | 127 | 127 |
| 128 | | - static constexpr FastStringKey type_name { "http2" }; | | 128 | + SET_BINDING_ID(http2_binding_data) | 129 | 129 |
| 130 | 130 | private: | 131 | 131 | struct http2_state_internal { | |
Collapse file Copy file name to clipboardExpand all lines: src/node_http_parser.cc +1-1Lines changed: 1 addition & 1 deletion | Original file line number | Diff line number | Diff line change |
|---|
@@ -95,7 +95,7 @@ class BindingData : public BaseObject { | 95 | 95 | public: | 96 | 96 | BindingData(Realm* realm, Local<Object> obj) : BaseObject(realm, obj) {} | 97 | 97 |
| 98 | | - static constexpr FastStringKey type_name { "http_parser" }; | | 98 | + SET_BINDING_ID(http_parser_binding_data) | 99 | 99 |
| 100 | 100 | std::vector<char> parser_buffer; | 101 | 101 | bool parser_buffer_in_use = false; | |
Collapse file Copy file name to clipboardExpand all lines: src/node_process.h +1-3Lines changed: 1 addition & 3 deletions | Original file line number | Diff line number | Diff line change |
|---|
@@ -54,9 +54,7 @@ class BindingData : public SnapshotableObject { | 54 | 54 | using InternalFieldInfo = InternalFieldInfoBase; | 55 | 55 |
| 56 | 56 | SERIALIZABLE_OBJECT_METHODS() | 57 | | - static constexpr FastStringKey type_name{"node::process::BindingData"}; | 58 | | - static constexpr EmbedderObjectType type_int = | 59 | | - EmbedderObjectType::k_process_binding_data; | | 57 | + SET_BINDING_ID(process_binding_data) | 60 | 58 |
| 61 | 59 | BindingData(Realm* realm, v8::Local<v8::Object> object); | 62 | 60 |
| |
Collapse file Copy file name to clipboardExpand all lines: src/node_realm-inl.h +9-5Lines changed: 9 additions & 5 deletions | Original file line number | Diff line number | Diff line change |
|---|
@@ -62,9 +62,11 @@ inline T* Realm::GetBindingData(v8::Local<v8::Context> context) { | 62 | 62 | static_cast<BindingDataStore*>(context->GetAlignedPointerFromEmbedderData( | 63 | 63 | ContextEmbedderIndex::kBindingDataStoreIndex)); | 64 | 64 | DCHECK_NOT_NULL(map); | 65 | | - auto it = map->find(T::type_name); | 66 | | - if (UNLIKELY(it == map->end())) return nullptr; | 67 | | - T* result = static_cast<T*>(it->second.get()); | | 65 | + constexpr size_t binding_index = static_cast<size_t>(T::binding_type_int); | | 66 | + static_assert(binding_index < std::tuple_size_v<BindingDataStore>); | | 67 | + auto ptr = (*map)[binding_index]; | | 68 | + if (UNLIKELY(!ptr)) return nullptr; | | 69 | + T* result = static_cast<T*>(ptr.get()); | 68 | 70 | DCHECK_NOT_NULL(result); | 69 | 71 | DCHECK_EQ(result->realm(), GetCurrent(context)); | 70 | 72 | return result; | @@ -80,8 +82,10 @@ inline T* Realm::AddBindingData(v8::Local<v8::Context> context, | 80 | 82 | static_cast<BindingDataStore*>(context->GetAlignedPointerFromEmbedderData( | 81 | 83 | ContextEmbedderIndex::kBindingDataStoreIndex)); | 82 | 84 | DCHECK_NOT_NULL(map); | 83 | | - auto result = map->emplace(T::type_name, item); | 84 | | - CHECK(result.second); | | 85 | + constexpr size_t binding_index = static_cast<size_t>(T::binding_type_int); | | 86 | + static_assert(binding_index < std::tuple_size_v<BindingDataStore>); | | 87 | + CHECK(!(*map)[binding_index]); // Should not insert the binding twice. | | 88 | + (*map)[binding_index] = item; | 85 | 89 | DCHECK_EQ(GetBindingData<T>(context), item.get()); | 86 | 90 | return item.get(); | 87 | 91 | } | |
|