Skip to content

Commit a1249c8

Browse files
committed
[ObjC] Only define metadata types if they don't already exist on the view
This eliminates a significant amount of wasted work when loading multiple images containing Objective-C from a shared cache. The time taken to load 400 images from an iOS shared cache (with an analysis hold enabled) drops from eight minutes to around six minutes.
1 parent 1efada4 commit a1249c8

File tree

1 file changed

+38
-25
lines changed

1 file changed

+38
-25
lines changed

objectivec/objc.cpp

Lines changed: 38 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
#include "objc.h"
22
#include "inttypes.h"
33
#include <optional>
4+
#include <string>
5+
#include <type_traits>
46

57
#define RELEASE_ASSERT(condition) ((condition) ? (void)0 : (std::abort(), (void)0))
68

@@ -1098,37 +1100,51 @@ void ObjCProcessor::ReadIvarList(ObjCReader* reader, ClassBase& cls, std::string
10981100
}
10991101
}
11001102

1103+
// Returns the type named `name`, creating it via `factory()` and
1104+
// defining it on the view if it does not already exist.
1105+
template <typename F>
1106+
requires (std::is_same_v<std::invoke_result_t<F>, Ref<Type>>)
1107+
std::pair<QualifiedName, Ref<Type>> DefineNamedType(
1108+
Ref<BinaryView> view, const QualifiedName& name, F&& factory)
1109+
{
1110+
auto typeID = Type::GenerateAutoTypeId("objc", name);
1111+
if (auto type = view->GetTypeById(typeID))
1112+
return {name, type};
1113+
1114+
auto type = factory();
1115+
auto definedName = view->DefineType(typeID, name, type);
1116+
return {definedName, type};
1117+
}
11011118

11021119
std::pair<QualifiedName, Ref<Type>> finalizeStructureBuilder(
1103-
Ref<BinaryView> m_data, StructureBuilder sb, std::string name)
1120+
Ref<BinaryView> m_data, StructureBuilder sb, const QualifiedName& name)
11041121
{
1105-
auto classTypeStruct = sb.Finalize();
1106-
1107-
QualifiedName classTypeName(name);
1108-
auto classTypeId = Type::GenerateAutoTypeId("objc", classTypeName);
1109-
auto classType = Type::StructureType(classTypeStruct);
1110-
auto classQualName = m_data->DefineType(classTypeId, classTypeName, classType);
1122+
return DefineNamedType(m_data, name, [&]() {
1123+
auto classTypeStruct = sb.Finalize();
1124+
return Type::StructureType(classTypeStruct);
1125+
});
1126+
}
11111127

1112-
return {classQualName, classType};
1128+
std::pair<QualifiedName, Ref<Type>> finalizeStructureBuilder(
1129+
Ref<BinaryView> m_data, StructureBuilder sb, const std::string& name)
1130+
{
1131+
return finalizeStructureBuilder(m_data, std::move(sb), QualifiedName(name));
11131132
}
11141133

11151134
std::pair<QualifiedName, Ref<Type>> finalizeEnumerationBuilder(
1116-
Ref<BinaryView> m_data, EnumerationBuilder eb, uint64_t size, QualifiedName name)
1135+
Ref<BinaryView> m_data, EnumerationBuilder eb, uint64_t size, const QualifiedName& name)
11171136
{
1118-
auto enumTypeStruct = eb.Finalize();
1119-
1120-
auto enumTypeId = Type::GenerateAutoTypeId("objc", name);
1121-
auto enumType = Type::EnumerationType(enumTypeStruct, size);
1122-
auto enumQualName = m_data->DefineType(enumTypeId, name, enumType);
1123-
1124-
return {enumQualName, enumType};
1137+
return DefineNamedType(m_data, name, [&]() {
1138+
auto enumTypeStruct = eb.Finalize();
1139+
return Type::EnumerationType(enumTypeStruct, size);
1140+
});
11251141
}
11261142

1127-
inline QualifiedName defineTypedef(Ref<BinaryView> m_data, const QualifiedName name, Ref<Type> type)
1143+
inline QualifiedName defineTypedef(Ref<BinaryView> m_data, const QualifiedName& name, Ref<Type> type)
11281144
{
1129-
auto typeID = Type::GenerateAutoTypeId("objc", name);
1130-
m_data->DefineType(typeID, name, type);
1131-
return m_data->GetTypeNameById(typeID);
1145+
return DefineNamedType(m_data, name, [&]() {
1146+
return type;
1147+
}).first;
11321148
}
11331149

11341150
void ObjCProcessor::GenerateClassTypes()
@@ -1528,11 +1544,8 @@ void ObjCProcessor::ProcessObjCData()
15281544
classBuilder.AddMember(Type::PointerType(addrSize, Type::VoidType()), "vtable");
15291545
classBuilder.AddMember(Type::PointerType(addrSize, Type::NamedType(m_data, m_typeNames.classRO)), "data");
15301546

1531-
auto classTypeStruct = classBuilder.Finalize();
1532-
auto classType = Type::StructureType(classTypeStruct);
1533-
auto classQualName = m_data->DefineType(classTypeId, classTypeName, classType);
1534-
1535-
m_typeNames.cls = classQualName;
1547+
type = finalizeStructureBuilder(m_data, classBuilder, classTypeName);
1548+
m_typeNames.cls = type.first;
15361549

15371550
StructureBuilder categoryBuilder;
15381551
categoryBuilder.AddMember(Type::PointerType(addrSize, Type::IntegerType(1, true)), "category_name");

0 commit comments

Comments
 (0)