Mercurial > hg > sv-dependency-builds
comparison osx/include/capnp/layout.h @ 147:45360b968bf4
Cap'n Proto v0.6 + build for OSX
author | Chris Cannam <cannam@all-day-breakfast.com> |
---|---|
date | Mon, 22 May 2017 10:01:37 +0100 |
parents | 41e769c91eca |
children |
comparison
equal
deleted
inserted
replaced
146:206f0eb279b8 | 147:45360b968bf4 |
---|---|
80 class Arena; | 80 class Arena; |
81 class BuilderArena; | 81 class BuilderArena; |
82 | 82 |
83 // ============================================================================= | 83 // ============================================================================= |
84 | 84 |
85 typedef decltype(BITS / ELEMENTS) BitsPerElement; | 85 #if CAPNP_DEBUG_TYPES |
86 typedef decltype(POINTERS / ELEMENTS) PointersPerElement; | 86 typedef kj::UnitRatio<kj::Bounded<64, uint>, BitLabel, ElementLabel> BitsPerElementTableType; |
87 | 87 #else |
88 static constexpr BitsPerElement BITS_PER_ELEMENT_TABLE[8] = { | 88 typedef uint BitsPerElementTableType; |
89 0 * BITS / ELEMENTS, | 89 #endif |
90 1 * BITS / ELEMENTS, | 90 |
91 8 * BITS / ELEMENTS, | 91 static constexpr BitsPerElementTableType BITS_PER_ELEMENT_TABLE[8] = { |
92 16 * BITS / ELEMENTS, | 92 bounded< 0>() * BITS / ELEMENTS, |
93 32 * BITS / ELEMENTS, | 93 bounded< 1>() * BITS / ELEMENTS, |
94 64 * BITS / ELEMENTS, | 94 bounded< 8>() * BITS / ELEMENTS, |
95 0 * BITS / ELEMENTS, | 95 bounded<16>() * BITS / ELEMENTS, |
96 0 * BITS / ELEMENTS | 96 bounded<32>() * BITS / ELEMENTS, |
97 }; | 97 bounded<64>() * BITS / ELEMENTS, |
98 | 98 bounded< 0>() * BITS / ELEMENTS, |
99 inline KJ_CONSTEXPR() BitsPerElement dataBitsPerElement(ElementSize size) { | 99 bounded< 0>() * BITS / ELEMENTS |
100 }; | |
101 | |
102 inline KJ_CONSTEXPR() BitsPerElementTableType dataBitsPerElement(ElementSize size) { | |
100 return _::BITS_PER_ELEMENT_TABLE[static_cast<int>(size)]; | 103 return _::BITS_PER_ELEMENT_TABLE[static_cast<int>(size)]; |
101 } | 104 } |
102 | 105 |
103 inline constexpr PointersPerElement pointersPerElement(ElementSize size) { | 106 inline constexpr PointersPerElementN<1> pointersPerElement(ElementSize size) { |
104 return size == ElementSize::POINTER ? 1 * POINTERS / ELEMENTS : 0 * POINTERS / ELEMENTS; | 107 return size == ElementSize::POINTER |
108 ? PointersPerElementN<1>(ONE * POINTERS / ELEMENTS) | |
109 : PointersPerElementN<1>(ZERO * POINTERS / ELEMENTS); | |
110 } | |
111 | |
112 static constexpr BitsPerElementTableType BITS_PER_ELEMENT_INCLUDING_PONITERS_TABLE[8] = { | |
113 bounded< 0>() * BITS / ELEMENTS, | |
114 bounded< 1>() * BITS / ELEMENTS, | |
115 bounded< 8>() * BITS / ELEMENTS, | |
116 bounded<16>() * BITS / ELEMENTS, | |
117 bounded<32>() * BITS / ELEMENTS, | |
118 bounded<64>() * BITS / ELEMENTS, | |
119 bounded<64>() * BITS / ELEMENTS, | |
120 bounded< 0>() * BITS / ELEMENTS | |
121 }; | |
122 | |
123 inline KJ_CONSTEXPR() BitsPerElementTableType bitsPerElementIncludingPointers(ElementSize size) { | |
124 return _::BITS_PER_ELEMENT_INCLUDING_PONITERS_TABLE[static_cast<int>(size)]; | |
105 } | 125 } |
106 | 126 |
107 template <size_t size> struct ElementSizeForByteSize; | 127 template <size_t size> struct ElementSizeForByteSize; |
108 template <> struct ElementSizeForByteSize<1> { static constexpr ElementSize value = ElementSize::BYTE; }; | 128 template <> struct ElementSizeForByteSize<1> { static constexpr ElementSize value = ElementSize::BYTE; }; |
109 template <> struct ElementSizeForByteSize<2> { static constexpr ElementSize value = ElementSize::TWO_BYTES; }; | 129 template <> struct ElementSizeForByteSize<2> { static constexpr ElementSize value = ElementSize::TWO_BYTES; }; |
124 // Void and bool are special. | 144 // Void and bool are special. |
125 template <> struct ElementSizeForType<Void> { static constexpr ElementSize value = ElementSize::VOID; }; | 145 template <> struct ElementSizeForType<Void> { static constexpr ElementSize value = ElementSize::VOID; }; |
126 template <> struct ElementSizeForType<bool> { static constexpr ElementSize value = ElementSize::BIT; }; | 146 template <> struct ElementSizeForType<bool> { static constexpr ElementSize value = ElementSize::BIT; }; |
127 | 147 |
128 // Lists and blobs are pointers, not structs. | 148 // Lists and blobs are pointers, not structs. |
129 template <typename T, bool b> struct ElementSizeForType<List<T, b>> { | 149 template <typename T, Kind K> struct ElementSizeForType<List<T, K>> { |
130 static constexpr ElementSize value = ElementSize::POINTER; | 150 static constexpr ElementSize value = ElementSize::POINTER; |
131 }; | 151 }; |
132 template <> struct ElementSizeForType<Text> { | 152 template <> struct ElementSizeForType<Text> { |
133 static constexpr ElementSize value = ElementSize::POINTER; | 153 static constexpr ElementSize value = ElementSize::POINTER; |
134 }; | 154 }; |
140 inline constexpr ElementSize elementSizeForType() { | 160 inline constexpr ElementSize elementSizeForType() { |
141 return ElementSizeForType<T>::value; | 161 return ElementSizeForType<T>::value; |
142 } | 162 } |
143 | 163 |
144 struct MessageSizeCounts { | 164 struct MessageSizeCounts { |
145 WordCount64 wordCount; | 165 WordCountN<61, uint64_t> wordCount; // 2^64 bytes |
146 uint capCount; | 166 uint capCount; |
147 | 167 |
148 MessageSizeCounts& operator+=(const MessageSizeCounts& other) { | 168 MessageSizeCounts& operator+=(const MessageSizeCounts& other) { |
149 wordCount += other.wordCount; | 169 // OK to truncate unchecked because this class is used to count actual stuff in memory, and |
170 // we couldn't possibly have anywhere near 2^61 words. | |
171 wordCount = assumeBits<61>(wordCount + other.wordCount); | |
150 capCount += other.capCount; | 172 capCount += other.capCount; |
151 return *this; | 173 return *this; |
152 } | 174 } |
153 | 175 |
176 void addWords(WordCountN<61, uint64_t> other) { | |
177 wordCount = assumeBits<61>(wordCount + other); | |
178 } | |
179 | |
154 MessageSize asPublic() { | 180 MessageSize asPublic() { |
155 return MessageSize { wordCount / WORDS, capCount }; | 181 return MessageSize { unbound(wordCount / WORDS), capCount }; |
156 } | 182 } |
157 }; | 183 }; |
158 | 184 |
159 // ============================================================================= | 185 // ============================================================================= |
160 | 186 |
166 uint8_t bytes[wordCount * sizeof(word)]; | 192 uint8_t bytes[wordCount * sizeof(word)]; |
167 word words[wordCount]; | 193 word words[wordCount]; |
168 }; | 194 }; |
169 | 195 |
170 struct StructSize { | 196 struct StructSize { |
171 WordCount16 data; | 197 StructDataWordCount data; |
172 WirePointerCount16 pointers; | 198 StructPointerCount pointers; |
173 | 199 |
174 inline constexpr WordCount total() const { return data + pointers * WORDS_PER_POINTER; } | 200 inline constexpr WordCountN<17> total() const { return data + pointers * WORDS_PER_POINTER; } |
175 | 201 |
176 StructSize() = default; | 202 StructSize() = default; |
177 inline constexpr StructSize(WordCount data, WirePointerCount pointers) | 203 inline constexpr StructSize(StructDataWordCount data, StructPointerCount pointers) |
178 : data(data), pointers(pointers) {} | 204 : data(data), pointers(pointers) {} |
179 }; | 205 }; |
180 | 206 |
181 template <typename T, typename CapnpPrivate = typename T::_capnpPrivate> | 207 template <typename T, typename CapnpPrivate = typename T::_capnpPrivate> |
182 inline constexpr StructSize structSize() { | 208 inline constexpr StructSize structSize() { |
183 return StructSize(CapnpPrivate::dataWordSize * WORDS, CapnpPrivate::pointerCount * POINTERS); | 209 return StructSize(bounded(CapnpPrivate::dataWordSize) * WORDS, |
210 bounded(CapnpPrivate::pointerCount) * POINTERS); | |
184 } | 211 } |
185 | 212 |
186 template <typename T, typename CapnpPrivate = typename T::_capnpPrivate, | 213 template <typename T, typename CapnpPrivate = typename T::_capnpPrivate, |
187 typename = kj::EnableIf<CAPNP_KIND(T) == Kind::STRUCT>> | 214 typename = kj::EnableIf<CAPNP_KIND(T) == Kind::STRUCT>> |
188 inline constexpr StructSize minStructSizeForElement() { | 215 inline constexpr StructSize minStructSizeForElement() { |
189 // If T is a struct, return its struct size. Otherwise return the minimum struct size big enough | 216 // If T is a struct, return its struct size. Otherwise return the minimum struct size big enough |
190 // to hold a T. | 217 // to hold a T. |
191 | 218 |
192 return StructSize(CapnpPrivate::dataWordSize * WORDS, CapnpPrivate::pointerCount * POINTERS); | 219 return StructSize(bounded(CapnpPrivate::dataWordSize) * WORDS, |
220 bounded(CapnpPrivate::pointerCount) * POINTERS); | |
193 } | 221 } |
194 | 222 |
195 template <typename T, typename = kj::EnableIf<CAPNP_KIND(T) != Kind::STRUCT>> | 223 template <typename T, typename = kj::EnableIf<CAPNP_KIND(T) != Kind::STRUCT>> |
196 inline constexpr StructSize minStructSizeForElement() { | 224 inline constexpr StructSize minStructSizeForElement() { |
197 // If T is a struct, return its struct size. Otherwise return the minimum struct size big enough | 225 // If T is a struct, return its struct size. Otherwise return the minimum struct size big enough |
198 // to hold a T. | 226 // to hold a T. |
199 | 227 |
200 return StructSize( | 228 return StructSize( |
201 dataBitsPerElement(elementSizeForType<T>()) * ELEMENTS > 0 * BITS ? 1 * WORDS : 0 * WORDS, | 229 dataBitsPerElement(elementSizeForType<T>()) * ELEMENTS > ZERO * BITS |
230 ? StructDataWordCount(ONE * WORDS) : StructDataWordCount(ZERO * WORDS), | |
202 pointersPerElement(elementSizeForType<T>()) * ELEMENTS); | 231 pointersPerElement(elementSizeForType<T>()) * ELEMENTS); |
203 } | 232 } |
204 | 233 |
205 // ------------------------------------------------------------------- | 234 // ------------------------------------------------------------------- |
206 // Masking of default values | 235 // Masking of default values |
316 SegmentBuilder* segment, CapTableBuilder* capTable, word* location); | 345 SegmentBuilder* segment, CapTableBuilder* capTable, word* location); |
317 // Get a PointerBuilder representing a message root located in the given segment at the given | 346 // Get a PointerBuilder representing a message root located in the given segment at the given |
318 // location. | 347 // location. |
319 | 348 |
320 inline bool isNull() { return getPointerType() == PointerType::NULL_; } | 349 inline bool isNull() { return getPointerType() == PointerType::NULL_; } |
321 PointerType getPointerType(); | 350 PointerType getPointerType() const; |
322 | 351 |
323 StructBuilder getStruct(StructSize size, const word* defaultValue); | 352 StructBuilder getStruct(StructSize size, const word* defaultValue); |
324 ListBuilder getList(ElementSize elementSize, const word* defaultValue); | 353 ListBuilder getList(ElementSize elementSize, const word* defaultValue); |
325 ListBuilder getStructList(StructSize elementSize, const word* defaultValue); | 354 ListBuilder getStructList(StructSize elementSize, const word* defaultValue); |
326 ListBuilder getListAnySize(const word* defaultValue); | 355 ListBuilder getListAnySize(const word* defaultValue); |
327 template <typename T> typename T::Builder getBlob(const void* defaultValue,ByteCount defaultSize); | 356 template <typename T> typename T::Builder getBlob( |
357 const void* defaultValue, ByteCount defaultSize); | |
328 #if !CAPNP_LITE | 358 #if !CAPNP_LITE |
329 kj::Own<ClientHook> getCapability(); | 359 kj::Own<ClientHook> getCapability(); |
330 #endif // !CAPNP_LITE | 360 #endif // !CAPNP_LITE |
331 // Get methods: Get the value. If it is null, initialize it to a copy of the default value. | 361 // Get methods: Get the value. If it is null, initialize it to a copy of the default value. |
332 // The default value is encoded as an "unchecked message" for structs, lists, and objects, or a | 362 // The default value is encoded as an "unchecked message" for structs, lists, and objects, or a |
472 | 502 |
473 inline word* getLocation() { return reinterpret_cast<word*>(data); } | 503 inline word* getLocation() { return reinterpret_cast<word*>(data); } |
474 // Get the object's location. Only valid for independently-allocated objects (i.e. not list | 504 // Get the object's location. Only valid for independently-allocated objects (i.e. not list |
475 // elements). | 505 // elements). |
476 | 506 |
477 inline BitCount getDataSectionSize() const { return dataSize; } | 507 inline StructDataBitCount getDataSectionSize() const { return dataSize; } |
478 inline WirePointerCount getPointerSectionSize() const { return pointerCount; } | 508 inline StructPointerCount getPointerSectionSize() const { return pointerCount; } |
479 inline kj::ArrayPtr<byte> getDataSectionAsBlob(); | 509 inline kj::ArrayPtr<byte> getDataSectionAsBlob(); |
480 inline _::ListBuilder getPointerSectionAsList(); | 510 inline _::ListBuilder getPointerSectionAsList(); |
481 | 511 |
482 template <typename T> | 512 template <typename T> |
483 KJ_ALWAYS_INLINE(bool hasDataField(ElementCount offset)); | 513 KJ_ALWAYS_INLINE(bool hasDataField(StructDataOffset offset)); |
484 // Return true if the field is set to something other than its default value. | 514 // Return true if the field is set to something other than its default value. |
485 | 515 |
486 template <typename T> | 516 template <typename T> |
487 KJ_ALWAYS_INLINE(T getDataField(ElementCount offset)); | 517 KJ_ALWAYS_INLINE(T getDataField(StructDataOffset offset)); |
488 // Gets the data field value of the given type at the given offset. The offset is measured in | 518 // Gets the data field value of the given type at the given offset. The offset is measured in |
489 // multiples of the field size, determined by the type. | 519 // multiples of the field size, determined by the type. |
490 | 520 |
491 template <typename T> | 521 template <typename T> |
492 KJ_ALWAYS_INLINE(T getDataField(ElementCount offset, Mask<T> mask)); | 522 KJ_ALWAYS_INLINE(T getDataField(StructDataOffset offset, Mask<T> mask)); |
493 // Like getDataField() but applies the given XOR mask to the data on load. Used for reading | 523 // Like getDataField() but applies the given XOR mask to the data on load. Used for reading |
494 // fields with non-zero default values. | 524 // fields with non-zero default values. |
495 | 525 |
496 template <typename T> | 526 template <typename T> |
497 KJ_ALWAYS_INLINE(void setDataField( | 527 KJ_ALWAYS_INLINE(void setDataField(StructDataOffset offset, kj::NoInfer<T> value)); |
498 ElementCount offset, kj::NoInfer<T> value)); | |
499 // Sets the data field value at the given offset. | 528 // Sets the data field value at the given offset. |
500 | 529 |
501 template <typename T> | 530 template <typename T> |
502 KJ_ALWAYS_INLINE(void setDataField( | 531 KJ_ALWAYS_INLINE(void setDataField(StructDataOffset offset, |
503 ElementCount offset, kj::NoInfer<T> value, Mask<T> mask)); | 532 kj::NoInfer<T> value, Mask<T> mask)); |
504 // Like setDataField() but applies the given XOR mask before storing. Used for writing fields | 533 // Like setDataField() but applies the given XOR mask before storing. Used for writing fields |
505 // with non-zero default values. | 534 // with non-zero default values. |
506 | 535 |
507 KJ_ALWAYS_INLINE(PointerBuilder getPointerField(WirePointerCount ptrIndex)); | 536 KJ_ALWAYS_INLINE(PointerBuilder getPointerField(StructPointerOffset ptrIndex)); |
508 // Get a builder for a pointer field given the index within the pointer section. | 537 // Get a builder for a pointer field given the index within the pointer section. |
509 | 538 |
510 void clearAll(); | 539 void clearAll(); |
511 // Clear all pointers and data. | 540 // Clear all pointers and data. |
512 | 541 |
536 SegmentBuilder* segment; // Memory segment in which the struct resides. | 565 SegmentBuilder* segment; // Memory segment in which the struct resides. |
537 CapTableBuilder* capTable; // Table of capability indexes. | 566 CapTableBuilder* capTable; // Table of capability indexes. |
538 void* data; // Pointer to the encoded data. | 567 void* data; // Pointer to the encoded data. |
539 WirePointer* pointers; // Pointer to the encoded pointers. | 568 WirePointer* pointers; // Pointer to the encoded pointers. |
540 | 569 |
541 BitCount32 dataSize; | 570 StructDataBitCount dataSize; |
542 // Size of data section. We use a bit count rather than a word count to more easily handle the | 571 // Size of data section. We use a bit count rather than a word count to more easily handle the |
543 // case of struct lists encoded with less than a word per element. | 572 // case of struct lists encoded with less than a word per element. |
544 | 573 |
545 WirePointerCount16 pointerCount; // Size of the pointer section. | 574 StructPointerCount pointerCount; // Size of the pointer section. |
546 | 575 |
547 inline StructBuilder(SegmentBuilder* segment, CapTableBuilder* capTable, | 576 inline StructBuilder(SegmentBuilder* segment, CapTableBuilder* capTable, |
548 void* data, WirePointer* pointers, | 577 void* data, WirePointer* pointers, |
549 BitCount dataSize, WirePointerCount pointerCount) | 578 StructDataBitCount dataSize, StructPointerCount pointerCount) |
550 : segment(segment), capTable(capTable), data(data), pointers(pointers), | 579 : segment(segment), capTable(capTable), data(data), pointers(pointers), |
551 dataSize(dataSize), pointerCount(pointerCount) {} | 580 dataSize(dataSize), pointerCount(pointerCount) {} |
552 | 581 |
553 friend class ListBuilder; | 582 friend class ListBuilder; |
554 friend struct WireHelpers; | 583 friend struct WireHelpers; |
556 }; | 585 }; |
557 | 586 |
558 class StructReader { | 587 class StructReader { |
559 public: | 588 public: |
560 inline StructReader() | 589 inline StructReader() |
561 : segment(nullptr), capTable(nullptr), data(nullptr), pointers(nullptr), dataSize(0), | 590 : segment(nullptr), capTable(nullptr), data(nullptr), pointers(nullptr), |
562 pointerCount(0), nestingLimit(0x7fffffff) {} | 591 dataSize(ZERO * BITS), pointerCount(ZERO * POINTERS), nestingLimit(0x7fffffff) {} |
563 inline StructReader(kj::ArrayPtr<const word> data) | 592 inline StructReader(kj::ArrayPtr<const word> data) |
564 : segment(nullptr), capTable(nullptr), data(data.begin()), pointers(nullptr), | 593 : segment(nullptr), capTable(nullptr), data(data.begin()), pointers(nullptr), |
565 dataSize(data.size() * WORDS * BITS_PER_WORD), pointerCount(0), nestingLimit(0x7fffffff) {} | 594 dataSize(assumeBits<STRUCT_DATA_WORD_COUNT_BITS>(data.size()) * WORDS * BITS_PER_WORD), |
595 pointerCount(ZERO * POINTERS), nestingLimit(0x7fffffff) {} | |
566 | 596 |
567 const void* getLocation() const { return data; } | 597 const void* getLocation() const { return data; } |
568 | 598 |
569 inline BitCount getDataSectionSize() const { return dataSize; } | 599 inline StructDataBitCount getDataSectionSize() const { return dataSize; } |
570 inline WirePointerCount getPointerSectionSize() const { return pointerCount; } | 600 inline StructPointerCount getPointerSectionSize() const { return pointerCount; } |
571 inline kj::ArrayPtr<const byte> getDataSectionAsBlob(); | 601 inline kj::ArrayPtr<const byte> getDataSectionAsBlob(); |
572 inline _::ListReader getPointerSectionAsList(); | 602 inline _::ListReader getPointerSectionAsList(); |
573 | 603 |
574 kj::Array<word> canonicalize(); | 604 kj::Array<word> canonicalize(); |
575 | 605 |
576 template <typename T> | 606 template <typename T> |
577 KJ_ALWAYS_INLINE(bool hasDataField(ElementCount offset) const); | 607 KJ_ALWAYS_INLINE(bool hasDataField(StructDataOffset offset) const); |
578 // Return true if the field is set to something other than its default value. | 608 // Return true if the field is set to something other than its default value. |
579 | 609 |
580 template <typename T> | 610 template <typename T> |
581 KJ_ALWAYS_INLINE(T getDataField(ElementCount offset) const); | 611 KJ_ALWAYS_INLINE(T getDataField(StructDataOffset offset) const); |
582 // Get the data field value of the given type at the given offset. The offset is measured in | 612 // Get the data field value of the given type at the given offset. The offset is measured in |
583 // multiples of the field size, determined by the type. Returns zero if the offset is past the | 613 // multiples of the field size, determined by the type. Returns zero if the offset is past the |
584 // end of the struct's data section. | 614 // end of the struct's data section. |
585 | 615 |
586 template <typename T> | 616 template <typename T> |
587 KJ_ALWAYS_INLINE( | 617 KJ_ALWAYS_INLINE(T getDataField(StructDataOffset offset, Mask<T> mask) const); |
588 T getDataField(ElementCount offset, Mask<T> mask) const); | |
589 // Like getDataField(offset), but applies the given XOR mask to the result. Used for reading | 618 // Like getDataField(offset), but applies the given XOR mask to the result. Used for reading |
590 // fields with non-zero default values. | 619 // fields with non-zero default values. |
591 | 620 |
592 KJ_ALWAYS_INLINE(PointerReader getPointerField(WirePointerCount ptrIndex) const); | 621 KJ_ALWAYS_INLINE(PointerReader getPointerField(StructPointerOffset ptrIndex) const); |
593 // Get a reader for a pointer field given the index within the pointer section. If the index | 622 // Get a reader for a pointer field given the index within the pointer section. If the index |
594 // is out-of-bounds, returns a null pointer. | 623 // is out-of-bounds, returns a null pointer. |
595 | 624 |
596 MessageSizeCounts totalSize() const; | 625 MessageSizeCounts totalSize() const; |
597 // Return the total size of the struct and everything to which it points. Does not count far | 626 // Return the total size of the struct and everything to which it points. Does not count far |
626 CapTableReader* capTable; // Table of capability indexes. | 655 CapTableReader* capTable; // Table of capability indexes. |
627 | 656 |
628 const void* data; | 657 const void* data; |
629 const WirePointer* pointers; | 658 const WirePointer* pointers; |
630 | 659 |
631 BitCount32 dataSize; | 660 StructDataBitCount dataSize; |
632 // Size of data section. We use a bit count rather than a word count to more easily handle the | 661 // Size of data section. We use a bit count rather than a word count to more easily handle the |
633 // case of struct lists encoded with less than a word per element. | 662 // case of struct lists encoded with less than a word per element. |
634 | 663 |
635 WirePointerCount16 pointerCount; // Size of the pointer section. | 664 StructPointerCount pointerCount; // Size of the pointer section. |
636 | 665 |
637 int nestingLimit; | 666 int nestingLimit; |
638 // Limits the depth of message structures to guard against stack-overflow-based DoS attacks. | 667 // Limits the depth of message structures to guard against stack-overflow-based DoS attacks. |
639 // Once this reaches zero, further pointers will be pruned. | 668 // Once this reaches zero, further pointers will be pruned. |
640 // TODO(perf): Limit to 16 bits for better packing? | 669 // TODO(perf): Limit to 16 bits for better packing? |
641 | 670 |
642 inline StructReader(SegmentReader* segment, CapTableReader* capTable, | 671 inline StructReader(SegmentReader* segment, CapTableReader* capTable, |
643 const void* data, const WirePointer* pointers, | 672 const void* data, const WirePointer* pointers, |
644 BitCount dataSize, WirePointerCount pointerCount, int nestingLimit) | 673 StructDataBitCount dataSize, StructPointerCount pointerCount, |
674 int nestingLimit) | |
645 : segment(segment), capTable(capTable), data(data), pointers(pointers), | 675 : segment(segment), capTable(capTable), data(data), pointers(pointers), |
646 dataSize(dataSize), pointerCount(pointerCount), | 676 dataSize(dataSize), pointerCount(pointerCount), |
647 nestingLimit(nestingLimit) {} | 677 nestingLimit(nestingLimit) {} |
648 | 678 |
649 friend class ListReader; | 679 friend class ListReader; |
654 // ------------------------------------------------------------------- | 684 // ------------------------------------------------------------------- |
655 | 685 |
656 class ListBuilder: public kj::DisallowConstCopy { | 686 class ListBuilder: public kj::DisallowConstCopy { |
657 public: | 687 public: |
658 inline explicit ListBuilder(ElementSize elementSize) | 688 inline explicit ListBuilder(ElementSize elementSize) |
659 : segment(nullptr), capTable(nullptr), ptr(nullptr), elementCount(0 * ELEMENTS), | 689 : segment(nullptr), capTable(nullptr), ptr(nullptr), elementCount(ZERO * ELEMENTS), |
660 step(0 * BITS / ELEMENTS), structDataSize(0 * BITS), structPointerCount(0 * POINTERS), | 690 step(ZERO * BITS / ELEMENTS), structDataSize(ZERO * BITS), |
661 elementSize(elementSize) {} | 691 structPointerCount(ZERO * POINTERS), elementSize(elementSize) {} |
662 | 692 |
663 inline word* getLocation() { | 693 inline word* getLocation() { |
664 // Get the object's location. | 694 // Get the object's location. |
665 | 695 |
666 if (elementSize == ElementSize::INLINE_COMPOSITE && ptr != nullptr) { | 696 if (elementSize == ElementSize::INLINE_COMPOSITE && ptr != nullptr) { |
670 } | 700 } |
671 } | 701 } |
672 | 702 |
673 inline ElementSize getElementSize() const { return elementSize; } | 703 inline ElementSize getElementSize() const { return elementSize; } |
674 | 704 |
675 inline ElementCount size() const; | 705 inline ListElementCount size() const; |
676 // The number of elements in the list. | 706 // The number of elements in the list. |
677 | 707 |
678 Text::Builder asText(); | 708 Text::Builder asText(); |
679 Data::Builder asData(); | 709 Data::Builder asData(); |
680 // Reinterpret the list as a blob. Throws an exception if the elements are not byte-sized. | 710 // Reinterpret the list as a blob. Throws an exception if the elements are not byte-sized. |
682 template <typename T> | 712 template <typename T> |
683 KJ_ALWAYS_INLINE(T getDataElement(ElementCount index)); | 713 KJ_ALWAYS_INLINE(T getDataElement(ElementCount index)); |
684 // Get the element of the given type at the given index. | 714 // Get the element of the given type at the given index. |
685 | 715 |
686 template <typename T> | 716 template <typename T> |
687 KJ_ALWAYS_INLINE(void setDataElement( | 717 KJ_ALWAYS_INLINE(void setDataElement(ElementCount index, kj::NoInfer<T> value)); |
688 ElementCount index, kj::NoInfer<T> value)); | |
689 // Set the element at the given index. | 718 // Set the element at the given index. |
690 | 719 |
691 KJ_ALWAYS_INLINE(PointerBuilder getPointerElement(ElementCount index)); | 720 KJ_ALWAYS_INLINE(PointerBuilder getPointerElement(ElementCount index)); |
692 | 721 |
693 StructBuilder getStructElement(ElementCount index); | 722 StructBuilder getStructElement(ElementCount index); |
708 SegmentBuilder* segment; // Memory segment in which the list resides. | 737 SegmentBuilder* segment; // Memory segment in which the list resides. |
709 CapTableBuilder* capTable; // Table of capability indexes. | 738 CapTableBuilder* capTable; // Table of capability indexes. |
710 | 739 |
711 byte* ptr; // Pointer to list content. | 740 byte* ptr; // Pointer to list content. |
712 | 741 |
713 ElementCount elementCount; // Number of elements in the list. | 742 ListElementCount elementCount; // Number of elements in the list. |
714 | 743 |
715 decltype(BITS / ELEMENTS) step; | 744 BitsPerElementN<23> step; |
716 // The distance between elements. | 745 // The distance between elements. The maximum value occurs when a struct contains 2^16-1 data |
717 | 746 // words and 2^16-1 pointers, i.e. 2^17 - 2 words, or 2^23 - 128 bits. |
718 BitCount32 structDataSize; | 747 |
719 WirePointerCount16 structPointerCount; | 748 StructDataBitCount structDataSize; |
749 StructPointerCount structPointerCount; | |
720 // The struct properties to use when interpreting the elements as structs. All lists can be | 750 // The struct properties to use when interpreting the elements as structs. All lists can be |
721 // interpreted as struct lists, so these are always filled in. | 751 // interpreted as struct lists, so these are always filled in. |
722 | 752 |
723 ElementSize elementSize; | 753 ElementSize elementSize; |
724 // The element size as a ElementSize. This is only really needed to disambiguate INLINE_COMPOSITE | 754 // The element size as a ElementSize. This is only really needed to disambiguate INLINE_COMPOSITE |
725 // from other types when the overall size is exactly zero or one words. | 755 // from other types when the overall size is exactly zero or one words. |
726 | 756 |
727 inline ListBuilder(SegmentBuilder* segment, CapTableBuilder* capTable, void* ptr, | 757 inline ListBuilder(SegmentBuilder* segment, CapTableBuilder* capTable, void* ptr, |
728 decltype(BITS / ELEMENTS) step, ElementCount size, | 758 BitsPerElementN<23> step, ListElementCount size, |
729 BitCount structDataSize, WirePointerCount structPointerCount, | 759 StructDataBitCount structDataSize, StructPointerCount structPointerCount, |
730 ElementSize elementSize) | 760 ElementSize elementSize) |
731 : segment(segment), capTable(capTable), ptr(reinterpret_cast<byte*>(ptr)), | 761 : segment(segment), capTable(capTable), ptr(reinterpret_cast<byte*>(ptr)), |
732 elementCount(size), step(step), structDataSize(structDataSize), | 762 elementCount(size), step(step), structDataSize(structDataSize), |
733 structPointerCount(structPointerCount), elementSize(elementSize) {} | 763 structPointerCount(structPointerCount), elementSize(elementSize) {} |
734 | 764 |
738 }; | 768 }; |
739 | 769 |
740 class ListReader { | 770 class ListReader { |
741 public: | 771 public: |
742 inline explicit ListReader(ElementSize elementSize) | 772 inline explicit ListReader(ElementSize elementSize) |
743 : segment(nullptr), capTable(nullptr), ptr(nullptr), elementCount(0), | 773 : segment(nullptr), capTable(nullptr), ptr(nullptr), elementCount(ZERO * ELEMENTS), |
744 step(0 * BITS / ELEMENTS), structDataSize(0), structPointerCount(0), | 774 step(ZERO * BITS / ELEMENTS), structDataSize(ZERO * BITS), |
745 elementSize(elementSize), nestingLimit(0x7fffffff) {} | 775 structPointerCount(ZERO * POINTERS), elementSize(elementSize), nestingLimit(0x7fffffff) {} |
746 | 776 |
747 inline ElementCount size() const; | 777 inline ListElementCount size() const; |
748 // The number of elements in the list. | 778 // The number of elements in the list. |
749 | 779 |
750 inline ElementSize getElementSize() const { return elementSize; } | 780 inline ElementSize getElementSize() const { return elementSize; } |
751 | 781 |
752 Text::Reader asText(); | 782 Text::Reader asText(); |
767 // Gets the capability context in which this object is operating. | 797 // Gets the capability context in which this object is operating. |
768 | 798 |
769 ListReader imbue(CapTableReader* capTable) const; | 799 ListReader imbue(CapTableReader* capTable) const; |
770 // Return a copy of this reader except using the given capability context. | 800 // Return a copy of this reader except using the given capability context. |
771 | 801 |
772 bool isCanonical(const word **readHead); | 802 bool isCanonical(const word **readHead, const WirePointer* ref); |
773 // Validate this pointer's canonicity, subject to the conditions: | 803 // Validate this pointer's canonicity, subject to the conditions: |
774 // * All data to the left of readHead has been read thus far (for pointer | 804 // * All data to the left of readHead has been read thus far (for pointer |
775 // ordering) | 805 // ordering) |
776 // * All pointers in preorder have already been checked | 806 // * All pointers in preorder have already been checked |
777 // * This pointer is in the first and only segment of the message | 807 // * This pointer is in the first and only segment of the message |
780 SegmentReader* segment; // Memory segment in which the list resides. | 810 SegmentReader* segment; // Memory segment in which the list resides. |
781 CapTableReader* capTable; // Table of capability indexes. | 811 CapTableReader* capTable; // Table of capability indexes. |
782 | 812 |
783 const byte* ptr; // Pointer to list content. | 813 const byte* ptr; // Pointer to list content. |
784 | 814 |
785 ElementCount elementCount; // Number of elements in the list. | 815 ListElementCount elementCount; // Number of elements in the list. |
786 | 816 |
787 decltype(BITS / ELEMENTS) step; | 817 BitsPerElementN<23> step; |
788 // The distance between elements. | 818 // The distance between elements. The maximum value occurs when a struct contains 2^16-1 data |
789 | 819 // words and 2^16-1 pointers, i.e. 2^17 - 2 words, or 2^23 - 2 bits. |
790 BitCount32 structDataSize; | 820 |
791 WirePointerCount16 structPointerCount; | 821 StructDataBitCount structDataSize; |
822 StructPointerCount structPointerCount; | |
792 // The struct properties to use when interpreting the elements as structs. All lists can be | 823 // The struct properties to use when interpreting the elements as structs. All lists can be |
793 // interpreted as struct lists, so these are always filled in. | 824 // interpreted as struct lists, so these are always filled in. |
794 | 825 |
795 ElementSize elementSize; | 826 ElementSize elementSize; |
796 // The element size as a ElementSize. This is only really needed to disambiguate INLINE_COMPOSITE | 827 // The element size as a ElementSize. This is only really needed to disambiguate INLINE_COMPOSITE |
799 int nestingLimit; | 830 int nestingLimit; |
800 // Limits the depth of message structures to guard against stack-overflow-based DoS attacks. | 831 // Limits the depth of message structures to guard against stack-overflow-based DoS attacks. |
801 // Once this reaches zero, further pointers will be pruned. | 832 // Once this reaches zero, further pointers will be pruned. |
802 | 833 |
803 inline ListReader(SegmentReader* segment, CapTableReader* capTable, const void* ptr, | 834 inline ListReader(SegmentReader* segment, CapTableReader* capTable, const void* ptr, |
804 ElementCount elementCount, decltype(BITS / ELEMENTS) step, | 835 ListElementCount elementCount, BitsPerElementN<23> step, |
805 BitCount structDataSize, WirePointerCount structPointerCount, | 836 StructDataBitCount structDataSize, StructPointerCount structPointerCount, |
806 ElementSize elementSize, int nestingLimit) | 837 ElementSize elementSize, int nestingLimit) |
807 : segment(segment), capTable(capTable), ptr(reinterpret_cast<const byte*>(ptr)), | 838 : segment(segment), capTable(capTable), ptr(reinterpret_cast<const byte*>(ptr)), |
808 elementCount(elementCount), step(step), structDataSize(structDataSize), | 839 elementCount(elementCount), step(step), structDataSize(structDataSize), |
809 structPointerCount(structPointerCount), elementSize(elementSize), | 840 structPointerCount(structPointerCount), elementSize(elementSize), |
810 nestingLimit(nestingLimit) {} | 841 nestingLimit(nestingLimit) {} |
864 // INLINE_COMPOSITE -- use asStructList() instead. | 895 // INLINE_COMPOSITE -- use asStructList() instead. |
865 | 896 |
866 ListBuilder asStructList(StructSize elementSize); | 897 ListBuilder asStructList(StructSize elementSize); |
867 // Interpret as a struct list, or throw an exception if not a list. | 898 // Interpret as a struct list, or throw an exception if not a list. |
868 | 899 |
900 ListBuilder asListAnySize(); | |
901 // For AnyList. | |
902 | |
869 Text::Builder asText(); | 903 Text::Builder asText(); |
870 Data::Builder asData(); | 904 Data::Builder asData(); |
871 // Interpret as a blob, or throw an exception if not a blob. | 905 // Interpret as a blob, or throw an exception if not a blob. |
872 | 906 |
873 StructReader asStructReader(StructSize size) const; | 907 StructReader asStructReader(StructSize size) const; |
874 ListReader asListReader(ElementSize elementSize) const; | 908 ListReader asListReader(ElementSize elementSize) const; |
909 ListReader asListReaderAnySize() const; | |
875 #if !CAPNP_LITE | 910 #if !CAPNP_LITE |
876 kj::Own<ClientHook> asCapability() const; | 911 kj::Own<ClientHook> asCapability() const; |
877 #endif // !CAPNP_LITE | 912 #endif // !CAPNP_LITE |
878 Text::Reader asTextReader() const; | 913 Text::Reader asTextReader() const; |
879 Data::Reader asDataReader() const; | 914 Data::Reader asDataReader() const; |
886 void truncate(ElementCount size, StructSize elementSize); | 921 void truncate(ElementCount size, StructSize elementSize); |
887 void truncateText(ElementCount size); | 922 void truncateText(ElementCount size); |
888 // Versions of truncate() that know how to allocate a new list if needed. | 923 // Versions of truncate() that know how to allocate a new list if needed. |
889 | 924 |
890 private: | 925 private: |
891 static_assert(1 * POINTERS * WORDS_PER_POINTER == 1 * WORDS, | 926 static_assert(ONE * POINTERS * WORDS_PER_POINTER == ONE * WORDS, |
892 "This struct assumes a pointer is one word."); | 927 "This struct assumes a pointer is one word."); |
893 word tag; | 928 word tag; |
894 // Contains an encoded WirePointer representing this object. WirePointer is defined in | 929 // Contains an encoded WirePointer representing this object. WirePointer is defined in |
895 // layout.c++, but fits in a word. | 930 // layout.c++, but fits in a word. |
896 // | 931 // |
932 // Internal implementation details... | 967 // Internal implementation details... |
933 | 968 |
934 // These are defined in the source file. | 969 // These are defined in the source file. |
935 template <> typename Text::Builder PointerBuilder::initBlob<Text>(ByteCount size); | 970 template <> typename Text::Builder PointerBuilder::initBlob<Text>(ByteCount size); |
936 template <> void PointerBuilder::setBlob<Text>(typename Text::Reader value); | 971 template <> void PointerBuilder::setBlob<Text>(typename Text::Reader value); |
937 template <> typename Text::Builder PointerBuilder::getBlob<Text>(const void* defaultValue, ByteCount defaultSize); | 972 template <> typename Text::Builder PointerBuilder::getBlob<Text>( |
938 template <> typename Text::Reader PointerReader::getBlob<Text>(const void* defaultValue, ByteCount defaultSize) const; | 973 const void* defaultValue, ByteCount defaultSize); |
974 template <> typename Text::Reader PointerReader::getBlob<Text>( | |
975 const void* defaultValue, ByteCount defaultSize) const; | |
939 | 976 |
940 template <> typename Data::Builder PointerBuilder::initBlob<Data>(ByteCount size); | 977 template <> typename Data::Builder PointerBuilder::initBlob<Data>(ByteCount size); |
941 template <> void PointerBuilder::setBlob<Data>(typename Data::Reader value); | 978 template <> void PointerBuilder::setBlob<Data>(typename Data::Reader value); |
942 template <> typename Data::Builder PointerBuilder::getBlob<Data>(const void* defaultValue, ByteCount defaultSize); | 979 template <> typename Data::Builder PointerBuilder::getBlob<Data>( |
943 template <> typename Data::Reader PointerReader::getBlob<Data>(const void* defaultValue, ByteCount defaultSize) const; | 980 const void* defaultValue, ByteCount defaultSize); |
981 template <> typename Data::Reader PointerReader::getBlob<Data>( | |
982 const void* defaultValue, ByteCount defaultSize) const; | |
944 | 983 |
945 inline PointerBuilder PointerBuilder::getRoot( | 984 inline PointerBuilder PointerBuilder::getRoot( |
946 SegmentBuilder* segment, CapTableBuilder* capTable, word* location) { | 985 SegmentBuilder* segment, CapTableBuilder* capTable, word* location) { |
947 return PointerBuilder(segment, capTable, reinterpret_cast<WirePointer*>(location)); | 986 return PointerBuilder(segment, capTable, reinterpret_cast<WirePointer*>(location)); |
948 } | 987 } |
953 } | 992 } |
954 | 993 |
955 // ------------------------------------------------------------------- | 994 // ------------------------------------------------------------------- |
956 | 995 |
957 inline kj::ArrayPtr<byte> StructBuilder::getDataSectionAsBlob() { | 996 inline kj::ArrayPtr<byte> StructBuilder::getDataSectionAsBlob() { |
958 return kj::ArrayPtr<byte>(reinterpret_cast<byte*>(data), dataSize / BITS_PER_BYTE / BYTES); | 997 return kj::ArrayPtr<byte>(reinterpret_cast<byte*>(data), |
998 unbound(dataSize / BITS_PER_BYTE / BYTES)); | |
959 } | 999 } |
960 | 1000 |
961 inline _::ListBuilder StructBuilder::getPointerSectionAsList() { | 1001 inline _::ListBuilder StructBuilder::getPointerSectionAsList() { |
962 return _::ListBuilder(segment, capTable, pointers, 1 * POINTERS * BITS_PER_POINTER / ELEMENTS, | 1002 return _::ListBuilder(segment, capTable, pointers, ONE * POINTERS * BITS_PER_POINTER / ELEMENTS, |
963 pointerCount * (1 * ELEMENTS / POINTERS), | 1003 pointerCount * (ONE * ELEMENTS / POINTERS), |
964 0 * BITS, 1 * POINTERS, ElementSize::POINTER); | 1004 ZERO * BITS, ONE * POINTERS, ElementSize::POINTER); |
965 } | 1005 } |
966 | 1006 |
967 template <typename T> | 1007 template <typename T> |
968 inline bool StructBuilder::hasDataField(ElementCount offset) { | 1008 inline bool StructBuilder::hasDataField(StructDataOffset offset) { |
969 return getDataField<Mask<T>>(offset) != 0; | 1009 return getDataField<Mask<T>>(offset) != 0; |
970 } | 1010 } |
971 | 1011 |
972 template <> | 1012 template <> |
973 inline bool StructBuilder::hasDataField<Void>(ElementCount offset) { | 1013 inline bool StructBuilder::hasDataField<Void>(StructDataOffset offset) { |
974 return false; | 1014 return false; |
975 } | 1015 } |
976 | 1016 |
977 template <typename T> | 1017 template <typename T> |
978 inline T StructBuilder::getDataField(ElementCount offset) { | 1018 inline T StructBuilder::getDataField(StructDataOffset offset) { |
979 return reinterpret_cast<WireValue<T>*>(data)[offset / ELEMENTS].get(); | 1019 return reinterpret_cast<WireValue<T>*>(data)[unbound(offset / ELEMENTS)].get(); |
980 } | 1020 } |
981 | 1021 |
982 template <> | 1022 template <> |
983 inline bool StructBuilder::getDataField<bool>(ElementCount offset) { | 1023 inline bool StructBuilder::getDataField<bool>(StructDataOffset offset) { |
984 BitCount boffset = offset * (1 * BITS / ELEMENTS); | 1024 BitCount32 boffset = offset * (ONE * BITS / ELEMENTS); |
985 byte* b = reinterpret_cast<byte*>(data) + boffset / BITS_PER_BYTE; | 1025 byte* b = reinterpret_cast<byte*>(data) + boffset / BITS_PER_BYTE; |
986 return (*reinterpret_cast<uint8_t*>(b) & (1 << (boffset % BITS_PER_BYTE / BITS))) != 0; | 1026 return (*reinterpret_cast<uint8_t*>(b) & |
987 } | 1027 unbound(ONE << (boffset % BITS_PER_BYTE / BITS))) != 0; |
988 | 1028 } |
989 template <> | 1029 |
990 inline Void StructBuilder::getDataField<Void>(ElementCount offset) { | 1030 template <> |
1031 inline Void StructBuilder::getDataField<Void>(StructDataOffset offset) { | |
991 return VOID; | 1032 return VOID; |
992 } | 1033 } |
993 | 1034 |
994 template <typename T> | 1035 template <typename T> |
995 inline T StructBuilder::getDataField(ElementCount offset, Mask<T> mask) { | 1036 inline T StructBuilder::getDataField(StructDataOffset offset, Mask<T> mask) { |
996 return unmask<T>(getDataField<Mask<T> >(offset), mask); | 1037 return unmask<T>(getDataField<Mask<T> >(offset), mask); |
997 } | 1038 } |
998 | 1039 |
999 template <typename T> | 1040 template <typename T> |
1000 inline void StructBuilder::setDataField(ElementCount offset, kj::NoInfer<T> value) { | 1041 inline void StructBuilder::setDataField(StructDataOffset offset, kj::NoInfer<T> value) { |
1001 reinterpret_cast<WireValue<T>*>(data)[offset / ELEMENTS].set(value); | 1042 reinterpret_cast<WireValue<T>*>(data)[unbound(offset / ELEMENTS)].set(value); |
1002 } | 1043 } |
1003 | 1044 |
1004 #if CAPNP_CANONICALIZE_NAN | 1045 #if CAPNP_CANONICALIZE_NAN |
1005 // Use mask() on floats and doubles to make sure we canonicalize NaNs. | 1046 // Use mask() on floats and doubles to make sure we canonicalize NaNs. |
1006 template <> | 1047 template <> |
1007 inline void StructBuilder::setDataField<float>(ElementCount offset, float value) { | 1048 inline void StructBuilder::setDataField<float>(StructDataOffset offset, float value) { |
1008 setDataField<uint32_t>(offset, mask<float>(value, 0)); | 1049 setDataField<uint32_t>(offset, mask<float>(value, 0)); |
1009 } | 1050 } |
1010 template <> | 1051 template <> |
1011 inline void StructBuilder::setDataField<double>(ElementCount offset, double value) { | 1052 inline void StructBuilder::setDataField<double>(StructDataOffset offset, double value) { |
1012 setDataField<uint64_t>(offset, mask<double>(value, 0)); | 1053 setDataField<uint64_t>(offset, mask<double>(value, 0)); |
1013 } | 1054 } |
1014 #endif | 1055 #endif |
1015 | 1056 |
1016 template <> | 1057 template <> |
1017 inline void StructBuilder::setDataField<bool>(ElementCount offset, bool value) { | 1058 inline void StructBuilder::setDataField<bool>(StructDataOffset offset, bool value) { |
1018 BitCount boffset = offset * (1 * BITS / ELEMENTS); | 1059 auto boffset = offset * (ONE * BITS / ELEMENTS); |
1019 byte* b = reinterpret_cast<byte*>(data) + boffset / BITS_PER_BYTE; | 1060 byte* b = reinterpret_cast<byte*>(data) + boffset / BITS_PER_BYTE; |
1020 uint bitnum = boffset % BITS_PER_BYTE / BITS; | 1061 uint bitnum = unboundMaxBits<3>(boffset % BITS_PER_BYTE / BITS); |
1021 *reinterpret_cast<uint8_t*>(b) = (*reinterpret_cast<uint8_t*>(b) & ~(1 << bitnum)) | 1062 *reinterpret_cast<uint8_t*>(b) = (*reinterpret_cast<uint8_t*>(b) & ~(1 << bitnum)) |
1022 | (static_cast<uint8_t>(value) << bitnum); | 1063 | (static_cast<uint8_t>(value) << bitnum); |
1023 } | 1064 } |
1024 | 1065 |
1025 template <> | 1066 template <> |
1026 inline void StructBuilder::setDataField<Void>(ElementCount offset, Void value) {} | 1067 inline void StructBuilder::setDataField<Void>(StructDataOffset offset, Void value) {} |
1027 | 1068 |
1028 template <typename T> | 1069 template <typename T> |
1029 inline void StructBuilder::setDataField(ElementCount offset, kj::NoInfer<T> value, Mask<T> m) { | 1070 inline void StructBuilder::setDataField(StructDataOffset offset, |
1071 kj::NoInfer<T> value, Mask<T> m) { | |
1030 setDataField<Mask<T> >(offset, mask<T>(value, m)); | 1072 setDataField<Mask<T> >(offset, mask<T>(value, m)); |
1031 } | 1073 } |
1032 | 1074 |
1033 inline PointerBuilder StructBuilder::getPointerField(WirePointerCount ptrIndex) { | 1075 inline PointerBuilder StructBuilder::getPointerField(StructPointerOffset ptrIndex) { |
1034 // Hacky because WirePointer is defined in the .c++ file (so is incomplete here). | 1076 // Hacky because WirePointer is defined in the .c++ file (so is incomplete here). |
1035 return PointerBuilder(segment, capTable, reinterpret_cast<WirePointer*>( | 1077 return PointerBuilder(segment, capTable, reinterpret_cast<WirePointer*>( |
1036 reinterpret_cast<word*>(pointers) + ptrIndex * WORDS_PER_POINTER)); | 1078 reinterpret_cast<word*>(pointers) + ptrIndex * WORDS_PER_POINTER)); |
1037 } | 1079 } |
1038 | 1080 |
1039 // ------------------------------------------------------------------- | 1081 // ------------------------------------------------------------------- |
1040 | 1082 |
1041 inline kj::ArrayPtr<const byte> StructReader::getDataSectionAsBlob() { | 1083 inline kj::ArrayPtr<const byte> StructReader::getDataSectionAsBlob() { |
1042 return kj::ArrayPtr<const byte>(reinterpret_cast<const byte*>(data), dataSize / BITS_PER_BYTE / BYTES); | 1084 return kj::ArrayPtr<const byte>(reinterpret_cast<const byte*>(data), |
1085 unbound(dataSize / BITS_PER_BYTE / BYTES)); | |
1043 } | 1086 } |
1044 | 1087 |
1045 inline _::ListReader StructReader::getPointerSectionAsList() { | 1088 inline _::ListReader StructReader::getPointerSectionAsList() { |
1046 return _::ListReader(segment, capTable, pointers, pointerCount * (1 * ELEMENTS / POINTERS), | 1089 return _::ListReader(segment, capTable, pointers, pointerCount * (ONE * ELEMENTS / POINTERS), |
1047 1 * POINTERS * BITS_PER_POINTER / ELEMENTS, 0 * BITS, 1 * POINTERS, | 1090 ONE * POINTERS * BITS_PER_POINTER / ELEMENTS, ZERO * BITS, ONE * POINTERS, |
1048 ElementSize::POINTER, nestingLimit); | 1091 ElementSize::POINTER, nestingLimit); |
1049 } | 1092 } |
1050 | 1093 |
1051 template <typename T> | 1094 template <typename T> |
1052 inline bool StructReader::hasDataField(ElementCount offset) const { | 1095 inline bool StructReader::hasDataField(StructDataOffset offset) const { |
1053 return getDataField<Mask<T>>(offset) != 0; | 1096 return getDataField<Mask<T>>(offset) != 0; |
1054 } | 1097 } |
1055 | 1098 |
1056 template <> | 1099 template <> |
1057 inline bool StructReader::hasDataField<Void>(ElementCount offset) const { | 1100 inline bool StructReader::hasDataField<Void>(StructDataOffset offset) const { |
1058 return false; | 1101 return false; |
1059 } | 1102 } |
1060 | 1103 |
1061 template <typename T> | 1104 template <typename T> |
1062 inline T StructReader::getDataField(ElementCount offset) const { | 1105 inline T StructReader::getDataField(StructDataOffset offset) const { |
1063 if ((offset + 1 * ELEMENTS) * capnp::bitsPerElement<T>() <= dataSize) { | 1106 if ((offset + ONE * ELEMENTS) * capnp::bitsPerElement<T>() <= dataSize) { |
1064 return reinterpret_cast<const WireValue<T>*>(data)[offset / ELEMENTS].get(); | 1107 return reinterpret_cast<const WireValue<T>*>(data)[unbound(offset / ELEMENTS)].get(); |
1065 } else { | 1108 } else { |
1066 return static_cast<T>(0); | 1109 return static_cast<T>(0); |
1067 } | 1110 } |
1068 } | 1111 } |
1069 | 1112 |
1070 template <> | 1113 template <> |
1071 inline bool StructReader::getDataField<bool>(ElementCount offset) const { | 1114 inline bool StructReader::getDataField<bool>(StructDataOffset offset) const { |
1072 BitCount boffset = offset * (1 * BITS / ELEMENTS); | 1115 auto boffset = offset * (ONE * BITS / ELEMENTS); |
1073 if (boffset < dataSize) { | 1116 if (boffset < dataSize) { |
1074 const byte* b = reinterpret_cast<const byte*>(data) + boffset / BITS_PER_BYTE; | 1117 const byte* b = reinterpret_cast<const byte*>(data) + boffset / BITS_PER_BYTE; |
1075 return (*reinterpret_cast<const uint8_t*>(b) & (1 << (boffset % BITS_PER_BYTE / BITS))) != 0; | 1118 return (*reinterpret_cast<const uint8_t*>(b) & |
1119 unbound(ONE << (boffset % BITS_PER_BYTE / BITS))) != 0; | |
1076 } else { | 1120 } else { |
1077 return false; | 1121 return false; |
1078 } | 1122 } |
1079 } | 1123 } |
1080 | 1124 |
1081 template <> | 1125 template <> |
1082 inline Void StructReader::getDataField<Void>(ElementCount offset) const { | 1126 inline Void StructReader::getDataField<Void>(StructDataOffset offset) const { |
1083 return VOID; | 1127 return VOID; |
1084 } | 1128 } |
1085 | 1129 |
1086 template <typename T> | 1130 template <typename T> |
1087 T StructReader::getDataField(ElementCount offset, Mask<T> mask) const { | 1131 T StructReader::getDataField(StructDataOffset offset, Mask<T> mask) const { |
1088 return unmask<T>(getDataField<Mask<T> >(offset), mask); | 1132 return unmask<T>(getDataField<Mask<T> >(offset), mask); |
1089 } | 1133 } |
1090 | 1134 |
1091 inline PointerReader StructReader::getPointerField(WirePointerCount ptrIndex) const { | 1135 inline PointerReader StructReader::getPointerField(StructPointerOffset ptrIndex) const { |
1092 if (ptrIndex < pointerCount) { | 1136 if (ptrIndex < pointerCount) { |
1093 // Hacky because WirePointer is defined in the .c++ file (so is incomplete here). | 1137 // Hacky because WirePointer is defined in the .c++ file (so is incomplete here). |
1094 return PointerReader(segment, capTable, reinterpret_cast<const WirePointer*>( | 1138 return PointerReader(segment, capTable, reinterpret_cast<const WirePointer*>( |
1095 reinterpret_cast<const word*>(pointers) + ptrIndex * WORDS_PER_POINTER), nestingLimit); | 1139 reinterpret_cast<const word*>(pointers) + ptrIndex * WORDS_PER_POINTER), nestingLimit); |
1096 } else{ | 1140 } else{ |
1098 } | 1142 } |
1099 } | 1143 } |
1100 | 1144 |
1101 // ------------------------------------------------------------------- | 1145 // ------------------------------------------------------------------- |
1102 | 1146 |
1103 inline ElementCount ListBuilder::size() const { return elementCount; } | 1147 inline ListElementCount ListBuilder::size() const { return elementCount; } |
1104 | 1148 |
1105 template <typename T> | 1149 template <typename T> |
1106 inline T ListBuilder::getDataElement(ElementCount index) { | 1150 inline T ListBuilder::getDataElement(ElementCount index) { |
1107 return reinterpret_cast<WireValue<T>*>(ptr + index * step / BITS_PER_BYTE)->get(); | 1151 return reinterpret_cast<WireValue<T>*>( |
1152 ptr + upgradeBound<uint64_t>(index) * step / BITS_PER_BYTE)->get(); | |
1108 | 1153 |
1109 // TODO(perf): Benchmark this alternate implementation, which I suspect may make better use of | 1154 // TODO(perf): Benchmark this alternate implementation, which I suspect may make better use of |
1110 // the x86 SIB byte. Also use it for all the other getData/setData implementations below, and | 1155 // the x86 SIB byte. Also use it for all the other getData/setData implementations below, and |
1111 // the various non-inline methods that look up pointers. | 1156 // the various non-inline methods that look up pointers. |
1112 // Also if using this, consider changing ptr back to void* instead of byte*. | 1157 // Also if using this, consider changing ptr back to void* instead of byte*. |
1115 } | 1160 } |
1116 | 1161 |
1117 template <> | 1162 template <> |
1118 inline bool ListBuilder::getDataElement<bool>(ElementCount index) { | 1163 inline bool ListBuilder::getDataElement<bool>(ElementCount index) { |
1119 // Ignore step for bit lists because bit lists cannot be upgraded to struct lists. | 1164 // Ignore step for bit lists because bit lists cannot be upgraded to struct lists. |
1120 BitCount bindex = index * (1 * BITS / ELEMENTS); | 1165 auto bindex = index * (ONE * BITS / ELEMENTS); |
1121 byte* b = ptr + bindex / BITS_PER_BYTE; | 1166 byte* b = ptr + bindex / BITS_PER_BYTE; |
1122 return (*reinterpret_cast<uint8_t*>(b) & (1 << (bindex % BITS_PER_BYTE / BITS))) != 0; | 1167 return (*reinterpret_cast<uint8_t*>(b) & |
1168 unbound(ONE << (bindex % BITS_PER_BYTE / BITS))) != 0; | |
1123 } | 1169 } |
1124 | 1170 |
1125 template <> | 1171 template <> |
1126 inline Void ListBuilder::getDataElement<Void>(ElementCount index) { | 1172 inline Void ListBuilder::getDataElement<Void>(ElementCount index) { |
1127 return VOID; | 1173 return VOID; |
1128 } | 1174 } |
1129 | 1175 |
1130 template <typename T> | 1176 template <typename T> |
1131 inline void ListBuilder::setDataElement(ElementCount index, kj::NoInfer<T> value) { | 1177 inline void ListBuilder::setDataElement(ElementCount index, kj::NoInfer<T> value) { |
1132 reinterpret_cast<WireValue<T>*>(ptr + index * step / BITS_PER_BYTE)->set(value); | 1178 reinterpret_cast<WireValue<T>*>( |
1179 ptr + upgradeBound<uint64_t>(index) * step / BITS_PER_BYTE)->set(value); | |
1133 } | 1180 } |
1134 | 1181 |
1135 #if CAPNP_CANONICALIZE_NAN | 1182 #if CAPNP_CANONICALIZE_NAN |
1136 // Use mask() on floats and doubles to make sure we canonicalize NaNs. | 1183 // Use mask() on floats and doubles to make sure we canonicalize NaNs. |
1137 template <> | 1184 template <> |
1145 #endif | 1192 #endif |
1146 | 1193 |
1147 template <> | 1194 template <> |
1148 inline void ListBuilder::setDataElement<bool>(ElementCount index, bool value) { | 1195 inline void ListBuilder::setDataElement<bool>(ElementCount index, bool value) { |
1149 // Ignore stepBytes for bit lists because bit lists cannot be upgraded to struct lists. | 1196 // Ignore stepBytes for bit lists because bit lists cannot be upgraded to struct lists. |
1150 BitCount bindex = index * (1 * BITS / ELEMENTS); | 1197 auto bindex = index * (ONE * BITS / ELEMENTS); |
1151 byte* b = ptr + bindex / BITS_PER_BYTE; | 1198 byte* b = ptr + bindex / BITS_PER_BYTE; |
1152 uint bitnum = bindex % BITS_PER_BYTE / BITS; | 1199 auto bitnum = bindex % BITS_PER_BYTE / BITS; |
1153 *reinterpret_cast<uint8_t*>(b) = (*reinterpret_cast<uint8_t*>(b) & ~(1 << bitnum)) | 1200 *reinterpret_cast<uint8_t*>(b) = (*reinterpret_cast<uint8_t*>(b) & ~(1 << unbound(bitnum))) |
1154 | (static_cast<uint8_t>(value) << bitnum); | 1201 | (static_cast<uint8_t>(value) << unbound(bitnum)); |
1155 } | 1202 } |
1156 | 1203 |
1157 template <> | 1204 template <> |
1158 inline void ListBuilder::setDataElement<Void>(ElementCount index, Void value) {} | 1205 inline void ListBuilder::setDataElement<Void>(ElementCount index, Void value) {} |
1159 | 1206 |
1160 inline PointerBuilder ListBuilder::getPointerElement(ElementCount index) { | 1207 inline PointerBuilder ListBuilder::getPointerElement(ElementCount index) { |
1161 return PointerBuilder(segment, capTable, | 1208 return PointerBuilder(segment, capTable, reinterpret_cast<WirePointer*>(ptr + |
1162 reinterpret_cast<WirePointer*>(ptr + index * step / BITS_PER_BYTE)); | 1209 upgradeBound<uint64_t>(index) * step / BITS_PER_BYTE)); |
1163 } | 1210 } |
1164 | 1211 |
1165 // ------------------------------------------------------------------- | 1212 // ------------------------------------------------------------------- |
1166 | 1213 |
1167 inline ElementCount ListReader::size() const { return elementCount; } | 1214 inline ListElementCount ListReader::size() const { return elementCount; } |
1168 | 1215 |
1169 template <typename T> | 1216 template <typename T> |
1170 inline T ListReader::getDataElement(ElementCount index) const { | 1217 inline T ListReader::getDataElement(ElementCount index) const { |
1171 return reinterpret_cast<const WireValue<T>*>(ptr + index * step / BITS_PER_BYTE)->get(); | 1218 return reinterpret_cast<const WireValue<T>*>( |
1219 ptr + upgradeBound<uint64_t>(index) * step / BITS_PER_BYTE)->get(); | |
1172 } | 1220 } |
1173 | 1221 |
1174 template <> | 1222 template <> |
1175 inline bool ListReader::getDataElement<bool>(ElementCount index) const { | 1223 inline bool ListReader::getDataElement<bool>(ElementCount index) const { |
1176 // Ignore step for bit lists because bit lists cannot be upgraded to struct lists. | 1224 // Ignore step for bit lists because bit lists cannot be upgraded to struct lists. |
1177 BitCount bindex = index * (1 * BITS / ELEMENTS); | 1225 auto bindex = index * (ONE * BITS / ELEMENTS); |
1178 const byte* b = ptr + bindex / BITS_PER_BYTE; | 1226 const byte* b = ptr + bindex / BITS_PER_BYTE; |
1179 return (*reinterpret_cast<const uint8_t*>(b) & (1 << (bindex % BITS_PER_BYTE / BITS))) != 0; | 1227 return (*reinterpret_cast<const uint8_t*>(b) & |
1228 unbound(ONE << (bindex % BITS_PER_BYTE / BITS))) != 0; | |
1180 } | 1229 } |
1181 | 1230 |
1182 template <> | 1231 template <> |
1183 inline Void ListReader::getDataElement<Void>(ElementCount index) const { | 1232 inline Void ListReader::getDataElement<Void>(ElementCount index) const { |
1184 return VOID; | 1233 return VOID; |
1185 } | 1234 } |
1186 | 1235 |
1187 inline PointerReader ListReader::getPointerElement(ElementCount index) const { | 1236 inline PointerReader ListReader::getPointerElement(ElementCount index) const { |
1188 return PointerReader(segment, capTable, | 1237 return PointerReader(segment, capTable, reinterpret_cast<const WirePointer*>( |
1189 reinterpret_cast<const WirePointer*>(ptr + index * step / BITS_PER_BYTE), nestingLimit); | 1238 ptr + upgradeBound<uint64_t>(index) * step / BITS_PER_BYTE), nestingLimit); |
1190 } | 1239 } |
1191 | 1240 |
1192 // ------------------------------------------------------------------- | 1241 // ------------------------------------------------------------------- |
1193 | 1242 |
1194 inline OrphanBuilder::OrphanBuilder(OrphanBuilder&& other) noexcept | 1243 inline OrphanBuilder::OrphanBuilder(OrphanBuilder&& other) noexcept |