Drop MapEntry::_InternalParse and use the TcParser generated version instead.

PiperOrigin-RevId: 609769553
pull/15933/head
Protobuf Team Bot 1 year ago committed by Copybara-Service
parent 5983f7033c
commit 6bf0d8a936
  1. 61
      src/google/protobuf/compiler/cpp/message.cc
  2. 35
      src/google/protobuf/generated_message_tctable_gen.cc
  3. 55
      src/google/protobuf/map_entry.h
  4. 161
      src/google/protobuf/map_type_handler.h

@ -1292,67 +1292,6 @@ void MessageGenerator::GenerateMapEntryClassDefinition(io::Printer* p) {
&_$classname$_default_instance_);
}
)cc");
auto utf8_check = internal::cpp::GetUtf8CheckMode(
descriptor_->field(0), GetOptimizeFor(descriptor_->file(), options_) ==
FileOptions::LITE_RUNTIME);
if (descriptor_->field(0)->type() == FieldDescriptor::TYPE_STRING &&
utf8_check != Utf8CheckMode::kNone) {
if (utf8_check == Utf8CheckMode::kStrict) {
format(
" static bool ValidateKey(std::string* s) {\n"
" return ::$proto_ns$::internal::WireFormatLite::"
"VerifyUtf8String(s->data(), static_cast<int>(s->size()), "
"::$proto_ns$::internal::WireFormatLite::PARSE, \"$1$\");\n"
" }\n",
descriptor_->field(0)->full_name());
} else {
ABSL_CHECK(utf8_check == Utf8CheckMode::kVerify);
format(
" static bool ValidateKey(std::string* s) {\n"
"#ifndef NDEBUG\n"
" ::$proto_ns$::internal::WireFormatLite::VerifyUtf8String(\n"
" s->data(), static_cast<int>(s->size()), "
"::$proto_ns$::internal::"
"WireFormatLite::PARSE, \"$1$\");\n"
"#else\n"
" (void) s;\n"
"#endif\n"
" return true;\n"
" }\n",
descriptor_->field(0)->full_name());
}
} else {
format(" static bool ValidateKey(void*) { return true; }\n");
}
if (descriptor_->field(1)->type() == FieldDescriptor::TYPE_STRING &&
utf8_check != Utf8CheckMode::kNone) {
if (utf8_check == Utf8CheckMode::kStrict) {
format(
" static bool ValidateValue(std::string* s) {\n"
" return ::$proto_ns$::internal::WireFormatLite::"
"VerifyUtf8String(s->data(), static_cast<int>(s->size()), "
"::$proto_ns$::internal::WireFormatLite::PARSE, \"$1$\");\n"
" }\n",
descriptor_->field(1)->full_name());
} else {
ABSL_CHECK(utf8_check == Utf8CheckMode::kVerify);
format(
" static bool ValidateValue(std::string* s) {\n"
"#ifndef NDEBUG\n"
" ::$proto_ns$::internal::WireFormatLite::VerifyUtf8String(\n"
" s->data(), static_cast<int>(s->size()), "
"::$proto_ns$::internal::"
"WireFormatLite::PARSE, \"$1$\");\n"
"#else\n"
" (void) s;\n"
"#endif\n"
" return true;\n"
" }\n",
descriptor_->field(1)->full_name());
}
} else {
format(" static bool ValidateValue(void*) { return true; }\n");
}
p->Emit(R"cc(
const $superclass$::ClassData* GetClassData() const final;
)cc");

@ -32,6 +32,15 @@ namespace internal {
namespace {
bool TreatEnumAsInt(const FieldDescriptor* field) {
return cpp::HasPreservingUnknownEnumSemantics(field) ||
// For legacy reasons, MapEntry mapped_type enum fields are handled as
// open always. The validation happens elsewhere.
(field->enum_type() != nullptr &&
field->containing_type() != nullptr &&
field->containing_type()->map_value() == field);
}
bool GetEnumValidationRange(const EnumDescriptor* enum_type, int16_t& start,
uint16_t& size) {
ABSL_CHECK_GT(enum_type->value_count(), 0) << enum_type->DebugString();
@ -159,7 +168,7 @@ TailCallTableInfo::FastFieldInfo::Field MakeFastFieldEntry(
picked = PROTOBUF_PICK_PACKABLE_FUNCTION(kFastF64);
break;
case FieldDescriptor::TYPE_ENUM:
if (cpp::HasPreservingUnknownEnumSemantics(field)) {
if (TreatEnumAsInt(field)) {
picked = PROTOBUF_PICK_PACKABLE_FUNCTION(kFastV32);
} else {
switch (GetEnumRangeInfo(field, info.aux_idx)) {
@ -283,12 +292,9 @@ bool IsFieldEligibleForFastParsing(
break;
}
if (cpp::HasHasbit(field)) {
// The tailcall parser can only update the first 32 hasbits. Fields with
// has-bits beyond the first 32 are handled by mini parsing/fallback.
ABSL_CHECK_GE(entry.hasbit_idx, 0) << field->DebugString();
if (entry.hasbit_idx >= 32) return false;
}
// The tailcall parser can only update the first 32 hasbits. Fields with
// has-bits beyond the first 32 are handled by mini parsing/fallback.
if (entry.hasbit_idx >= 32) return false;
// If the field needs auxiliary data, then the aux index is needed. This
// must fit in a uint8_t.
@ -404,7 +410,7 @@ std::vector<TailCallTableInfo::FastFieldInfo> SplitFastFieldsForSize(
fast_field.coded_tag = tag;
// If this field does not have presence, then it can set an out-of-bounds
// bit (tailcall parsing uses a uint64_t for hasbits, but only stores 32).
fast_field.hasbit_idx = cpp::HasHasbit(field) ? entry.hasbit_idx : 63;
fast_field.hasbit_idx = entry.hasbit_idx >= 0 ? entry.hasbit_idx : 63;
}
return result;
}
@ -537,12 +543,12 @@ TailCallTableInfo::NumToEntryTable MakeNumToEntryTable(
}
uint16_t MakeTypeCardForField(
const FieldDescriptor* field,
const FieldDescriptor* field, bool has_hasbit,
const TailCallTableInfo::MessageOptions& message_options,
const TailCallTableInfo::PerFieldOptions& options) {
uint16_t type_card;
namespace fl = internal::field_layout;
if (internal::cpp::HasHasbit(field)) {
if (has_hasbit) {
type_card = fl::kFcOptional;
} else if (field->is_repeated()) {
type_card = fl::kFcRepeated;
@ -588,7 +594,7 @@ uint16_t MakeTypeCardForField(
: fl::kBool;
break;
case FieldDescriptor::TYPE_ENUM:
if (internal::cpp::HasPreservingUnknownEnumSemantics(field)) {
if (TreatEnumAsInt(field)) {
// No validation is required.
type_card |= field->is_repeated() && field->is_packed()
? fl::kPackedOpenEnum
@ -812,11 +818,12 @@ TailCallTableInfo::TailCallTableInfo(
for (const FieldDescriptor* field : ordered_fields) {
auto options = option_provider.GetForField(field);
field_entries.push_back(
{field, internal::cpp ::HasHasbit(field)
{field, static_cast<size_t>(field->index()) < has_bit_indices.size()
? has_bit_indices[static_cast<size_t>(field->index())]
: -1});
auto& entry = field_entries.back();
entry.type_card = MakeTypeCardForField(field, message_options, options);
entry.type_card = MakeTypeCardForField(field, entry.hasbit_idx >= 0,
message_options, options);
if (field->type() == FieldDescriptor::TYPE_MESSAGE ||
field->type() == FieldDescriptor::TYPE_GROUP) {
@ -865,7 +872,7 @@ TailCallTableInfo::TailCallTableInfo(
}
}
} else if (field->type() == FieldDescriptor::TYPE_ENUM &&
!cpp::HasPreservingUnknownEnumSemantics(field)) {
!TreatEnumAsInt(field)) {
// Enum fields which preserve unknown values (proto3 behavior) are
// effectively int32 fields with respect to parsing -- i.e., the value
// does not need to be validated at parse time.

@ -84,17 +84,6 @@ class MapEntry : public Message {
using KeyOnMemory = typename KeyTypeHandler::TypeOnMemory;
using ValueOnMemory = typename ValueTypeHandler::TypeOnMemory;
// Constants for field number.
static const int kKeyFieldNumber = 1;
static const int kValueFieldNumber = 2;
// Constants for field tag.
static const uint8_t kKeyTag =
GOOGLE_PROTOBUF_WIRE_FORMAT_MAKE_TAG(kKeyFieldNumber, KeyTypeHandler::kWireType);
static const uint8_t kValueTag = GOOGLE_PROTOBUF_WIRE_FORMAT_MAKE_TAG(
kValueFieldNumber, ValueTypeHandler::kWireType);
static const size_t kTagSize = 1;
public:
constexpr MapEntry()
: key_(KeyTypeHandler::Constinit()),
@ -118,56 +107,12 @@ class MapEntry : public Message {
using InternalArenaConstructable_ = void;
using DestructorSkippable_ = void;
// accessors ======================================================
inline auto* mutable_key() {
_has_bits_[0] |= 0x00000001u;
return KeyTypeHandler::EnsureMutable(&key_, GetArena());
}
inline auto* mutable_value() {
_has_bits_[0] |= 0x00000002u;
return ValueTypeHandler::EnsureMutable(&value_, GetArena());
}
// TODO: These methods currently differ in behavior from the ones
// implemented via reflection. This means that a MapEntry does not behave the
// same as an equivalent object made via DynamicMessage.
const char* _InternalParse(const char* ptr, ParseContext* ctx) final {
while (!ctx->Done(&ptr)) {
uint32_t tag;
ptr = ReadTag(ptr, &tag);
GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
if (tag == kKeyTag) {
auto* key = mutable_key();
ptr = KeyTypeHandler::Read(ptr, ctx, key);
if (!Derived::ValidateKey(key)) return nullptr;
} else if (tag == kValueTag) {
auto* value = mutable_value();
ptr = ValueTypeHandler::Read(ptr, ctx, value);
if (!Derived::ValidateValue(value)) return nullptr;
} else {
if (tag == 0 || WireFormatLite::GetTagWireType(tag) ==
WireFormatLite::WIRETYPE_END_GROUP) {
ctx->SetLastTag(tag);
return ptr;
}
ptr = UnknownFieldParse(tag, static_cast<std::string*>(nullptr), ptr,
ctx);
}
GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
}
return ptr;
}
Message* New(Arena* arena) const final {
return Arena::CreateMessage<Derived>(arena);
}
protected:
friend class google::protobuf::Arena;
template <typename C, typename K, typename V, WireFormatLite::FieldType,
WireFormatLite::FieldType>
friend class MapField;
HasBits<1> _has_bits_{};
mutable CachedSize _cached_size_{};

@ -84,10 +84,6 @@ class MapTypeHandler<WireFormatLite::TYPE_MESSAGE, Type> {
// Functions used in parsing and serialization. ===================
static inline size_t ByteSize(const MapEntryAccessorType& value);
static inline int GetCachedSize(const MapEntryAccessorType& value);
static inline bool Read(io::CodedInputStream* input,
MapEntryAccessorType* value);
static inline const char* Read(const char* ptr, ParseContext* ctx,
MapEntryAccessorType* value);
static inline uint8_t* Write(int field, const MapEntryAccessorType& value,
uint8_t* ptr, io::EpsCopyOutputStream* stream);
@ -95,8 +91,6 @@ class MapTypeHandler<WireFormatLite::TYPE_MESSAGE, Type> {
// Functions to manipulate data on memory. ========================
static inline void DeleteNoArena(const Type* x);
static constexpr TypeOnMemory Constinit();
static inline Type* EnsureMutable(Type** value, Arena* arena);
};
#define MAP_HANDLER(FieldType) \
@ -113,18 +107,12 @@ class MapTypeHandler<WireFormatLite::TYPE_MESSAGE, Type> {
Type>::kWireType; \
static inline int ByteSize(const MapEntryAccessorType& value); \
static inline int GetCachedSize(const MapEntryAccessorType& value); \
static inline bool Read(io::CodedInputStream* input, \
MapEntryAccessorType* value); \
static inline const char* Read(const char* begin, ParseContext* ctx, \
MapEntryAccessorType* value); \
static inline uint8_t* Write(int field, const MapEntryAccessorType& value, \
uint8_t* ptr, \
io::EpsCopyOutputStream* stream); \
static inline void DeleteNoArena(const TypeOnMemory& x); \
static void DeleteNoArena(TypeOnMemory& value); \
static constexpr TypeOnMemory Constinit(); \
static inline MapEntryAccessorType* EnsureMutable(TypeOnMemory* value, \
Arena* arena); \
};
MAP_HANDLER(STRING)
MAP_HANDLER(BYTES)
@ -281,132 +269,6 @@ WRITE_METHOD(BOOL, Bool)
#undef WRITE_METHOD
template <typename Type>
inline bool MapTypeHandler<WireFormatLite::TYPE_MESSAGE, Type>::Read(
io::CodedInputStream* input, MapEntryAccessorType* value) {
return WireFormatLite::ReadMessageNoVirtual(input, value);
}
template <typename Type>
inline bool MapTypeHandler<WireFormatLite::TYPE_STRING, Type>::Read(
io::CodedInputStream* input, MapEntryAccessorType* value) {
return WireFormatLite::ReadString(input, value);
}
template <typename Type>
inline bool MapTypeHandler<WireFormatLite::TYPE_BYTES, Type>::Read(
io::CodedInputStream* input, MapEntryAccessorType* value) {
return WireFormatLite::ReadBytes(input, value);
}
template <typename Type>
const char* MapTypeHandler<WireFormatLite::TYPE_MESSAGE, Type>::Read(
const char* ptr, ParseContext* ctx, MapEntryAccessorType* value) {
return ctx->ParseMessage(value, ptr);
}
template <typename Type>
const char* MapTypeHandler<WireFormatLite::TYPE_STRING, Type>::Read(
const char* ptr, ParseContext* ctx, MapEntryAccessorType* value) {
int size = ReadSize(&ptr);
GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
return ctx->ReadString(ptr, size, value);
}
template <typename Type>
const char* MapTypeHandler<WireFormatLite::TYPE_BYTES, Type>::Read(
const char* ptr, ParseContext* ctx, MapEntryAccessorType* value) {
int size = ReadSize(&ptr);
GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
return ctx->ReadString(ptr, size, value);
}
inline const char* ReadINT64(const char* ptr, int64_t* value) {
return VarintParse(ptr, reinterpret_cast<uint64_t*>(value));
}
inline const char* ReadUINT64(const char* ptr, uint64_t* value) {
return VarintParse(ptr, value);
}
inline const char* ReadINT32(const char* ptr, int32_t* value) {
return VarintParse(ptr, reinterpret_cast<uint32_t*>(value));
}
inline const char* ReadUINT32(const char* ptr, uint32_t* value) {
return VarintParse(ptr, value);
}
inline const char* ReadSINT64(const char* ptr, int64_t* value) {
*value = ReadVarintZigZag64(&ptr);
return ptr;
}
inline const char* ReadSINT32(const char* ptr, int32_t* value) {
*value = ReadVarintZigZag32(&ptr);
return ptr;
}
template <typename E>
inline const char* ReadENUM(const char* ptr, E* value) {
*value = static_cast<E>(ReadVarint32(&ptr));
return ptr;
}
inline const char* ReadBOOL(const char* ptr, bool* value) {
*value = static_cast<bool>(ReadVarint64(&ptr));
return ptr;
}
template <typename F>
inline const char* ReadUnaligned(const char* ptr, F* value) {
*value = UnalignedLoad<F>(ptr);
return ptr + sizeof(F);
}
inline const char* ReadFLOAT(const char* ptr, float* value) {
return ReadUnaligned(ptr, value);
}
inline const char* ReadDOUBLE(const char* ptr, double* value) {
return ReadUnaligned(ptr, value);
}
inline const char* ReadFIXED64(const char* ptr, uint64_t* value) {
return ReadUnaligned(ptr, value);
}
inline const char* ReadFIXED32(const char* ptr, uint32_t* value) {
return ReadUnaligned(ptr, value);
}
inline const char* ReadSFIXED64(const char* ptr, int64_t* value) {
return ReadUnaligned(ptr, value);
}
inline const char* ReadSFIXED32(const char* ptr, int32_t* value) {
return ReadUnaligned(ptr, value);
}
#define READ_METHOD(FieldType) \
template <typename Type> \
inline bool MapTypeHandler<WireFormatLite::TYPE_##FieldType, Type>::Read( \
io::CodedInputStream* input, MapEntryAccessorType* value) { \
return WireFormatLite::ReadPrimitive<TypeOnMemory, \
WireFormatLite::TYPE_##FieldType>( \
input, value); \
} \
template <typename Type> \
const char* MapTypeHandler<WireFormatLite::TYPE_##FieldType, Type>::Read( \
const char* begin, ParseContext* ctx, MapEntryAccessorType* value) { \
(void)ctx; \
return Read##FieldType(begin, value); \
}
READ_METHOD(INT64)
READ_METHOD(UINT64)
READ_METHOD(INT32)
READ_METHOD(UINT32)
READ_METHOD(SINT64)
READ_METHOD(SINT32)
READ_METHOD(ENUM)
READ_METHOD(DOUBLE)
READ_METHOD(FLOAT)
READ_METHOD(FIXED64)
READ_METHOD(FIXED32)
READ_METHOD(SFIXED64)
READ_METHOD(SFIXED32)
READ_METHOD(BOOL)
#undef READ_METHOD
// Definition for message handler
template <typename Type>
@ -421,15 +283,6 @@ constexpr auto MapTypeHandler<WireFormatLite::TYPE_MESSAGE, Type>::Constinit()
return nullptr;
}
template <typename Type>
inline Type* MapTypeHandler<WireFormatLite::TYPE_MESSAGE, Type>::EnsureMutable(
Type** value, Arena* arena) {
if (*value == nullptr) {
*value = Arena::CreateMessage<Type>(arena);
}
return *value;
}
// Definition for string/bytes handler
#define STRING_OR_BYTES_HANDLER_FUNCTIONS(FieldType) \
@ -444,13 +297,6 @@ inline Type* MapTypeHandler<WireFormatLite::TYPE_MESSAGE, Type>::EnsureMutable(
-> TypeOnMemory { \
return TypeOnMemory(&internal::fixed_address_empty_string, \
ConstantInitialized{}); \
} \
template <typename Type> \
inline typename MapTypeHandler<WireFormatLite::TYPE_##FieldType, \
Type>::MapEntryAccessorType* \
MapTypeHandler<WireFormatLite::TYPE_##FieldType, Type>::EnsureMutable( \
TypeOnMemory* value, Arena* arena) { \
return value->Mutable(arena); \
}
STRING_OR_BYTES_HANDLER_FUNCTIONS(STRING)
STRING_OR_BYTES_HANDLER_FUNCTIONS(BYTES)
@ -465,13 +311,6 @@ STRING_OR_BYTES_HANDLER_FUNCTIONS(BYTES)
MapTypeHandler<WireFormatLite::TYPE_##FieldType, Type>::Constinit() \
->TypeOnMemory { \
return 0; \
} \
template <typename Type> \
inline typename MapTypeHandler<WireFormatLite::TYPE_##FieldType, \
Type>::MapEntryAccessorType* \
MapTypeHandler<WireFormatLite::TYPE_##FieldType, Type>::EnsureMutable( \
TypeOnMemory* value, Arena* /* arena */) { \
return value; \
}
PRIMITIVE_HANDLER_FUNCTIONS(INT64)
PRIMITIVE_HANDLER_FUNCTIONS(UINT64)

Loading…
Cancel
Save