Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
19 commits
Select commit Hold shift + click to select a range
1a1fb79
rootpcm: Read enums before class to get the correct underlying type.
pcanal Mar 16, 2022
fe0b4ce
When loading a TClass for map, also update the pair's TClass.
pcanal Mar 24, 2022
bed6557
TStreamerInfo::Clear, also reset TStreamerElement's offset
pcanal Mar 24, 2022
8a79a4a
rootcling: record Enum used by classes and collection.
pcanal Mar 24, 2022
3c5fa3d
io: Correct offset passed from SyntheticPair to StreamerInfo.
pcanal Mar 24, 2022
01e58c7
Add missing TListOfEnums::FindObject.
pcanal Mar 25, 2022
f972463
TGenCollectionProxy: add missing nullptr protection
pcanal Mar 25, 2022
dd8ccca
When resetting a pair's StreamerInfo inform all collection proxies
pcanal Mar 25, 2022
7e37d73
TProtoClass::FillTClass: Create a ListEnumsWithLock when needed
pcanal Mar 30, 2022
9c6129c
Don't put class' enum in rootpcm global list of enums
pcanal Mar 30, 2022
a0c9807
pair: Also treat unordered map
pcanal Mar 29, 2022
c982d6f
TClass: clear fLastReadInfo, fCurrentInfo when deleting TStreamerInfos
pcanal Mar 29, 2022
84a00aa
Do the pair TClass StreamerInfo refresh only when needed
pcanal Mar 29, 2022
942aa1b
TBufferFile: create StreamerInfo only if needed.
pcanal Mar 31, 2022
260355c
TGenCollectionProxy init: fail if the value's StreamerInfo is not there.
pcanal Mar 31, 2022
44bef95
Avoid reading pass the end of the StreamerInfo container.
pcanal Mar 31, 2022
d36536d
CollectionProxy: pass pair hint to R__CreateValue
pcanal Mar 31, 2022
a5a3b05
Remove unnecessary trailing semi-colon
pcanal Apr 6, 2022
c8a1283
[NFC] Simplify code in TListOfEnums
pcanal Apr 6, 2022
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 6 additions & 3 deletions core/cont/inc/TVirtualCollectionProxy.h
Original file line number Diff line number Diff line change
Expand Up @@ -68,11 +68,14 @@ class TVirtualCollectionProxy {
TPushPop& operator=(const TPushPop&) = delete;
};

TVirtualCollectionProxy() : fClass(), fProperties(0) {};
TVirtualCollectionProxy(TClass *cl) : fClass(cl), fProperties(0) {};
TVirtualCollectionProxy() : fClass(), fProperties(0) {}
TVirtualCollectionProxy(TClass *cl) : fClass(cl), fProperties(0) {}

virtual TVirtualCollectionProxy* Generate() const = 0; // Returns an object of the actual CollectionProxy class
virtual ~TVirtualCollectionProxy() {};
virtual ~TVirtualCollectionProxy() {}

// Reset the info gathered from StreamerInfos and value's TClass.
virtual Bool_t Reset() { return kTRUE; }

virtual TClass *GetCollectionClass() const { return fClass; }
// Return a pointer to the TClass representing the container
Expand Down
3 changes: 3 additions & 0 deletions core/meta/inc/TListOfEnums.h
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,9 @@ class TListOfEnums : public THashList
TEnum *Find(DeclId_t id) const;
virtual TEnum *GetObject(const char*) const;

TObject *FindObject(const char*) const override;
using THashList::FindObject;

void Clear(Option_t *option) override;
void Delete(Option_t *option="") override;

Expand Down
43 changes: 43 additions & 0 deletions core/meta/src/TClass.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -5995,6 +5995,45 @@ void TClass::PostLoadCheck()
}
}
}
if (fCollectionProxy) {
// Update the related pair's TClass if it has already been created.
size_t noffset = 0;
if (strncmp(GetName(), "map<", 4) == 0)
noffset = 3;
else if (strncmp(GetName(), "multimap<", 9) == 0)
noffset = 8;
else if (strncmp(GetName(), "unordered_map<", 14) == 0)
noffset = 13;
else if (strncmp(GetName(), "unordered_multimap<", 19) == 0)
noffset = 18;
if (noffset) {
std::string pairname("pair");
pairname.append(GetName() + noffset);
auto pcl = TClass::GetClass(pairname.c_str(), false, false);
if ( pcl && !pcl->IsLoaded() && !pcl->IsSyntheticPair() )
{
TInterpreter::SuspendAutoLoadingRAII autoloadOff(gInterpreter);

fCollectionProxy->Reset();
TIter nextClass(gROOT->GetListOfClasses());
while (auto acl = (TClass*)nextClass()) {
if (acl == this) continue;
if (acl->fCollectionProxy && acl->fCollectionProxy->GetValueClass() == pcl) {
acl->fCollectionProxy->Reset();
}
}

TIter next(pcl->GetStreamerInfos());
while (auto info = (TVirtualStreamerInfo*)next()) {
if (info->IsBuilt()) {
info->Clear("build");
info->BuildOld();
}
}
fCollectionProxy->GetValueClass();
}
}
}
}

////////////////////////////////////////////////////////////////////////////////
Expand Down Expand Up @@ -7258,6 +7297,10 @@ void TClass::RemoveStreamerInfo(Int_t slot)
R__LOCKGUARD(gInterpreterMutex);
TVirtualStreamerInfo *info = (TVirtualStreamerInfo*)fStreamerInfo->At(slot);
fStreamerInfo->RemoveAt(fClassVersion);
if (fLastReadInfo.load() == info)
fLastReadInfo = nullptr;
if (fCurrentInfo.load() == info)
fCurrentInfo = nullptr;
delete info;
if (fState == kEmulated && fStreamerInfo->GetEntries() == 0) {
fState = kForwardDeclared;
Expand Down
15 changes: 15 additions & 0 deletions core/meta/src/TListOfEnums.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -183,6 +183,21 @@ TEnum *TListOfEnums::Find(DeclId_t id) const
return (TEnum *)fIds->GetValue((Long64_t)id);
}

////////////////////////////////////////////////////////////////////////////////
/// Specialize FindObject to do search for the
/// a enum just by name or create it if its not already in the list

TObject *TListOfEnums::FindObject(const char *name) const
{
TObject *result = THashList::FindObject(name);
if (!result) {
TInterpreter::DeclId_t decl;
decl = gInterpreter->GetEnum(GetClass(), name);
if (decl) result = const_cast<TListOfEnums *>(this)->Get(decl, name);
}
return result;
}

////////////////////////////////////////////////////////////////////////////////
/// Return (after creating it if necessary) the TEnum
/// describing the enum corresponding to the Decl 'id'.
Expand Down
11 changes: 1 addition & 10 deletions core/meta/src/TListOfEnumsWithLock.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -156,16 +156,7 @@ void TListOfEnumsWithLock::Delete(Option_t *option /* ="" */)
TObject *TListOfEnumsWithLock::FindObject(const char *name) const
{
R__LOCKGUARD(gInterpreterMutex);
TObject *result = TListOfEnums::FindObject(name);
if (!result) {


TInterpreter::DeclId_t decl;
if (GetClass()) decl = gInterpreter->GetEnum(GetClass(), name);
else decl = gInterpreter->GetEnum(0, name);
if (decl) result = const_cast<TListOfEnumsWithLock *>(this)->Get(decl, name);
}
return result;
return TListOfEnums::FindObject(name);
}


Expand Down
20 changes: 19 additions & 1 deletion core/meta/src/TProtoClass.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -24,13 +24,30 @@ Persistent version of a TClass.
#include "TList.h"
#include "TListOfDataMembers.h"
#include "TListOfEnums.h"
#include "TListOfEnumsWithLock.h"
#include "TRealData.h"
#include "TError.h"
#include "TVirtualCollectionProxy.h"

#include <cassert>
#include <unordered_map>

#ifdef WIN32
#include <io.h>
#include "Windows4Root.h"
#include <Psapi.h>
#define RTLD_DEFAULT ((void *)::GetModuleHandle(NULL))
#define dlsym(library, function_name) ::GetProcAddress((HMODULE)library, function_name)
#else
#include <dlfcn.h>
#endif

static bool IsFromRootCling() {
// rootcling also uses TCling for generating the dictionary ROOT files.
const static bool foundSymbol = dlsym(RTLD_DEFAULT, "usedToIdentifyRootClingByDlSym");
return foundSymbol;
}

////////////////////////////////////////////////////////////////////////////////
/// Initialize a TProtoClass from a TClass.

Expand Down Expand Up @@ -262,7 +279,8 @@ Bool_t TProtoClass::FillTClass(TClass* cl) {
// We need to fill enums one by one to initialise the internal map which is
// transient
{
auto temp = new TListOfEnums();
auto temp = cl->fEnums.load() ? cl->fEnums.load() :
IsFromRootCling() ? new TListOfEnums() : new TListOfEnumsWithLock();
if (fEnums) {
for (TObject* enumAsTObj : *fEnums){
temp->Add((TEnum*) enumAsTObj);
Expand Down
90 changes: 45 additions & 45 deletions core/metacling/src/TCling.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -1712,51 +1712,6 @@ void TCling::LoadPCMImpl(TFile &pcmFile)
if (gDebug > 1)
::Info("TCling::LoadPCMImpl", "reading protoclasses for %s \n", pcmFile.GetName());

pcmFile.GetObject("__ProtoClasses", protoClasses);

if (protoClasses) {
for (auto obj : *protoClasses) {
TProtoClass *proto = (TProtoClass *)obj;
TClassTable::Add(proto);
}
// Now that all TClass-es know how to set them up we can update
// existing TClasses, which might cause the creation of e.g. TBaseClass
// objects which in turn requires the creation of TClasses, that could
// come from the PCH, but maybe later in the loop. Instead of resolving
// a dependency graph the addition to the TClassTable above allows us
// to create these dependent TClasses as needed below.
for (auto proto : *protoClasses) {
if (TClass *existingCl = (TClass *)gROOT->GetListOfClasses()->FindObject(proto->GetName())) {
// We have an existing TClass object. It might be emulated
// or interpreted; we now have more information available.
// Make that available.
if (existingCl->GetState() != TClass::kHasTClassInit) {
DictFuncPtr_t dict = gClassTable->GetDict(proto->GetName());
if (!dict) {
::Error("TCling::LoadPCM", "Inconsistent TClassTable for %s", proto->GetName());
} else {
// This will replace the existing TClass.
TClass *ncl = (*dict)();
if (ncl)
ncl->PostLoadCheck();
}
}
}
}

protoClasses->Clear(); // Ownership was transfered to TClassTable.
delete protoClasses;
}

TObjArray *dataTypes;
pcmFile.GetObject("__Typedefs", dataTypes);
if (dataTypes) {
for (auto typedf : *dataTypes)
gROOT->GetListOfTypes()->Add(typedf);
dataTypes->Clear(); // Ownership was transfered to TListOfTypes.
delete dataTypes;
}

TObjArray *enums;
pcmFile.GetObject("__Enums", enums);
if (enums) {
Expand Down Expand Up @@ -1806,6 +1761,51 @@ void TCling::LoadPCMImpl(TFile &pcmFile)
enums->Clear();
delete enums;
}

pcmFile.GetObject("__ProtoClasses", protoClasses);

if (protoClasses) {
for (auto obj : *protoClasses) {
TProtoClass *proto = (TProtoClass *)obj;
TClassTable::Add(proto);
}
// Now that all TClass-es know how to set them up we can update
// existing TClasses, which might cause the creation of e.g. TBaseClass
// objects which in turn requires the creation of TClasses, that could
// come from the PCH, but maybe later in the loop. Instead of resolving
// a dependency graph the addition to the TClassTable above allows us
// to create these dependent TClasses as needed below.
for (auto proto : *protoClasses) {
if (TClass *existingCl = (TClass *)gROOT->GetListOfClasses()->FindObject(proto->GetName())) {
// We have an existing TClass object. It might be emulated
// or interpreted; we now have more information available.
// Make that available.
if (existingCl->GetState() != TClass::kHasTClassInit) {
DictFuncPtr_t dict = gClassTable->GetDict(proto->GetName());
if (!dict) {
::Error("TCling::LoadPCM", "Inconsistent TClassTable for %s", proto->GetName());
} else {
// This will replace the existing TClass.
TClass *ncl = (*dict)();
if (ncl)
ncl->PostLoadCheck();
}
}
}
}

protoClasses->Clear(); // Ownership was transfered to TClassTable.
delete protoClasses;
}

TObjArray *dataTypes;
pcmFile.GetObject("__Typedefs", dataTypes);
if (dataTypes) {
for (auto typedf : *dataTypes)
gROOT->GetListOfTypes()->Add(typedf);
dataTypes->Clear(); // Ownership was transfered to TListOfTypes.
delete dataTypes;
}
}

////////////////////////////////////////////////////////////////////////////////
Expand Down
5 changes: 4 additions & 1 deletion io/io/inc/TGenCollectionProxy.h
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ class TGenCollectionProxy
// Default copy constructor has the correct implementation.

// Initializing constructor
Value(const std::string& info, Bool_t silent);
Value(const std::string& info, Bool_t silent, size_t hint_pair_offset = 0, size_t hint_pair_size = 0);
// Delete individual item from STL container
void DeleteItem(void* ptr);

Expand Down Expand Up @@ -359,6 +359,9 @@ class TGenCollectionProxy
// Standard destructor.
virtual ~TGenCollectionProxy();

// Reset the info gathered from StreamerInfos and value's TClass.
virtual Bool_t Reset();

// Return a pointer to the TClass representing the container.
virtual TClass *GetCollectionClass() const;

Expand Down
2 changes: 2 additions & 0 deletions io/io/src/TBufferFile.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -3516,6 +3516,8 @@ Int_t TBufferFile::WriteClassBuffer(const TClass *cl, void *pointer)
//Have to be sure between the check and the taking of the lock if the current streamer has changed
R__LOCKGUARD(gInterpreterMutex);
sinfo = (TStreamerInfo*)const_cast<TClass*>(cl)->GetCurrentStreamerInfo();
if (sinfo == nullptr)
sinfo = (TStreamerInfo*)const_cast<TClass*>(cl)->GetStreamerInfo();
if (sinfo == nullptr) {
const_cast<TClass*>(cl)->BuildRealData(pointer);
sinfo = new TStreamerInfo(const_cast<TClass*>(cl));
Expand Down
37 changes: 28 additions & 9 deletions io/io/src/TGenCollectionProxy.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -313,7 +313,7 @@ class TGenMapProxy : public TGenSetProxy {
////////////////////////////////////////////////////////////////////////////////
/// Constructor.

TGenCollectionProxy::Value::Value(const std::string& inside_type, Bool_t silent)
TGenCollectionProxy::Value::Value(const std::string& inside_type, Bool_t silent, size_t hint_pair_offset, size_t hint_pair_size)
{
std::string inside = (inside_type.find("const ")==0) ? inside_type.substr(6) : inside_type;
fCase = 0;
Expand Down Expand Up @@ -364,7 +364,7 @@ TGenCollectionProxy::Value::Value(const std::string& inside_type, Bool_t silent)
// might fail because CINT does not known the nesting
// scope, so let's first look for an emulated class:

fType = TClass::GetClass(intype.c_str(),kTRUE,silent);
fType = TClass::GetClass(intype.c_str(),kTRUE,silent, hint_pair_offset, hint_pair_size);

if (fType) {
if (isPointer) {
Expand Down Expand Up @@ -775,6 +775,19 @@ TGenCollectionProxy *TGenCollectionProxy::Initialize(Bool_t silent) const
return p->InitializeEx(silent);
}

////////////////////////////////////////////////////////////////////////////////
/// Reset the info gathered from StreamerInfos and value's TClass.
Bool_t TGenCollectionProxy::Reset()
{
if (fReadMemberWise)
fReadMemberWise->Clear();
delete fWriteMemberWise;
fWriteMemberWise = nullptr;
if (fConversionReadMemberWise)
fConversionReadMemberWise->clear();
return kTRUE;
}

////////////////////////////////////////////////////////////////////////////////
/// Check existence of function pointers

Expand Down Expand Up @@ -815,9 +828,10 @@ void TGenCollectionProxy::CheckFunctions() const
////////////////////////////////////////////////////////////////////////////////
/// Utility routine to issue a Fatal error is the Value object is not valid

static TGenCollectionProxy::Value *R__CreateValue(const std::string &name, Bool_t silent)
static TGenCollectionProxy::Value *R__CreateValue(const std::string &name, Bool_t silent,
size_t hint_pair_offset = 0, size_t hint_pair_size = 0)
{
TGenCollectionProxy::Value *val = new TGenCollectionProxy::Value( name, silent );
TGenCollectionProxy::Value *val = new TGenCollectionProxy::Value( name, silent, hint_pair_offset, hint_pair_size );
if ( !val->IsValid() ) {
Fatal("TGenCollectionProxy","Could not find %s!",name.c_str());
}
Expand Down Expand Up @@ -881,11 +895,16 @@ TGenCollectionProxy *TGenCollectionProxy::InitializeEx(Bool_t silent)

{
TInterpreter::SuspendAutoParsing autoParseRaii(gCling);
if (0==TClass::GetClass(nam.c_str(), true, false, fValOffset, fValDiff)) {
TClass *paircl = TClass::GetClass(nam.c_str(), true, false, fValOffset, fValDiff);
if (paircl == nullptr) {
// We need to emulate the pair
TVirtualStreamerInfo::Factory()->GenerateInfoForPair(inside[1], inside[2], silent, fValOffset, fValDiff);
auto info = TVirtualStreamerInfo::Factory()->GenerateInfoForPair(inside[1], inside[2], silent, fValOffset, fValDiff);
if (!info) {
Fatal("InitializeEx",
"Could not load nor generate the dictionary for \"%s\", some element might be missing their dictionary (eg. enums)",
nam.c_str());
}
} else {
TClass *paircl = TClass::GetClass(nam.c_str());
if (paircl->GetClassSize() != fValDiff) {
if (paircl->GetState() >= TClass::kInterpreted)
Fatal("InitializeEx",
Expand All @@ -896,7 +915,7 @@ TGenCollectionProxy *TGenCollectionProxy::InitializeEx(Bool_t silent)
else {
gROOT->GetListOfClasses()->Remove(paircl);
TClass *newpaircl = TClass::GetClass(nam.c_str(), true, false, fValOffset, fValDiff);
if (newpaircl == paircl || newpaircl->GetClassSize() != fValDiff)
if (!newpaircl || newpaircl == paircl || newpaircl->GetClassSize() != fValDiff)
Fatal("InitializeEx",
"The TClass creation for %s did not get the right size: %d instead of%d\n",
nam.c_str(), (int)paircl->GetClassSize(), (int)fValDiff);
Expand All @@ -906,7 +925,7 @@ TGenCollectionProxy *TGenCollectionProxy::InitializeEx(Bool_t silent)
}
}
}
newfValue = R__CreateValue(nam, silent);
newfValue = R__CreateValue(nam, silent, fValOffset, fValDiff);

fPointers = (0 != (fKey->fCase&kIsPointer));
if (fPointers || (0 != (fKey->fProperties&kNeedDelete))) {
Expand Down
Loading