@@ -423,8 +423,8 @@ constexpr char GetOrNull(absl::string_view data, size_t pos) {
423423 return pos < data.size () ? data[pos] : ' \0 ' ;
424424}
425425
426- // We store cordz_info as 64 bit pointer value in big endian format. This
427- // guarantees that the least significant byte of cordz_info matches the last
426+ // We store cordz_info as 64 bit pointer value in little endian format. This
427+ // guarantees that the least significant byte of cordz_info matches the first
428428// byte of the inline data representation in as_chars_, which holds the inlined
429429// size or the 'is_tree' bit.
430430using cordz_info_t = int64_t ;
@@ -434,14 +434,14 @@ using cordz_info_t = int64_t;
434434static_assert (sizeof (cordz_info_t ) * 2 == kMaxInline + 1 , " " );
435435static_assert (sizeof (cordz_info_t ) >= sizeof (intptr_t ), " " );
436436
437- // BigEndianByte () creates a big endian representation of 'value', i.e.: a big
438- // endian value where the last byte in the host's representation holds 'value`,
439- // with all other bytes being 0.
440- static constexpr cordz_info_t BigEndianByte (unsigned char value) {
437+ // LittleEndianByte () creates a little endian representation of 'value', i.e.:
438+ // a little endian value where the first byte in the host's representation
439+ // holds 'value`, with all other bytes being 0.
440+ static constexpr cordz_info_t LittleEndianByte (unsigned char value) {
441441#if defined(ABSL_IS_BIG_ENDIAN)
442- return value;
443- #else
444442 return static_cast <cordz_info_t >(value) << ((sizeof (cordz_info_t ) - 1 ) * 8 );
443+ #else
444+ return value;
445445#endif
446446}
447447
@@ -450,25 +450,37 @@ class InlineData {
450450 // DefaultInitType forces the use of the default initialization constructor.
451451 enum DefaultInitType { kDefaultInit };
452452
453- // kNullCordzInfo holds the big endian representation of intptr_t(1)
453+ // kNullCordzInfo holds the little endian representation of intptr_t(1)
454454 // This is the 'null' / initial value of 'cordz_info'. The null value
455455 // is specifically big endian 1 as with 64-bit pointers, the last
456456 // byte of cordz_info overlaps with the last byte holding the tag.
457- static constexpr cordz_info_t kNullCordzInfo = BigEndianByte(1 );
457+ static constexpr cordz_info_t kNullCordzInfo = LittleEndianByte(1 );
458+
459+ // kTagOffset contains the offset of the control byte / tag. This constant is
460+ // intended mostly for debugging purposes: do not remove this constant as it
461+ // is actively inspected and used by gdb pretty printing code.
462+ static constexpr size_t kTagOffset = 0 ;
458463
459464 constexpr InlineData () : as_chars_{0 } {}
460465 explicit InlineData (DefaultInitType) {}
461466 explicit constexpr InlineData (CordRep* rep) : as_tree_(rep) {}
462467 explicit constexpr InlineData (absl::string_view chars)
463- : as_chars_{
464- GetOrNull (chars, 0 ), GetOrNull (chars, 1 ),
465- GetOrNull (chars, 2 ), GetOrNull (chars, 3 ),
466- GetOrNull (chars, 4 ), GetOrNull (chars, 5 ),
467- GetOrNull (chars, 6 ), GetOrNull (chars, 7 ),
468- GetOrNull (chars, 8 ), GetOrNull (chars, 9 ),
469- GetOrNull (chars, 10 ), GetOrNull (chars, 11 ),
470- GetOrNull (chars, 12 ), GetOrNull (chars, 13 ),
471- GetOrNull (chars, 14 ), static_cast <char >((chars.size () << 1 ))} {}
468+ : as_chars_{static_cast <char >((chars.size () << 1 )),
469+ GetOrNull (chars, 0 ),
470+ GetOrNull (chars, 1 ),
471+ GetOrNull (chars, 2 ),
472+ GetOrNull (chars, 3 ),
473+ GetOrNull (chars, 4 ),
474+ GetOrNull (chars, 5 ),
475+ GetOrNull (chars, 6 ),
476+ GetOrNull (chars, 7 ),
477+ GetOrNull (chars, 8 ),
478+ GetOrNull (chars, 9 ),
479+ GetOrNull (chars, 10 ),
480+ GetOrNull (chars, 11 ),
481+ GetOrNull (chars, 12 ),
482+ GetOrNull (chars, 13 ),
483+ GetOrNull (chars, 14 )} {}
472484
473485 // Returns true if the current instance is empty.
474486 // The 'empty value' is an inlined data value of zero length.
@@ -499,8 +511,8 @@ class InlineData {
499511 // Requires the current instance to hold a tree value.
500512 CordzInfo* cordz_info () const {
501513 assert (is_tree ());
502- intptr_t info = static_cast <intptr_t >(
503- absl::big_endian::ToHost64 ( static_cast <uint64_t >(as_tree_.cordz_info )));
514+ intptr_t info = static_cast <intptr_t >(absl::little_endian::ToHost64 (
515+ static_cast <uint64_t >(as_tree_.cordz_info )));
504516 assert (info & 1 );
505517 return reinterpret_cast <CordzInfo*>(info - 1 );
506518 }
@@ -512,7 +524,7 @@ class InlineData {
512524 assert (is_tree ());
513525 uintptr_t info = reinterpret_cast <uintptr_t >(cordz_info) | 1 ;
514526 as_tree_.cordz_info =
515- static_cast <cordz_info_t >(absl::big_endian ::FromHost64 (info));
527+ static_cast <cordz_info_t >(absl::little_endian ::FromHost64 (info));
516528 }
517529
518530 // Resets the current cordz_info to null / empty.
@@ -525,7 +537,7 @@ class InlineData {
525537 // Requires the current instance to hold inline data.
526538 const char * as_chars () const {
527539 assert (!is_tree ());
528- return as_chars_;
540+ return & as_chars_[ 1 ] ;
529541 }
530542
531543 // Returns a mutable pointer to the character data inside this instance.
@@ -543,7 +555,7 @@ class InlineData {
543555 //
544556 // It's an error to read from the returned pointer without a preceding write
545557 // if the current instance does not hold inline data, i.e.: is_tree() == true.
546- char * as_chars () { return as_chars_; }
558+ char * as_chars () { return & as_chars_[ 1 ] ; }
547559
548560 // Returns the tree value of this value.
549561 // Requires the current instance to hold a tree value.
@@ -608,20 +620,13 @@ class InlineData {
608620 private:
609621 // See cordz_info_t for forced alignment and size of `cordz_info` details.
610622 struct AsTree {
611- explicit constexpr AsTree (absl::cord_internal::CordRep* tree)
612- : rep(tree), cordz_info(kNullCordzInfo ) {}
613- // This union uses up extra space so that whether rep is 32 or 64 bits,
614- // cordz_info will still start at the eighth byte, and the last
615- // byte of cordz_info will still be the last byte of InlineData.
616- union {
617- absl::cord_internal::CordRep* rep;
618- cordz_info_t unused_aligner;
619- };
620- cordz_info_t cordz_info;
623+ explicit constexpr AsTree (absl::cord_internal::CordRep* tree) : rep(tree) {}
624+ cordz_info_t cordz_info = kNullCordzInfo ;
625+ absl::cord_internal::CordRep* rep;
621626 };
622627
623- char & tag () { return reinterpret_cast <char *>(this )[kMaxInline ]; }
624- char tag () const { return reinterpret_cast <const char *>(this )[kMaxInline ]; }
628+ int8_t & tag () { return reinterpret_cast <int8_t *>(this )[0 ]; }
629+ int8_t tag () const { return reinterpret_cast <const int8_t *>(this )[0 ]; }
625630
626631 // If the data has length <= kMaxInline, we store it in `as_chars_`, and
627632 // store the size in the last char of `as_chars_` shifted left + 1.
0 commit comments