@@ -1048,9 +1048,9 @@ void NominalTypeDecl::addedMember(Decl *member) {
1048
1048
if (!vd)
1049
1049
return ;
1050
1050
1051
- // If we have a lookup table, add the new member to it.
1052
- auto *lookup = LookupTable. getPointer ();
1053
- if (lookup && isLookupTablePopulated () ) {
1051
+ // If we have a lookup table, add the new member to it. If not, we'll pick up
1052
+ // this member when we first create the table.
1053
+ if (auto * lookup = LookupTable ) {
1054
1054
if (hasLazyMembers ()) {
1055
1055
// If we have lazy members, only add the new member to the lookup
1056
1056
// table if we already have another member with the same name.
@@ -1064,11 +1064,6 @@ void NominalTypeDecl::addedMember(Decl *member) {
1064
1064
}
1065
1065
}
1066
1066
1067
- void NominalTypeDecl::addedExtension (ExtensionDecl *ext) {
1068
- if (hasLazyMembers ())
1069
- setLookupTablePopulated (false );
1070
- }
1071
-
1072
1067
void ExtensionDecl::addedMember (Decl *member) {
1073
1068
// If this extension has already been bound to a nominal, add the new member
1074
1069
// to the nominal's lookup table.
@@ -1133,16 +1128,15 @@ void ExtensionDecl::addedMember(Decl *member) {
1133
1128
//
1134
1129
// If the IDC list is later populated and/or an extension is added _after_
1135
1130
// MemberLookupTable is constructed (and possibly has entries in it),
1136
- // MemberLookupTable is purged and reconstructed from IDC's list .
1131
+ // MemberLookupTable is incrementally reconstituted with new members .
1137
1132
1138
1133
static bool
1139
1134
populateLookupTableEntryFromLazyIDCLoader (ASTContext &ctx,
1140
1135
MemberLookupTable &LookupTable,
1141
1136
DeclBaseName name,
1142
1137
IterableDeclContext *IDC) {
1143
- if (IDC->isLoadingLazyMembers ()) {
1144
- return false ;
1145
- }
1138
+ assert (!IDC->isLoadingLazyMembers () &&
1139
+ " Re-entrant member loading is not supported!" );
1146
1140
IDC->setLoadingLazyMembers (true );
1147
1141
auto ci = ctx.getOrCreateLazyIterableContextData (IDC,
1148
1142
/* lazyLoader=*/ nullptr );
@@ -1182,64 +1176,53 @@ populateLookupTableEntryFromExtensions(ASTContext &ctx,
1182
1176
NominalTypeDecl *nominal,
1183
1177
DeclBaseName name) {
1184
1178
for (auto e : nominal->getExtensions ()) {
1185
- if (e->wasDeserialized () || e->hasClangNode ()) {
1186
- assert (!e->hasUnparsedMembers ());
1187
- if (populateLookupTableEntryFromLazyIDCLoader (ctx, table,
1188
- name, e)) {
1189
- populateLookupTableEntryFromCurrentMembers (ctx, table, name, e);
1190
- }
1191
- } else {
1179
+ // If we can retrieve the members of this extension without deserializing
1180
+ // anything, do so now.
1181
+ if (!e->wasDeserialized () && !e->hasClangNode ()) {
1192
1182
populateLookupTableEntryFromCurrentMembers (ctx, table, name, e);
1183
+ continue ;
1193
1184
}
1194
- }
1195
- }
1196
-
1197
- bool NominalTypeDecl::isLookupTablePopulated () const {
1198
- return LookupTable.getInt ();
1199
- }
1200
1185
1201
- void NominalTypeDecl::setLookupTablePopulated (bool value) {
1202
- LookupTable.setInt (value);
1186
+ assert (!e->hasUnparsedMembers ());
1187
+ if (populateLookupTableEntryFromLazyIDCLoader (ctx, table, name, e)) {
1188
+ populateLookupTableEntryFromCurrentMembers (ctx, table, name, e);
1189
+ }
1190
+ }
1203
1191
}
1204
1192
1205
1193
void NominalTypeDecl::prepareLookupTable () {
1206
- // If we haven't allocated the lookup table yet, do so now.
1207
- if (!LookupTable. getPointer ()) {
1208
- auto &ctx = getASTContext ();
1209
- LookupTable. setPointer ( new (ctx) MemberLookupTable (ctx)) ;
1194
+ // If we have already allocated the lookup table, then there's nothing further
1195
+ // to do.
1196
+ if (LookupTable) {
1197
+ return ;
1210
1198
}
1211
1199
1200
+ // Otherwise start the first fill.
1201
+ auto &ctx = getASTContext ();
1202
+ LookupTable = new (ctx) MemberLookupTable (ctx);
1203
+
1212
1204
if (hasLazyMembers ()) {
1213
1205
assert (!hasUnparsedMembers ());
1214
1206
1215
1207
// Lazy members: if the table needs population, populate the table _only
1216
1208
// from those members already in the IDC member list_ such as implicits or
1217
1209
// globals-as-members, then update table entries from the extensions that
1218
1210
// have the same names as any such initial-population members.
1219
- if (!isLookupTablePopulated ()) {
1220
- setLookupTablePopulated (true );
1221
- LookupTable.getPointer ()->addMembers (getCurrentMembersWithoutLoading ());
1211
+ LookupTable->addMembers (getCurrentMembersWithoutLoading ());
1222
1212
1223
- llvm::SetVector<DeclBaseName> baseNamesPresent;
1224
- for (auto entry : *LookupTable.getPointer ()) {
1225
- baseNamesPresent.insert (entry.getFirst ().getBaseName ());
1226
- }
1213
+ llvm::SmallSet<DeclBaseName, 4 > baseNamesPresent;
1214
+ for (auto entry : *LookupTable) {
1215
+ auto baseName = entry.getFirst ().getBaseName ();
1216
+ if (!baseNamesPresent.insert (baseName).second )
1217
+ continue ;
1227
1218
1228
- for (auto baseName : baseNamesPresent) {
1229
- populateLookupTableEntryFromExtensions (getASTContext (),
1230
- *LookupTable.getPointer (),
1231
- this , baseName);
1232
- }
1219
+ populateLookupTableEntryFromExtensions (getASTContext (),
1220
+ *LookupTable,
1221
+ this , baseName);
1233
1222
}
1234
-
1235
1223
} else {
1236
- // No lazy members: if the table needs population, populate the table
1237
- // en-masse; and in either case update the extensions.
1238
- if (!isLookupTablePopulated ()) {
1239
- setLookupTablePopulated (true );
1240
- LookupTable.getPointer ()->addMembers (getMembers ());
1241
- }
1242
- LookupTable.getPointer ()->updateLookupTable (this );
1224
+ LookupTable->addMembers (getMembers ());
1225
+ LookupTable->updateLookupTable (this );
1243
1226
}
1244
1227
}
1245
1228
@@ -1265,96 +1248,82 @@ maybeFilterOutAttrImplements(TinyPtrVector<ValueDecl *> decls,
1265
1248
return result;
1266
1249
}
1267
1250
1268
- TinyPtrVector<ValueDecl *> NominalTypeDecl::lookupDirect (
1269
- DeclName name,
1270
- OptionSet<LookupDirectFlags> flags) {
1251
+ TinyPtrVector<ValueDecl *>
1252
+ NominalTypeDecl::lookupDirect ( DeclName name,
1253
+ OptionSet<LookupDirectFlags> flags) {
1271
1254
ASTContext &ctx = getASTContext ();
1272
1255
if (auto s = ctx.Stats ) {
1273
1256
++s->getFrontendCounters ().NominalTypeLookupDirectCount ;
1274
1257
}
1275
1258
1276
1259
// We only use NamedLazyMemberLoading when a user opts-in and we have
1277
1260
// not yet loaded all the members into the IDC list in the first place.
1278
- bool useNamedLazyMemberLoading = (ctx.LangOpts .NamedLazyMemberLoading &&
1279
- hasLazyMembers ());
1261
+ const bool useNamedLazyMemberLoading = (ctx.LangOpts .NamedLazyMemberLoading &&
1262
+ hasLazyMembers ());
1280
1263
1281
- bool includeAttrImplements =
1264
+ const bool includeAttrImplements =
1282
1265
flags.contains (LookupDirectFlags::IncludeAttrImplements);
1283
1266
1284
1267
LLVM_DEBUG (llvm::dbgs () << getNameStr () << " .lookupDirect("
1285
- << name << " )"
1286
- << " , isLookupTablePopulated()=" << isLookupTablePopulated ()
1287
- << " , hasLazyMembers()=" << hasLazyMembers ()
1288
- << " , useNamedLazyMemberLoading=" << useNamedLazyMemberLoading
1289
- << " \n " );
1290
-
1291
- // We check the LookupTable at most twice, possibly treating a miss in the
1292
- // first try as a cache-miss that we then do a cache-fill on, and retry.
1293
- for (int i = 0 ; i < 2 ; ++i) {
1294
-
1295
- // First, if we're _not_ doing NamedLazyMemberLoading, we make sure we've
1296
- // populated the IDC and brought it up to date with any extensions. This
1297
- // will flip the hasLazyMembers() flag to false as well.
1298
- if (!useNamedLazyMemberLoading) {
1299
- // It's possible that the lookup table exists but has information in it
1300
- // that is either currently out of date or soon to be out of date.
1301
- // This can happen two ways:
1302
- //
1303
- // - We've not yet indexed the members we have (isLookupTablePopulated()
1304
- // is zero).
1305
- //
1306
- // - We've still got more lazy members left to load; this can happen
1307
- // even if we _did_ index some members.
1308
- //
1309
- // In either of these cases, we want to reset the table to empty and
1310
- // mark it as needing reconstruction.
1311
- if (LookupTable.getPointer () &&
1312
- (hasLazyMembers () || !isLookupTablePopulated ())) {
1313
- LookupTable.getPointer ()->clear ();
1314
- setLookupTablePopulated (false );
1315
- }
1316
-
1317
- (void )getMembers ();
1268
+ << name << " )"
1269
+ << " , hasLazyMembers()=" << hasLazyMembers ()
1270
+ << " , useNamedLazyMemberLoading=" << useNamedLazyMemberLoading
1271
+ << " \n " );
1318
1272
1319
- // Make sure we have the complete list of members (in this nominal and in
1320
- // all extensions).
1321
- for (auto E : getExtensions ())
1322
- (void )E->getMembers ();
1323
- }
1324
1273
1325
- // Next, in all cases, prepare the lookup table for use, possibly
1326
- // repopulating it from the IDC if the IDC member list has just grown.
1327
- prepareLookupTable ();
1274
+ prepareLookupTable ();
1328
1275
1276
+ auto tryCacheLookup =
1277
+ [=](MemberLookupTable *table,
1278
+ DeclName name) -> Optional<TinyPtrVector<ValueDecl *>> {
1329
1279
// Look for a declaration with this name.
1330
- auto known = LookupTable.getPointer ()->find (name);
1280
+ auto known = table->find (name);
1281
+ if (known == table->end ())
1282
+ return None;
1331
1283
1332
1284
// We found something; return it.
1333
- if (known != LookupTable. getPointer ()-> end ())
1334
- return maybeFilterOutAttrImplements (known-> second , name,
1335
- includeAttrImplements) ;
1285
+ return maybeFilterOutAttrImplements (known-> second , name,
1286
+ includeAttrImplements);
1287
+ } ;
1336
1288
1337
- // If we have no more second chances, stop now.
1338
- if (!useNamedLazyMemberLoading || i > 0 )
1339
- break ;
1289
+ auto updateLookupTable = [this ](MemberLookupTable *table) {
1290
+ // Make sure we have the complete list of members (in this nominal and in
1291
+ // all extensions).
1292
+ (void )getMembers ();
1340
1293
1341
- // If we get here, we had a cache-miss and _are_ using
1342
- // NamedLazyMemberLoading. Try to populate a _single_ entry in the
1343
- // MemberLookupTable from both this nominal and all of its extensions, and
1344
- // retry. Any failure to load here flips the useNamedLazyMemberLoading to
1345
- // false, and we fall back to loading all members during the retry.
1346
- auto &Table = *LookupTable.getPointer ();
1347
- if (populateLookupTableEntryFromLazyIDCLoader (ctx, Table,
1348
- name.getBaseName (), this )) {
1349
- useNamedLazyMemberLoading = false ;
1350
- } else {
1351
- populateLookupTableEntryFromExtensions (ctx, Table, this ,
1352
- name.getBaseName ());
1353
- }
1294
+ for (auto E : getExtensions ())
1295
+ (void )E->getMembers ();
1296
+
1297
+ LookupTable->updateLookupTable (this );
1298
+ };
1299
+
1300
+ if (!useNamedLazyMemberLoading) {
1301
+ updateLookupTable (LookupTable);
1354
1302
}
1355
1303
1356
- // None of our attempts found anything.
1357
- return { };
1304
+ // Look for a declaration with this name.
1305
+ if (auto lookup = tryCacheLookup (LookupTable, name))
1306
+ return lookup.getValue ();
1307
+
1308
+ if (!useNamedLazyMemberLoading) {
1309
+ return { };
1310
+ }
1311
+
1312
+ // If we get here, we had a cache-miss and _are_ using
1313
+ // NamedLazyMemberLoading. Try to populate a _single_ entry in the
1314
+ // MemberLookupTable from both this nominal and all of its extensions, and
1315
+ // retry.
1316
+ auto &Table = *LookupTable;
1317
+ if (populateLookupTableEntryFromLazyIDCLoader (ctx, Table,
1318
+ name.getBaseName (), this )) {
1319
+ updateLookupTable (LookupTable);
1320
+ } else {
1321
+ populateLookupTableEntryFromExtensions (ctx, Table, this ,
1322
+ name.getBaseName ());
1323
+ }
1324
+
1325
+ return tryCacheLookup (LookupTable, name)
1326
+ .getValueOr (TinyPtrVector<ValueDecl *>());
1358
1327
}
1359
1328
1360
1329
void ClassDecl::createObjCMethodLookup () {
0 commit comments