Skip to content

Commit

Permalink
[meta] Add TClass::GetListOfUsingDataMembers():
Browse files Browse the repository at this point in the history
To allow e.g. PyROOT to iterate over all members including those pulled in
through using decls, and to include namespace members pulled into the
global scope through using decls, introduce iteration of members-through-
using-decls. TClass splits these two explictly:

    TClass::GetListOfDataMembers() // no using decls
    TClass::GetListOfUsingDataMembers() // only using decls

to prevent the I/O from getting confused by using decls (that do not need to
be streamed as part of the class containing the using decls).

TGlobal now contains a combination of both.

Still to come: teach PyROOT to do lookup in both TClass lists.
  • Loading branch information
Axel-Naumann committed Oct 7, 2020
1 parent bd3bd87 commit f3f0f13
Show file tree
Hide file tree
Showing 11 changed files with 123 additions and 61 deletions.
2 changes: 1 addition & 1 deletion core/base/src/TROOT.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -1729,7 +1729,7 @@ TCollection *TROOT::GetListOfFunctionTemplates()
TCollection *TROOT::GetListOfGlobals(Bool_t load)
{
if (!fGlobals) {
fGlobals = new TListOfDataMembers(0);
fGlobals = new TListOfDataMembers(nullptr, TDictionary::EMemberSelection::kAlsoUsingDecls);
// We add to the list the "funcky-fake" globals.

// provide special functor for gROOT, while ROOT::GetROOT() does not return reference
Expand Down
7 changes: 6 additions & 1 deletion core/meta/inc/TClass.h
Original file line number Diff line number Diff line change
Expand Up @@ -179,7 +179,8 @@ friend class ROOT::Internal::TCheckHashRecursiveRemoveConsistency;
mutable ConvSIMap_t fConversionStreamerInfo; //Array of the streamer infos derived from another class.
TList *fRealData; //linked list for persistent members including base classes
std::atomic<TList*> fBase; //linked list for base classes
TListOfDataMembers *fData; //linked list for data members
std::atomic<TListOfDataMembers*> fData; //linked list for data members; non-owning.
std::atomic<TListOfDataMembers*> fUsingData;//linked list for data members pulled in through using decls.

std::atomic<TListOfEnums*> fEnums; //linked list for the enums
TListOfFunctionTemplates *fFuncTemplate; //linked list for function templates [Not public until implemented as active list]
Expand Down Expand Up @@ -312,6 +313,9 @@ friend class ROOT::Internal::TCheckHashRecursiveRemoveConsistency;
TClass(const TClass& tc) = delete;
TClass& operator=(const TClass&) = delete;

bool IsClassStructOrUnion() const { return Property() & (kIsClass|kIsStruct|kIsUnion); }
TList *CreateListOfDataMembers(std::atomic<TListOfDataMembers*> &data, TDictionary::EMemberSelection selection, bool load);

protected:
TVirtualStreamerInfo *FindStreamerInfo(TObjArray *arr, UInt_t checksum) const;
void GetMissingDictionariesForBaseClasses(TCollection &result, TCollection &visited, bool recurse);
Expand Down Expand Up @@ -401,6 +405,7 @@ friend class ROOT::Internal::TCheckHashRecursiveRemoveConsistency;
TVirtualStreamerInfo *GetLastReadInfo() const { return fLastReadInfo; }
void SetLastReadInfo(TVirtualStreamerInfo *info) { fLastReadInfo = info; }
TList *GetListOfDataMembers(Bool_t load = kTRUE);
TList *GetListOfUsingDataMembers(Bool_t load = kTRUE);
TList *GetListOfEnums(Bool_t load = kTRUE);
TList *GetListOfFunctionTemplates(Bool_t load = kTRUE);
TList *GetListOfBases();
Expand Down
9 changes: 9 additions & 0 deletions core/meta/inc/TDictionary.h
Original file line number Diff line number Diff line change
Expand Up @@ -210,6 +210,15 @@ class TDictionary : public TNamed {
kBitset = ROOT::kSTLbitset
};

/// Kinds of members to include in lists.
enum class EMemberSelection {
kNoUsingDecls,
kOnlyUsingDecls,
kAlsoUsingDecls
};
static bool WantsRegularMembers(EMemberSelection sel) { return sel != EMemberSelection::kOnlyUsingDecls; }
static bool WantsUsingDecls(EMemberSelection sel) { return sel != EMemberSelection::kNoUsingDecls; }

typedef const void *DeclId_t;
ClassDef(TDictionary,2) //Interface to dictionary
};
Expand Down
2 changes: 1 addition & 1 deletion core/meta/inc/TInterpreter.h
Original file line number Diff line number Diff line change
Expand Up @@ -454,7 +454,7 @@ class TInterpreter : public TNamed {
// DataMemberInfo interface
virtual int DataMemberInfo_ArrayDim(DataMemberInfo_t * /* dminfo */) const {return 0;}
virtual void DataMemberInfo_Delete(DataMemberInfo_t * /* dminfo */) const {;}
virtual DataMemberInfo_t *DataMemberInfo_Factory(ClassInfo_t * /* clinfo */ = 0) const {return 0;}
virtual DataMemberInfo_t *DataMemberInfo_Factory(ClassInfo_t * /* clinfo */, TDictionary::EMemberSelection /*selection*/) const {return 0;}
virtual DataMemberInfo_t *DataMemberInfo_Factory(DeclId_t declid, ClassInfo_t* clinfo) const = 0;
virtual DataMemberInfo_t *DataMemberInfo_FactoryCopy(DataMemberInfo_t * /* dminfo */) const {return 0;}
virtual Bool_t DataMemberInfo_IsValid(DataMemberInfo_t * /* dminfo */) const {return 0;}
Expand Down
22 changes: 13 additions & 9 deletions core/meta/inc/TListOfDataMembers.h
Original file line number Diff line number Diff line change
Expand Up @@ -32,12 +32,13 @@ class TDataMember;
class TListOfDataMembers : public THashList
{
private:
TClass *fClass; //! Context of this list. Not owned.
TClass *fClass = nullptr; //! Context of this list. Not owned.

TExMap *fIds; //! Map from DeclId_t to TDataMember*
THashList *fUnloaded; //! Holder of TDataMember for unloaded DataMembers.
Bool_t fIsLoaded; //! Mark whether Load was executed.
ULong64_t fLastLoadMarker; //! Represent interpreter state when we last did a full load.
TExMap *fIds = nullptr; //! Map from DeclId_t to TDataMember*
THashList *fUnloaded = nullptr; //! Holder of TDataMember for unloaded DataMembers.
ULong64_t fLastLoadMarker = 0; //! Represent interpreter state when we last did a full load.
Bool_t fIsLoaded = kFALSE; //! Mark whether Load was executed.
TDictionary::EMemberSelection fSelection = TDictionary::EMemberSelection::kNoUsingDecls; //! Whether the list should contain regular data members or only using decls or both.

TListOfDataMembers(const TListOfDataMembers&) = delete;
TListOfDataMembers& operator=(const TListOfDataMembers&) = delete;
Expand All @@ -48,12 +49,15 @@ class TListOfDataMembers : public THashList
public:
typedef TDictionary::DeclId_t DeclId_t;

TListOfDataMembers(TClass *cl = 0);
// construct from a generic collection of data members objects
/// Constructor, possibly for all members of a class (or globals).
/// Include (or not) the scope's using declarations of variables.
TListOfDataMembers(TClass *cl, TDictionary::EMemberSelection selection):
fClass(cl), fSelection(selection) {}

/// Construct from a generic collection of data members objects
template<class DataMemberList>
TListOfDataMembers(DataMemberList & dmlist) :
fClass(0),fIds(0),fUnloaded(0),
fIsLoaded(kTRUE), fLastLoadMarker(0)
fIsLoaded(kTRUE)
{
for (auto * dataMember : dmlist)
Add(dataMember);
Expand Down
86 changes: 61 additions & 25 deletions core/meta/src/TClass.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -911,7 +911,7 @@ void TAutoInspector::Inspect(TClass *cl, const char *tit, const char *name,
if (!classInfo) return;

// Browse data members
DataMemberInfo_t *m = gCling->DataMemberInfo_Factory(classInfo);
DataMemberInfo_t *m = gCling->DataMemberInfo_Factory(classInfo, TDictionary::EMemberSelection::kNoUsingDecls);
TString mname;

int found=0;
Expand Down Expand Up @@ -1039,7 +1039,7 @@ TClass::TClass() :
TDictionary(),
fPersistentRef(0),
fStreamerInfo(0), fConversionStreamerInfo(0), fRealData(0),
fBase(0), fData(0), fEnums(0), fFuncTemplate(0), fMethod(0), fAllPubData(0),
fBase(0), fData(0), fUsingData(0), fEnums(0), fFuncTemplate(0), fMethod(0), fAllPubData(0),
fAllPubMethod(0), fClassMenuList(0),
fDeclFileName(""), fImplFileName(""), fDeclFileLine(0), fImplFileLine(0),
fInstanceCount(0), fOnHeap(0),
Expand Down Expand Up @@ -1077,7 +1077,7 @@ TClass::TClass(const char *name, Bool_t silent) :
TDictionary(name),
fPersistentRef(0),
fStreamerInfo(0), fConversionStreamerInfo(0), fRealData(0),
fBase(0), fData(0), fEnums(0), fFuncTemplate(0), fMethod(0), fAllPubData(0),
fBase(0), fData(0), fUsingData(0), fEnums(0), fFuncTemplate(0), fMethod(0), fAllPubData(0),
fAllPubMethod(0), fClassMenuList(0),
fDeclFileName(""), fImplFileName(""), fDeclFileLine(0), fImplFileLine(0),
fInstanceCount(0), fOnHeap(0),
Expand Down Expand Up @@ -1124,7 +1124,7 @@ TClass::TClass(const char *name, Version_t cversion, Bool_t silent) :
TDictionary(name),
fPersistentRef(0),
fStreamerInfo(0), fConversionStreamerInfo(0), fRealData(0),
fBase(0), fData(0), fEnums(0), fFuncTemplate(0), fMethod(0), fAllPubData(0),
fBase(0), fData(0), fUsingData(0), fEnums(0), fFuncTemplate(0), fMethod(0), fAllPubData(0),
fAllPubMethod(0), fClassMenuList(0),
fDeclFileName(""), fImplFileName(""), fDeclFileLine(0), fImplFileLine(0),
fInstanceCount(0), fOnHeap(0),
Expand All @@ -1151,7 +1151,7 @@ TClass::TClass(const char *name, Version_t cversion, EState theState, Bool_t sil
TDictionary(name),
fPersistentRef(0),
fStreamerInfo(0), fConversionStreamerInfo(0), fRealData(0),
fBase(0), fData(0), fEnums(0), fFuncTemplate(0), fMethod(0), fAllPubData(0),
fBase(0), fData(0), fUsingData(0), fEnums(0), fFuncTemplate(0), fMethod(0), fAllPubData(0),
fAllPubMethod(0), fClassMenuList(0),
fDeclFileName(""), fImplFileName(""), fDeclFileLine(0), fImplFileLine(0),
fInstanceCount(0), fOnHeap(0),
Expand Down Expand Up @@ -1195,7 +1195,7 @@ TClass::TClass(ClassInfo_t *classInfo, Version_t cversion,
TDictionary(""),
fPersistentRef(0),
fStreamerInfo(0), fConversionStreamerInfo(0), fRealData(0),
fBase(0), fData(0), fEnums(0), fFuncTemplate(0), fMethod(0), fAllPubData(0),
fBase(0), fData(0), fUsingData(0), fEnums(0), fFuncTemplate(0), fMethod(0), fAllPubData(0),
fAllPubMethod(0), fClassMenuList(0),
fDeclFileName(""), fImplFileName(""), fDeclFileLine(0), fImplFileLine(0),
fInstanceCount(0), fOnHeap(0),
Expand Down Expand Up @@ -1245,7 +1245,7 @@ TClass::TClass(const char *name, Version_t cversion,
TDictionary(name),
fPersistentRef(0),
fStreamerInfo(0), fConversionStreamerInfo(0), fRealData(0),
fBase(0), fData(0), fEnums(0), fFuncTemplate(0), fMethod(0), fAllPubData(0),
fBase(0), fData(0), fUsingData(0), fEnums(0), fFuncTemplate(0), fMethod(0), fAllPubData(0),
fAllPubMethod(0), fClassMenuList(0),
fDeclFileName(""), fImplFileName(""), fDeclFileLine(0), fImplFileLine(0),
fInstanceCount(0), fOnHeap(0),
Expand Down Expand Up @@ -1275,7 +1275,7 @@ TClass::TClass(const char *name, Version_t cversion,
TDictionary(name),
fPersistentRef(0),
fStreamerInfo(0), fConversionStreamerInfo(0), fRealData(0),
fBase(0), fData(0), fEnums(0), fFuncTemplate(0), fMethod(0), fAllPubData(0),
fBase(0), fData(0), fUsingData(0), fEnums(0), fFuncTemplate(0), fMethod(0), fAllPubData(0),
fAllPubMethod(0),
fClassMenuList(0),
fDeclFileName(""), fImplFileName(""), fDeclFileLine(0), fImplFileLine(0),
Expand Down Expand Up @@ -1640,9 +1640,13 @@ TClass::~TClass()
(*fBase).Delete();
delete fBase.load(); fBase = 0;

if (fData)
fData->Delete();
delete fData; fData = 0;
if (fData.load())
(*fData).Delete();
delete fData.load(); fData = 0;

if (fUsingData.load())
(*fUsingData).Delete();
delete fUsingData.load(); fUsingData = 0;

if (fEnums.load())
(*fEnums).Delete();
Expand Down Expand Up @@ -3317,7 +3321,7 @@ DictFuncPtr_t TClass::GetDict (const std::type_info& info)

TDataMember *TClass::GetDataMember(const char *datamember) const
{
if ((!(fData && fData->IsLoaded()) && !HasInterpreterInfo())
if ((!(fData.load() && (*fData).IsLoaded()) && !HasInterpreterInfo())
|| datamember == 0) return 0;

// Strip off leading *'s and trailing [
Expand Down Expand Up @@ -3660,13 +3664,14 @@ TList *TClass::GetListOfEnums(Bool_t requestListLoading /* = kTRUE */)
}

////////////////////////////////////////////////////////////////////////////////
/// Return list containing the TDataMembers of a class.
/// Create the list containing the TDataMembers (of actual data members or members
/// pulled in through using declarations) of a class.

TList *TClass::GetListOfDataMembers(Bool_t load /* = kTRUE */)
TList *TClass::CreateListOfDataMembers(std::atomic<TListOfDataMembers*> &data, TDictionary::EMemberSelection selection, bool load)
{
R__LOCKGUARD(gInterpreterMutex);

if (!fData) {
if (!data) {
if (fCanLoadClassInfo && fState == kHasTClassInit) {
// NOTE: Add test to prevent redo if another thread has already done the work.
// if (!fHasRootPcmInfo) {
Expand All @@ -3678,20 +3683,46 @@ TList *TClass::GetListOfDataMembers(Bool_t load /* = kTRUE */)
// R__ASSERT(kFALSE);

fHasRootPcmInfo = kTRUE;
return fData;
return data;
}
}
fData = new TListOfDataMembers(this);

data = new TListOfDataMembers(this, selection);
}
if (Property() & (kIsClass|kIsStruct|kIsUnion)) {
if (IsClassStructOrUnion()) {
// If the we have a class or struct or union, the order
// of data members is the list is essential since it determines their
// order on file. So we must always load. Also, the list is fixed
// since the language does not allow to add members.
if (!fData->IsLoaded()) fData->Load();
if (!(*data).IsLoaded())
(*data).Load();

} else if (load) fData->Load();
return fData;
} else if (load) (*data).Load();
return data;
}

////////////////////////////////////////////////////////////////////////////////
/// Return list containing the TDataMembers of a class.

TList *TClass::GetListOfDataMembers(Bool_t load /* = kTRUE */)
{
// Fast path, no lock? Classes load at creation time.
if ((!load || IsClassStructOrUnion()) && fData)
return fData;

return CreateListOfDataMembers(fData, TDictionary::EMemberSelection::kNoUsingDecls, load);
}

////////////////////////////////////////////////////////////////////////////////
/// Return list containing the TDataMembers of using declarations of a class.

TList *TClass::GetListOfUsingDataMembers(Bool_t load /* = kTRUE */)
{
// Fast path, no lock? Classes load at creation time.
if ((!load || IsClassStructOrUnion()) && fUsingData)
return fUsingData;

return CreateListOfDataMembers(fUsingData, TDictionary::EMemberSelection::kOnlyUsingDecls, load);
}

////////////////////////////////////////////////////////////////////////////////
Expand Down Expand Up @@ -4124,8 +4155,10 @@ void TClass::ResetCaches()
R__ASSERT(!TestBit(kLoading) && "Resetting the caches does not make sense during loading!" );

// Not owning lists, don't call Delete(), but unload
if (fData)
fData->Unload();
if (fData.load())
(*fData).Unload();
if (fUsingData.load())
(*fUsingData).Unload();
if (fEnums.load())
(*fEnums).Unload();
if (fMethod.load())
Expand Down Expand Up @@ -6108,8 +6141,11 @@ void TClass::SetUnloaded()
if (fMethod.load()) {
(*fMethod).Unload();
}
if (fData) {
fData->Unload();
if (fData.load()) {
(*fData).Unload();
}
if (fUsingData.load()) {
(*fUsingData).Unload();
}
if (fEnums.load()) {
(*fEnums).Unload();
Expand Down
10 changes: 1 addition & 9 deletions core/meta/src/TListOfDataMembers.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -33,14 +33,6 @@ const unsigned int idsSize=19;

ClassImp(TListOfDataMembers);

////////////////////////////////////////////////////////////////////////////////
/// Constructor.

TListOfDataMembers::TListOfDataMembers(TClass *cl /*=0*/) :
fClass(cl),fIds(0),fUnloaded(0),fIsLoaded(kFALSE), fLastLoadMarker(0)
{
}

////////////////////////////////////////////////////////////////////////////////
/// Destructor.

Expand Down Expand Up @@ -474,7 +466,7 @@ void TListOfDataMembers::Load()
}

// Now we follow the ordinary pattern
DataMemberInfo_t *t = gInterpreter->DataMemberInfo_Factory(info);
DataMemberInfo_t *t = gInterpreter->DataMemberInfo_Factory(info, fSelection);
while (gInterpreter->DataMemberInfo_Next(t)) {
if (gInterpreter->DataMemberInfo_IsValid(t)) {
// Get will check if there is already there or create a new one
Expand Down
6 changes: 3 additions & 3 deletions core/metacling/src/TCling.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -6019,7 +6019,7 @@ Int_t TCling::DeepAutoLoadImpl(const char *cls)
if (classinfo && gInterpreter->ClassInfo_IsValid(classinfo)
&& !(gInterpreter->ClassInfo_Property(classinfo) & kIsEnum))
{
DataMemberInfo_t *memberinfo = gInterpreter->DataMemberInfo_Factory(classinfo);
DataMemberInfo_t *memberinfo = gInterpreter->DataMemberInfo_Factory(classinfo, TDictionary::EMemberSelection::kNoUsingDecls);
while (gInterpreter->DataMemberInfo_Next(memberinfo)) {
auto membertypename = TClassEdit::GetLong64_Name(gInterpreter->TypeName(gInterpreter->DataMemberInfo_TypeTrueName(memberinfo)));
if (!(gInterpreter->DataMemberInfo_TypeProperty(memberinfo) & ::kIsFundamental)
Expand Down Expand Up @@ -8431,11 +8431,11 @@ void TCling::DataMemberInfo_Delete(DataMemberInfo_t* dminfo) const

////////////////////////////////////////////////////////////////////////////////

DataMemberInfo_t* TCling::DataMemberInfo_Factory(ClassInfo_t* clinfo /*= 0*/) const
DataMemberInfo_t* TCling::DataMemberInfo_Factory(ClassInfo_t* clinfo, TDictionary::EMemberSelection selection) const
{
R__LOCKGUARD(gInterpreterMutex);
TClingClassInfo* TClingclass_info = (TClingClassInfo*) clinfo;
return (DataMemberInfo_t*) new TClingDataMemberInfo(GetInterpreterImpl(), TClingclass_info);
return (DataMemberInfo_t*) new TClingDataMemberInfo(GetInterpreterImpl(), TClingclass_info, selection);
}

////////////////////////////////////////////////////////////////////////////////
Expand Down
2 changes: 1 addition & 1 deletion core/metacling/src/TCling.h
Original file line number Diff line number Diff line change
Expand Up @@ -467,7 +467,7 @@ class TCling final : public TInterpreter {
virtual DeclId_t GetDeclId(DataMemberInfo_t *info) const;
virtual int DataMemberInfo_ArrayDim(DataMemberInfo_t* dminfo) const;
virtual void DataMemberInfo_Delete(DataMemberInfo_t* dminfo) const;
virtual DataMemberInfo_t* DataMemberInfo_Factory(ClassInfo_t* clinfo = 0) const;
virtual DataMemberInfo_t* DataMemberInfo_Factory(ClassInfo_t* clinfo, TDictionary::EMemberSelection selection) const;
virtual DataMemberInfo_t *DataMemberInfo_Factory(DeclId_t declid, ClassInfo_t* clinfo) const;
virtual DataMemberInfo_t* DataMemberInfo_FactoryCopy(DataMemberInfo_t* dminfo) const;
virtual bool DataMemberInfo_IsValid(DataMemberInfo_t* dminfo) const;
Expand Down
Loading

0 comments on commit f3f0f13

Please sign in to comment.