Skip to content

Commit

Permalink
Merge pull request #147 from pcanal/v622-pairOffset
Browse files Browse the repository at this point in the history
V622 pair offset
  • Loading branch information
smuzaffar authored Nov 24, 2020
2 parents 337ccd5 + dbeece7 commit e3e9015
Show file tree
Hide file tree
Showing 9 changed files with 160 additions and 43 deletions.
33 changes: 29 additions & 4 deletions core/meta/inc/TClass.h
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,7 @@ friend void ROOT::ResetClassVersion(TClass*, const char*, Short_t);
friend class ROOT::TGenericClassInfo;
friend class TProtoClass;
friend class ROOT::Internal::TCheckHashRecursiveRemoveConsistency;
friend class TStreamerInfo;

public:
// TClass status bits
Expand Down Expand Up @@ -222,7 +223,13 @@ friend class ROOT::Internal::TCheckHashRecursiveRemoveConsistency;
ClassConvStreamerFunc_t fConvStreamerFunc; //Wrapper around this class custom conversion Streamer member function.
Int_t fSizeof; //Sizeof the class.

Int_t fCanSplit; //!Indicates whether this class can be split or not.
// Bit field
Int_t fCanSplit : 3; //!Indicates whether this class can be split or not. Values are -1, 0, 1, 2

//! Indicates whether this class represent a pair and was not created from a dictionary nor interpreter info but has
//! compiler compatible offset and size (and all the info is in the StreamerInfo per se)
Bool_t fIsSyntheticPair : 1; //!

mutable std::atomic<Long_t> fProperty; //!Property See TClass::Property() for details
mutable Long_t fClassProperty; //!C++ Property of the class (is abstract, has virtual table, etc.)

Expand Down Expand Up @@ -367,7 +374,7 @@ friend class ROOT::Internal::TCheckHashRecursiveRemoveConsistency;
TVirtualStreamerInfo *FindConversionStreamerInfo( const char* onfile_classname, UInt_t checksum ) const;
TVirtualStreamerInfo *GetConversionStreamerInfo( const TClass* onfile_cl, Int_t version ) const;
TVirtualStreamerInfo *FindConversionStreamerInfo( const TClass* onfile_cl, UInt_t checksum ) const;
Bool_t HasDataMemberInfo() const { return fHasRootPcmInfo || HasInterpreterInfo(); }
Bool_t HasDataMemberInfo() const { return fIsSyntheticPair || fHasRootPcmInfo || HasInterpreterInfo(); }
Bool_t HasDefaultConstructor(Bool_t testio = kFALSE) const;
Bool_t HasInterpreterInfoInMemory() const { return 0 != fClassInfo; }
Bool_t HasInterpreterInfo() const { return fCanLoadClassInfo || fClassInfo; }
Expand Down Expand Up @@ -479,6 +486,7 @@ friend class ROOT::Internal::TCheckHashRecursiveRemoveConsistency;
Bool_t IsLoaded() const;
Bool_t IsForeign() const;
Bool_t IsStartingWithTObject() const;
Bool_t IsSyntheticPair() const { return fIsSyntheticPair; }
Bool_t IsVersioned() const { return !( GetClassVersion()<=1 && IsForeign() ); }
Bool_t IsTObject() const;
static TClass *LoadClass(const char *requestedname, Bool_t silent);
Expand Down Expand Up @@ -535,7 +543,8 @@ friend class ROOT::Internal::TCheckHashRecursiveRemoveConsistency;
static void RemoveClass(TClass *cl);
static void RemoveClassDeclId(TDictionary::DeclId_t id);
static TClass *GetClass(const char *name, Bool_t load = kTRUE, Bool_t silent = kFALSE);
static TClass *GetClass(const std::type_info &typeinfo, Bool_t load = kTRUE, Bool_t silent = kFALSE);
static TClass *GetClass(const char *name, Bool_t load, Bool_t silent, size_t hint_pair_offset, size_t hint_pair_size);
static TClass *GetClass(const std::type_info &typeinfo, Bool_t load = kTRUE, Bool_t silent = kFALSE, size_t hint_pair_offset = 0, size_t hint_pair_size = 0);
static TClass *GetClass(ClassInfo_t *info, Bool_t load = kTRUE, Bool_t silent = kFALSE);
template<typename T>
static TClass *GetClass(Bool_t load = kTRUE, Bool_t silent = kFALSE);
Expand Down Expand Up @@ -580,10 +589,26 @@ TClass *GetClassHelper(Bool_t, Bool_t, std::true_type)
return T::Class();
}

template <typename T>
struct TClassGetClassHelper {
static TClass *GetClass(Bool_t load, Bool_t silent) {
return TClass::GetClass(typeid(T), load, silent);
}
};

template <typename F, typename S>
struct TClassGetClassHelper<std::pair<F, S> > {
static TClass *GetClass(Bool_t load, Bool_t silent) {
std::pair<F, S> *p = nullptr;
size_t hint_offset = ((char*)&(p->second)) - (char*)p;
return TClass::GetClass(typeid(std::pair<F, S>), load, silent, hint_offset, sizeof(std::pair<F,S>));
}
};

template <typename T>
TClass *GetClassHelper(Bool_t load, Bool_t silent, std::false_type)
{
return TClass::GetClass(typeid(T), load, silent);
return TClassGetClassHelper<T>::GetClass(load, silent);
}

} // namespace Internal
Expand Down
4 changes: 2 additions & 2 deletions core/meta/inc/TVirtualStreamerInfo.h
Original file line number Diff line number Diff line change
Expand Up @@ -185,8 +185,8 @@ class TVirtualStreamerInfo : public TNamed {
// provokes the creation of the corresponding TClass. This relies on the dictionary for
// std::pair<const int, int> to already exist (or the interpreter information being available)
// as it is used as a template.
virtual TVirtualStreamerInfo *GenerateInfoForPair(const std::string &pairclassname, bool silent) = 0;
virtual TVirtualStreamerInfo *GenerateInfoForPair(const std::string &firstname, const std::string &secondname, bool silent) = 0;
virtual TVirtualStreamerInfo *GenerateInfoForPair(const std::string &pairclassname, bool silent, size_t hint_pair_offset, size_t hint_pair_size) = 0;
virtual TVirtualStreamerInfo *GenerateInfoForPair(const std::string &firstname, const std::string &secondname, bool silent, size_t hint_pair_offset, size_t hint_pair_size) = 0;

virtual TVirtualCollectionProxy *GenEmulatedProxy(const char* class_name, Bool_t silent) = 0;
virtual TClassStreamer *GenEmulatedClassStreamer(const char* class_name, Bool_t silent) = 0;
Expand Down
39 changes: 27 additions & 12 deletions core/meta/src/TClass.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -1053,7 +1053,7 @@ TClass::TClass() :
fStreamer(0), fIsA(0), fGlobalIsA(0), fIsAMethod(0),
fMerge(0), fResetAfterMerge(0), fNew(0), fNewArray(0), fDelete(0), fDeleteArray(0),
fDestructor(0), fDirAutoAdd(0), fStreamerFunc(0), fConvStreamerFunc(0), fSizeof(-1),
fCanSplit(-1), fProperty(0), fClassProperty(0), fHasRootPcmInfo(kFALSE), fCanLoadClassInfo(kFALSE),
fCanSplit(-1), fIsSyntheticPair(kFALSE), fProperty(0), fClassProperty(0), fHasRootPcmInfo(kFALSE), fCanLoadClassInfo(kFALSE),
fIsOffsetStreamerSet(kFALSE), fVersionUsed(kFALSE), fRuntimeProperties(0), fOffsetStreamer(0), fStreamerType(TClass::kDefault),
fState(kNoInfo),
fCurrentInfo(0), fLastReadInfo(0), fRefProxy(0),
Expand Down Expand Up @@ -1091,7 +1091,7 @@ TClass::TClass(const char *name, Bool_t silent) :
fStreamer(0), fIsA(0), fGlobalIsA(0), fIsAMethod(0),
fMerge(0), fResetAfterMerge(0), fNew(0), fNewArray(0), fDelete(0), fDeleteArray(0),
fDestructor(0), fDirAutoAdd(0), fStreamerFunc(0), fConvStreamerFunc(0), fSizeof(-1),
fCanSplit(-1), fProperty(0), fClassProperty(0), fHasRootPcmInfo(kFALSE), fCanLoadClassInfo(kFALSE),
fCanSplit(-1), fIsSyntheticPair(kFALSE), fProperty(0), fClassProperty(0), fHasRootPcmInfo(kFALSE), fCanLoadClassInfo(kFALSE),
fIsOffsetStreamerSet(kFALSE), fVersionUsed(kFALSE), fRuntimeProperties(0), fOffsetStreamer(0), fStreamerType(TClass::kDefault),
fState(kNoInfo),
fCurrentInfo(0), fLastReadInfo(0), fRefProxy(0),
Expand Down Expand Up @@ -1138,7 +1138,7 @@ TClass::TClass(const char *name, Version_t cversion, Bool_t silent) :
fStreamer(0), fIsA(0), fGlobalIsA(0), fIsAMethod(0),
fMerge(0), fResetAfterMerge(0), fNew(0), fNewArray(0), fDelete(0), fDeleteArray(0),
fDestructor(0), fDirAutoAdd(0), fStreamerFunc(0), fConvStreamerFunc(0), fSizeof(-1),
fCanSplit(-1), fProperty(0), fClassProperty(0), fHasRootPcmInfo(kFALSE), fCanLoadClassInfo(kFALSE),
fCanSplit(-1), fIsSyntheticPair(kFALSE), fProperty(0), fClassProperty(0), fHasRootPcmInfo(kFALSE), fCanLoadClassInfo(kFALSE),
fIsOffsetStreamerSet(kFALSE), fVersionUsed(kFALSE), fRuntimeProperties(0), fOffsetStreamer(0), fStreamerType(TClass::kDefault),
fState(kNoInfo),
fCurrentInfo(0), fLastReadInfo(0), fRefProxy(0),
Expand All @@ -1165,7 +1165,7 @@ TClass::TClass(const char *name, Version_t cversion, EState theState, Bool_t sil
fStreamer(0), fIsA(0), fGlobalIsA(0), fIsAMethod(0),
fMerge(0), fResetAfterMerge(0), fNew(0), fNewArray(0), fDelete(0), fDeleteArray(0),
fDestructor(0), fDirAutoAdd(0), fStreamerFunc(0), fConvStreamerFunc(0), fSizeof(-1),
fCanSplit(-1), fProperty(0), fClassProperty(0), fHasRootPcmInfo(kFALSE), fCanLoadClassInfo(kFALSE),
fCanSplit(-1), fIsSyntheticPair(kFALSE), fProperty(0), fClassProperty(0), fHasRootPcmInfo(kFALSE), fCanLoadClassInfo(kFALSE),
fIsOffsetStreamerSet(kFALSE), fVersionUsed(kFALSE), fRuntimeProperties(0), fOffsetStreamer(0), fStreamerType(TClass::kDefault),
fState(theState),
fCurrentInfo(0), fLastReadInfo(0), fRefProxy(0),
Expand Down Expand Up @@ -1209,7 +1209,7 @@ TClass::TClass(ClassInfo_t *classInfo, Version_t cversion,
fStreamer(0), fIsA(0), fGlobalIsA(0), fIsAMethod(0),
fMerge(0), fResetAfterMerge(0), fNew(0), fNewArray(0), fDelete(0), fDeleteArray(0),
fDestructor(0), fDirAutoAdd(0), fStreamerFunc(0), fConvStreamerFunc(0), fSizeof(-1),
fCanSplit(-1), fProperty(0), fClassProperty(0), fHasRootPcmInfo(kFALSE), fCanLoadClassInfo(kFALSE),
fCanSplit(-1), fIsSyntheticPair(kFALSE), fProperty(0), fClassProperty(0), fHasRootPcmInfo(kFALSE), fCanLoadClassInfo(kFALSE),
fIsOffsetStreamerSet(kFALSE), fVersionUsed(kFALSE), fRuntimeProperties(0), fOffsetStreamer(0), fStreamerType(TClass::kDefault),
fState(kNoInfo),
fCurrentInfo(0), fLastReadInfo(0), fRefProxy(0),
Expand Down Expand Up @@ -1259,7 +1259,7 @@ TClass::TClass(const char *name, Version_t cversion,
fStreamer(0), fIsA(0), fGlobalIsA(0), fIsAMethod(0),
fMerge(0), fResetAfterMerge(0), fNew(0), fNewArray(0), fDelete(0), fDeleteArray(0),
fDestructor(0), fDirAutoAdd(0), fStreamerFunc(0), fConvStreamerFunc(0), fSizeof(-1),
fCanSplit(-1), fProperty(0), fClassProperty(0), fHasRootPcmInfo(kFALSE), fCanLoadClassInfo(kFALSE),
fCanSplit(-1), fIsSyntheticPair(kFALSE), fProperty(0), fClassProperty(0), fHasRootPcmInfo(kFALSE), fCanLoadClassInfo(kFALSE),
fIsOffsetStreamerSet(kFALSE), fVersionUsed(kFALSE), fRuntimeProperties(0), fOffsetStreamer(0), fStreamerType(TClass::kDefault),
fState(kNoInfo),
fCurrentInfo(0), fLastReadInfo(0), fRefProxy(0),
Expand Down Expand Up @@ -1290,7 +1290,7 @@ TClass::TClass(const char *name, Version_t cversion,
fStreamer(0), fIsA(0), fGlobalIsA(0), fIsAMethod(0),
fMerge(0), fResetAfterMerge(0), fNew(0), fNewArray(0), fDelete(0), fDeleteArray(0),
fDestructor(0), fDirAutoAdd(0), fStreamerFunc(0), fConvStreamerFunc(0), fSizeof(-1),
fCanSplit(-1), fProperty(0), fClassProperty(0), fHasRootPcmInfo(kFALSE), fCanLoadClassInfo(kFALSE),
fCanSplit(-1), fIsSyntheticPair(kFALSE), fProperty(0), fClassProperty(0), fHasRootPcmInfo(kFALSE), fCanLoadClassInfo(kFALSE),
fIsOffsetStreamerSet(kFALSE), fVersionUsed(kFALSE), fRuntimeProperties(0), fOffsetStreamer(0), fStreamerType(TClass::kDefault),
fState(kHasTClassInit),
fCurrentInfo(0), fLastReadInfo(0), fRefProxy(0),
Expand Down Expand Up @@ -2927,6 +2927,11 @@ TVirtualIsAProxy* TClass::GetIsAProxy() const
/// Returns 0 in case class is not found.

TClass *TClass::GetClass(const char *name, Bool_t load, Bool_t silent)
{
return TClass::GetClass(name, load, silent, 0, 0);
}

TClass *TClass::GetClass(const char *name, Bool_t load, Bool_t silent, size_t hint_pair_offset, size_t hint_pair_size)
{
if (!name || !name[0]) return 0;

Expand Down Expand Up @@ -3086,12 +3091,11 @@ TClass *TClass::GetClass(const char *name, Bool_t load, Bool_t silent)
// TClass if we have one.
if (cl) return cl;

if (ispair) {
auto pairinfo = TVirtualStreamerInfo::Factory()->GenerateInfoForPair(normalizedName, silent);
if (ispair && hint_pair_offset && hint_pair_size) {
auto pairinfo = TVirtualStreamerInfo::Factory()->GenerateInfoForPair(normalizedName, silent, hint_pair_offset, hint_pair_size);
//return pairinfo ? pairinfo->GetClass() : nullptr;
if (pairinfo)
return pairinfo->GetClass();

} else if (TClassEdit::IsSTLCont( normalizedName.c_str() )) {

return gInterpreter->GenerateTClass(normalizedName.c_str(), kTRUE, silent);
Expand Down Expand Up @@ -3174,7 +3178,7 @@ TClass *TClass::GetClass(const char *name, Bool_t load, Bool_t silent)
////////////////////////////////////////////////////////////////////////////////
/// Return pointer to class with name.

TClass *TClass::GetClass(const std::type_info& typeinfo, Bool_t load, Bool_t /* silent */)
TClass *TClass::GetClass(const std::type_info& typeinfo, Bool_t load, Bool_t /* silent */, size_t hint_pair_offset, size_t hint_pair_size)
{
if (!gROOT->GetListOfClasses())
return 0;
Expand Down Expand Up @@ -3239,12 +3243,23 @@ TClass *TClass::GetClass(const std::type_info& typeinfo, Bool_t load, Bool_t /*
if (autoload_old && gInterpreter->AutoLoad(typeinfo,kTRUE)) {
// Disable autoload to avoid potential infinite recursion
TInterpreter::SuspendAutoLoadingRAII autoloadOff(gInterpreter);
cl = GetClass(typeinfo, load);
cl = GetClass(typeinfo, load, hint_pair_offset, hint_pair_size);
if (cl) {
return cl;
}
}

if (hint_pair_offset) {
int err = 0;
char* demangled_name = TClassEdit::DemangleTypeIdName(typeinfo, err);
if (!err) {
cl = TClass::GetClass(demangled_name, load, kTRUE, hint_pair_offset, hint_pair_size);
free(demangled_name);
if (cl)
return cl;
}
}

// last attempt. Look in the interpreter list of all (compiled+interpreted)
// classes
cl = gInterpreter->GetClass(typeinfo, load);
Expand Down
43 changes: 33 additions & 10 deletions core/meta/src/TProtoClass.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -312,7 +312,9 @@ Bool_t TProtoClass::FillTClass(TClass* cl) {
int prevLevel = 0;
bool first = true;
if (fPRealData.size() > 0) {
size_t element_next_idx = 0;
for (auto element: fPRealData) {
++element_next_idx;
//if (element->IsA() == TObjString::Class()) {
if (element.IsAClass() ) {
// We now check for the TClass entry, w/o loading. Indeed we did that above.
Expand All @@ -322,16 +324,34 @@ Bool_t TProtoClass::FillTClass(TClass* cl) {
// will be issued.
TInterpreter::SuspendAutoParsing autoParseRaii(gInterpreter);

const char *classname = GetClassName(element.fClassIndex);

// Disable autoparsing which might be triggered by the use of ResolvedTypedef
// and the fallback new TClass() below.
currentRDClass = TClass::GetClass(GetClassName(element.fClassIndex), false /* Load */ );
currentRDClass = TClass::GetClass(classname, false /* Load */ );
//printf("element is a class - name %s - index %d %s \n ",currentRDClass->GetName(), element.fClassIndex, GetClassName(element.fClassIndex) );
if (!currentRDClass && !element.TestFlag(TProtoRealData::kIsTransient)) {
if (gDebug>1)
Info("FillTClass()",
"Cannot find TClass for %s; Creating an empty one in the kForwardDeclared state.",
GetClassName(element.fClassIndex));
currentRDClass = new TClass(GetClassName(element.fClassIndex),1,TClass::kForwardDeclared, true /*silent*/);

if (TClassEdit::IsStdPair(classname) && element.fDMIndex == 0 && fPRealData.size() > element_next_idx) {
size_t hint_offset = fPRealData[element_next_idx].fOffset - element.fOffset;
size_t hint_size = 0;
// Now find the size.
size_t end = element_next_idx + 1;
while (end < fPRealData.size() && fPRealData[end].fLevel > element.fLevel)
++end;
if (end < fPRealData.size()) {
hint_size = fPRealData[end].fOffset - element.fOffset;
} else {
hint_size = fSizeof - element.fOffset;
}
currentRDClass = TClass::GetClass(classname, true, false, hint_offset, hint_size);
}
if (!currentRDClass) {
if (gDebug > 1)
Info("FillTClass()",
"Cannot find TClass for %s; Creating an empty one in the kForwardDeclared state.", classname);
currentRDClass = new TClass(classname, 1, TClass::kForwardDeclared, true /*silent*/);
}
}
}
//else {
Expand Down Expand Up @@ -432,10 +452,10 @@ TRealData* TProtoClass::TProtoRealData::CreateRealData(TClass* dmClass,
//TDataMember* dm = (TDataMember*)dmClass->GetListOfDataMembers()->FindObject(fName);
TDataMember* dm = TProtoClass::FindDataMember(dmClass, fDMIndex);

if (!dm && dmClass->GetState()!=TClass::kForwardDeclared) {
if (!dm && dmClass->GetState()!=TClass::kForwardDeclared && !dmClass->fIsSyntheticPair) {
::Error("CreateRealData",
"Cannot find data member # %d of class %s for parent %s!", fDMIndex, dmClass->GetName(),
parent->GetName());
"Cannot find data member # %d of class %s for parent %s!", fDMIndex, dmClass->GetName(),
parent->GetName());
return nullptr;
}

Expand All @@ -444,6 +464,9 @@ TRealData* TProtoClass::TProtoRealData::CreateRealData(TClass* dmClass,
TString realMemberName;
// keep an empty name if data member is not found
if (dm) realMemberName = dm->GetName();
else if (dmClass->fIsSyntheticPair) {
realMemberName = (fDMIndex == 0) ? "first" : "second";
}
if (TestFlag(kIsPointer) )
realMemberName = TString("*")+realMemberName;
else if (dm){
Expand Down Expand Up @@ -530,7 +553,7 @@ TDataMember * TProtoClass::FindDataMember(TClass * cl, Int_t index)
return dm;
i++;
}
if (cl->GetState()!=TClass::kForwardDeclared)
if (cl->GetState()!=TClass::kForwardDeclared && !cl->fIsSyntheticPair)
::Error("TProtoClass::FindDataMember","data member with index %d is not found in class %s",index,cl->GetName());
return nullptr;
}
4 changes: 2 additions & 2 deletions io/io/inc/TStreamerInfo.h
Original file line number Diff line number Diff line change
Expand Up @@ -283,8 +283,8 @@ class TStreamerInfo : public TVirtualStreamerInfo {
// provokes the creation of the corresponding TClass. This relies on the dictionary for
// std::pair<const int, int> to already exist (or the interpreter information being available)
// as it is used as a template.
virtual TVirtualStreamerInfo *GenerateInfoForPair(const std::string &pairclassname, bool silent);
virtual TVirtualStreamerInfo *GenerateInfoForPair(const std::string &firstname, const std::string &secondname, bool silent);
virtual TVirtualStreamerInfo *GenerateInfoForPair(const std::string &pairclassname, bool silent, size_t hint_pair_offset, size_t hint_pair_size);
virtual TVirtualStreamerInfo *GenerateInfoForPair(const std::string &firstname, const std::string &secondname, bool silent, size_t hint_pair_offset, size_t hint_pair_size);

virtual TVirtualCollectionProxy *GenEmulatedProxy(const char* class_name, Bool_t silent);
virtual TClassStreamer *GenEmulatedClassStreamer(const char* class_name, Bool_t silent);
Expand Down
2 changes: 1 addition & 1 deletion io/io/src/TEmulatedCollectionProxy.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -183,7 +183,7 @@ TGenCollectionProxy *TEmulatedCollectionProxy::InitializeEx(Bool_t silent)

if (0==TClass::GetClass(nam.c_str(), kTRUE, silent)) {
// We need to emulate the pair
TVirtualStreamerInfo::Factory()->GenerateInfoForPair(inside[1],inside[2], silent);
TVirtualStreamerInfo::Factory()->GenerateInfoForPair(inside[1],inside[2], silent, 0, 0);
}
}
fValue = new Value(nam,silent);
Expand Down
3 changes: 1 addition & 2 deletions io/io/src/TFile.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -3559,7 +3559,7 @@ void TFile::ReadStreamerInfo()
Int_t asize = fClassIndex->GetSize();
if (uid >= asize && uid <100000) fClassIndex->Set(2*asize);
if (uid >= 0 && uid < fClassIndex->GetSize()) fClassIndex->fArray[uid] = 1;
else if (!isstl) {
else if (!isstl && !info->GetClass()->IsSyntheticPair()) {
printf("ReadStreamerInfo, class:%s, illegal uid=%d\n",info->GetName(),uid);
}
if (gDebug > 0) printf(" -class: %s version: %d info read at slot %d\n",info->GetName(), info->GetClassVersion(),uid);
Expand Down Expand Up @@ -3675,7 +3675,6 @@ void TFile::WriteStreamerInfo()
listOfRules.SetName("listOfRules");
std::set<TClass*> classSet;


while ((info = (TStreamerInfo*)next())) {
Int_t uid = info->GetNumber();
if (fClassIndex->fArray[uid]) {
Expand Down
Loading

0 comments on commit e3e9015

Please sign in to comment.