|
4 | 4 |
|
5 | 5 | #if defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS |
6 | 6 |
|
| 7 | +#include <cassert> // For static_assert |
| 8 | +#include <cstddef> // For offsetof |
7 | 9 | #include "aliased_buffer.h" |
8 | 10 | #include "base_object.h" |
9 | 11 | #include "util.h" |
@@ -33,13 +35,13 @@ bool WithoutCodeCache(const SnapshotConfig& config); |
33 | 35 | // and pass it into the V8 callback as the payload of StartupData. |
34 | 36 | // The memory chunk looks like this: |
35 | 37 | // |
36 | | -// [ type ] - EmbedderObjectType (a uint8_t) |
37 | | -// [ length ] - a size_t |
| 38 | +// [ type ] - EmbedderObjectType (a uint64_t) |
| 39 | +// [ length ] - a uint64_t |
38 | 40 | // [ ... ] - custom bytes of size |length - header size| |
39 | 41 | struct InternalFieldInfoBase { |
40 | 42 | public: |
41 | 43 | EmbedderObjectType type; |
42 | | - size_t length; |
| 44 | + uint64_t length; |
43 | 45 |
|
44 | 46 | template <typename T> |
45 | 47 | static T* New(EmbedderObjectType type) { |
@@ -71,14 +73,35 @@ struct InternalFieldInfoBase { |
71 | 73 | InternalFieldInfoBase() = default; |
72 | 74 | }; |
73 | 75 |
|
| 76 | +// Make sure that there's no padding in the struct since we will memcpy |
| 77 | +// them into the snapshot blob and they need to be reproducible. |
| 78 | +static_assert(offsetof(InternalFieldInfoBase, type) == 0, |
| 79 | + "InternalFieldInfoBase::type should start from offset 0"); |
| 80 | +static_assert(offsetof(InternalFieldInfoBase, length) == |
| 81 | + sizeof(EmbedderObjectType), |
| 82 | + "InternalFieldInfoBase::type should have no padding"); |
| 83 | + |
74 | 84 | struct EmbedderTypeInfo { |
75 | | - enum class MemoryMode : uint8_t { kBaseObject, kCppGC }; |
| 85 | + // To avoid padding, the enum is uint64_t. |
| 86 | + enum class MemoryMode : uint64_t { kBaseObject = 0, kCppGC }; |
76 | 87 | EmbedderTypeInfo(EmbedderObjectType t, MemoryMode m) : type(t), mode(m) {} |
77 | 88 | EmbedderTypeInfo() = default; |
| 89 | + |
78 | 90 | EmbedderObjectType type; |
79 | 91 | MemoryMode mode; |
80 | 92 | }; |
81 | 93 |
|
| 94 | +// Make sure that there's no padding in the struct since we will memcpy |
| 95 | +// them into the snapshot blob and they need to be reproducible. |
| 96 | +static_assert(offsetof(EmbedderTypeInfo, type) == 0, |
| 97 | + "EmbedderTypeInfo::type should start from offset 0"); |
| 98 | +static_assert(offsetof(EmbedderTypeInfo, mode) == sizeof(EmbedderObjectType), |
| 99 | + "EmbedderTypeInfo::type should have no padding"); |
| 100 | +static_assert(sizeof(EmbedderTypeInfo) == |
| 101 | + sizeof(EmbedderObjectType) + |
| 102 | + sizeof(EmbedderTypeInfo::MemoryMode), |
| 103 | + "EmbedderTypeInfo::mode should have no padding"); |
| 104 | + |
82 | 105 | // An interface for snapshotable native objects to inherit from. |
83 | 106 | // Use the SERIALIZABLE_OBJECT_METHODS() macro in the class to define |
84 | 107 | // the following methods to implement: |
@@ -150,6 +173,12 @@ class BindingData : public SnapshotableObject { |
150 | 173 | AliasedBufferIndex is_building_snapshot_buffer; |
151 | 174 | }; |
152 | 175 |
|
| 176 | + // Make sure that there's no padding in the struct since we will memcpy |
| 177 | + // them into the snapshot blob and they need to be reproducible. |
| 178 | + static_assert(sizeof(InternalFieldInfo) == |
| 179 | + sizeof(InternalFieldInfoBase) + sizeof(AliasedBufferIndex), |
| 180 | + "InternalFieldInfo should have no padding"); |
| 181 | + |
153 | 182 | BindingData(Realm* realm, |
154 | 183 | v8::Local<v8::Object> obj, |
155 | 184 | InternalFieldInfo* info = nullptr); |
|
0 commit comments