From eae690bb9db4b0e5f743d9880e8c0835a325df9d Mon Sep 17 00:00:00 2001 From: Dave MacLachlan Date: Mon, 8 Dec 2025 09:10:17 -0800 Subject: [PATCH] Move to using `objc_externally_retained` to elide unneeded calls to retain/release in j2objc protobuf code. I believe all of the C code that is wrapped in these blocks can assume that the objects being passed in are going to be held externally and will live for the lifetime of the call. https://clang.llvm.org/docs/AutomaticReferenceCounting.html#externally-retained-variables PiperOrigin-RevId: 841790480 --- jre_emul/Classes/J2ObjC_common.h | 12 ++++++++++++ .../google/protobuf/compiler/j2objc/j2objc_enum.cc | 2 ++ .../protobuf/compiler/j2objc/j2objc_message.cc | 2 ++ .../protobuf/compiler/j2objc/j2objc_message_lite.cc | 2 ++ .../google/protobuf/compiler/j2objc/j2objc_oneof.cc | 2 ++ 5 files changed, 20 insertions(+) diff --git a/jre_emul/Classes/J2ObjC_common.h b/jre_emul/Classes/J2ObjC_common.h index a87d79d077..bc588b6a6b 100644 --- a/jre_emul/Classes/J2ObjC_common.h +++ b/jre_emul/Classes/J2ObjC_common.h @@ -127,6 +127,18 @@ __attribute__((always_inline)) inline id JreRetainedAutoreleasedReturnValue(id v # define WEAK_ __unsafe_unretained #endif +#ifndef J2OBJC_EXTERNALLY_RETAINED +#if __has_feature(objc_arc) && __has_attribute(objc_externally_retained) +# define J2OBJC_EXTERNALLY_RETAINED __attribute__((objc_externally_retained)) +# define J2OBJC_ASSUME_EXTERNALLY_RETAINED_BEGIN _Pragma("clang attribute J2OBJC_ASSUME_EXTERNALLY_RETAINED.push(__attribute__((objc_externally_retained)), apply_to=any(function, block, objc_method))") +# define J2OBJC_ASSUME_EXTERNALLY_RETAINED_END _Pragma("clang attribute J2OBJC_ASSUME_EXTERNALLY_RETAINED.pop") +#else // __OBJC__ && objc_arc && objc_externally_retained +# define J2OBJC_EXTERNALLY_RETAINED +# define J2OBJC_ASSUME_EXTERNALLY_RETAINED_BEGIN +# define J2OBJC_ASSUME_EXTERNALLY_RETAINED_END +#endif // __OBJC__ && objc_arc && objc_externally_retained +#endif // !J2OBJC_EXTERNALLY_RETAINED + CF_EXTERN_C_BEGIN id JreThrowNullPointerException(void) __attribute__((noreturn)); diff --git a/protobuf/compiler/src/google/protobuf/compiler/j2objc/j2objc_enum.cc b/protobuf/compiler/src/google/protobuf/compiler/j2objc/j2objc_enum.cc index 91924ecb8e..efe65d1c53 100644 --- a/protobuf/compiler/src/google/protobuf/compiler/j2objc/j2objc_enum.cc +++ b/protobuf/compiler/src/google/protobuf/compiler/j2objc/j2objc_enum.cc @@ -398,6 +398,7 @@ void EnumGenerator::GenerateSource(io::Printer* printer) { "\n" "@end\n" "\n" + "J2OBJC_ASSUME_EXTERNALLY_RETAINED_BEGIN\n" "J2OBJC_CLASS_TYPE_LITERAL_SOURCE($classname$)\n" "\n" "IOSObjectArray *$classname$_values(void) {\n" @@ -471,6 +472,7 @@ void EnumGenerator::GenerateSource(io::Printer* printer) { "}\n", "classname", ClassName(descriptor_), "name", "UNRECOGNIZED"); } + printer->Print("\nJ2OBJC_ASSUME_EXTERNALLY_RETAINED_END\n"); } } // namespace j2objc diff --git a/protobuf/compiler/src/google/protobuf/compiler/j2objc/j2objc_message.cc b/protobuf/compiler/src/google/protobuf/compiler/j2objc/j2objc_message.cc index 9a0dfe69bb..952f1b9d79 100644 --- a/protobuf/compiler/src/google/protobuf/compiler/j2objc/j2objc_message.cc +++ b/protobuf/compiler/src/google/protobuf/compiler/j2objc/j2objc_message.cc @@ -518,6 +518,7 @@ void MessageGenerator::GenerateSource(io::Printer* printer) { "\n" "@end\n" "\n" + "J2OBJC_ASSUME_EXTERNALLY_RETAINED_BEGIN\n" "J2OBJC_CLASS_TYPE_LITERAL_SOURCE($classname$)\n" "\n" "$classname$ * _Nonnull $classname$_getDefaultInstance(void) {\n" @@ -575,6 +576,7 @@ void MessageGenerator::GenerateSource(io::Printer* printer) { "$classname$_descriptor_, input, registry);\n" "}\n", "classname", ClassName(descriptor_)); + printer->Print("\nJ2OBJC_ASSUME_EXTERNALLY_RETAINED_END\n"); for (int i = 0; i < descriptor_->real_oneof_decl_count(); i++) { OneofGenerator(descriptor_->oneof_decl(i)).GenerateSource(printer); diff --git a/protobuf/compiler/src/google/protobuf/compiler/j2objc/j2objc_message_lite.cc b/protobuf/compiler/src/google/protobuf/compiler/j2objc/j2objc_message_lite.cc index ce3e23cb6d..74c8ea4002 100644 --- a/protobuf/compiler/src/google/protobuf/compiler/j2objc/j2objc_message_lite.cc +++ b/protobuf/compiler/src/google/protobuf/compiler/j2objc/j2objc_message_lite.cc @@ -398,6 +398,7 @@ void MessageLiteGenerator::GenerateSource(io::Printer* printer) { "\n" "@end\n" "\n" + "J2OBJC_ASSUME_EXTERNALLY_RETAINED_BEGIN\n" "J2OBJC_CLASS_TYPE_LITERAL_SOURCE($classname$)\n" "\n" "$classname$ * _Nonnull $classname$_getDefaultInstance(void) {\n" @@ -455,6 +456,7 @@ void MessageLiteGenerator::GenerateSource(io::Printer* printer) { "$classname$_descriptor_, input, registry);\n" "}\n", "classname", ClassName(descriptor_)); + printer->Print("\nJ2OBJC_ASSUME_EXTERNALLY_RETAINED_END\n"); for (int i = 0; i < descriptor_->oneof_decl_count(); i++) { OneofGenerator(descriptor_->oneof_decl(i)).GenerateSource(printer); diff --git a/protobuf/compiler/src/google/protobuf/compiler/j2objc/j2objc_oneof.cc b/protobuf/compiler/src/google/protobuf/compiler/j2objc/j2objc_oneof.cc index 8538f8e682..a061b976d7 100644 --- a/protobuf/compiler/src/google/protobuf/compiler/j2objc/j2objc_oneof.cc +++ b/protobuf/compiler/src/google/protobuf/compiler/j2objc/j2objc_oneof.cc @@ -326,6 +326,7 @@ void OneofGenerator::GenerateSource(io::Printer* printer) { "\n" "@end\n" "\n" + "J2OBJC_ASSUME_EXTERNALLY_RETAINED_BEGIN\n" "J2OBJC_CLASS_TYPE_LITERAL_SOURCE($classname$)\n" "\n" "IOSObjectArray *$classname$_values(void) {\n" @@ -379,6 +380,7 @@ void OneofGenerator::GenerateSource(io::Printer* printer) { "classname", CaseClassName(descriptor_), "name", CaseValueName(descriptor_->field(i))); } + printer->Print("\nJ2OBJC_ASSUME_EXTERNALLY_RETAINED_END\n"); } void OneofGenerator::GenerateMessageOrBuilder(io::Printer* printer) {