|
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