Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Decl id map #59

Closed
7 changes: 7 additions & 0 deletions core/meta/inc/TClass.h
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@
#include <map>
#include <string>
#include <set>
#include <vector>

class TBaseClass;
class TBrowser;
Expand Down Expand Up @@ -72,8 +73,10 @@ namespace ROOT {

namespace ROOT {
class TMapTypeToTClass;
class TMapDeclIdToTClass;
}
typedef ROOT::TMapTypeToTClass IdMap_t;
typedef ROOT::TMapDeclIdToTClass DeclIdMap_t;

class TClass : public TDictionary {

Expand Down Expand Up @@ -195,6 +198,7 @@ friend class ROOT::TGenericClassInfo;
void StreamerDefault(void *object, TBuffer &b, const TClass *onfile_class) const;

static IdMap_t *GetIdMap(); //Map from typeid to TClass pointer
static DeclIdMap_t *GetDeclIdMap(); //Map from DeclId_t to TClass pointer
static ENewType fgCallingNew; //Intent of why/how TClass::New() is called
static Int_t fgClassCount; //provides unique id for a each class
//stored in TObject::fUniqueID
Expand Down Expand Up @@ -402,11 +406,14 @@ friend class ROOT::TGenericClassInfo;

// Function to retrieve the TClass object and dictionary function
static void AddClass(TClass *cl);
static void AddClassToDeclIdMap(TDictionary::DeclId_t id, TClass* cl);
static void RemoveClass(TClass *cl);
static void RemoveClassDeclId(TDictionary::DeclId_t id);
static TClass *GetClassOrAlias(const char *name);
static TClass *GetClass(const char *name, Bool_t load = kTRUE, Bool_t silent = kFALSE);
static TClass *GetClass(const type_info &typeinfo, Bool_t load = kTRUE, Bool_t silent = kFALSE);
static TClass *GetClass(ClassInfo_t *info, Bool_t load = kTRUE, Bool_t silent = kFALSE);
static Bool_t GetClass(DeclId_t id, std::vector<TClass*> &classes);
static VoidFuncPtr_t GetDict (const char *cname);
static VoidFuncPtr_t GetDict (const type_info &info);

Expand Down
85 changes: 85 additions & 0 deletions core/meta/src/TClass.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@
#include <typeinfo>
#include <cmath>
#include <assert.h>
#include <vector>

#include "TListOfDataMembers.h"
#include "TListOfFunctions.h"
Expand Down Expand Up @@ -253,6 +254,41 @@ namespace ROOT {
}
#endif
};

class TMapDeclIdToTClass {
// Wrapper class for the multimap of DeclId_t and TClass.
public:
typedef multimap<TDictionary::DeclId_t, TClass*> DeclIdMap_t;
typedef DeclIdMap_t::key_type key_type;
typedef DeclIdMap_t::mapped_type mapped_type;
typedef DeclIdMap_t::const_iterator const_iterator;
typedef std::pair <const_iterator, const_iterator> equal_range;
typedef DeclIdMap_t::size_type size_type;

private:
DeclIdMap_t fMap;

public:
void Add(const key_type &key, mapped_type obj)
{
// Add the <key,obj> pair to the map.
std::pair<const key_type, mapped_type> pair = make_pair(key, obj);
fMap.insert(pair);
}
size_type CountElementsWithKey(const key_type &key)
{
return fMap.count(key);
}
equal_range Find(const key_type &key) const
{
// Find the type corresponding to the key.
return fMap.equal_range(key);
}
void Remove(const key_type &key) {
// Remove the type corresponding to the key.
fMap.erase(key);
}
};
}

IdMap_t *TClass::GetIdMap() {
Expand All @@ -266,6 +302,17 @@ IdMap_t *TClass::GetIdMap() {
#endif
}

DeclIdMap_t *TClass::GetDeclIdMap() {

#ifdef R__COMPLETE_MEM_TERMINATION
static DeclIdMap_t gDeclIdMapObject;
return &gIdMap;
#else
static DeclIdMap_t *gDeclIdMap = new DeclIdMap_t;
return gDeclIdMap;
#endif
}

//______________________________________________________________________________
void TClass::AddClass(TClass *cl)
{
Expand All @@ -276,6 +323,18 @@ void TClass::AddClass(TClass *cl)
if (cl->GetTypeInfo()) {
GetIdMap()->Add(cl->GetTypeInfo()->name(),cl);
}
if (cl->fClassInfo) {
GetDeclIdMap()->Add((void*)(cl->fClassInfo), cl);
}
}

//______________________________________________________________________________
void TClass::AddClassToDeclIdMap(TDictionary::DeclId_t id, TClass* cl)
{
// static: Add a TClass* to the map of classes.

if (!cl || !id) return;
GetDeclIdMap()->Add(id, cl);
}

//______________________________________________________________________________
Expand All @@ -288,6 +347,16 @@ void TClass::RemoveClass(TClass *oldcl)
if (oldcl->GetTypeInfo()) {
GetIdMap()->Remove(oldcl->GetTypeInfo()->name());
}
if (oldcl->fClassInfo) {
//GetDeclIdMap()->Remove((void*)(oldcl->fClassInfo));
}
}

//______________________________________________________________________________
void TClass::RemoveClassDeclId(TDictionary::DeclId_t id)
{
if (!id) return;
GetDeclIdMap()->Remove(id);
}

//______________________________________________________________________________
Expand Down Expand Up @@ -2865,6 +2934,22 @@ TClass *TClass::GetClass(ClassInfo_t *info, Bool_t load, Bool_t silent)
}
}

//______________________________________________________________________________
Bool_t TClass::GetClass(DeclId_t id, std::vector<TClass*> &classes)
{
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Wouldn't be simpler/clearer to 'only' return the result in the vector. Currently if the result is 'zero' it might mean 'no class' or 'multiple class'.
I recommend the following simpler interface:
bool GetClass(DeclId_t id, std::vector<TClass*>& classes)

(Since load and silent are not used, at least for now, I don't see a reason to introduce them)
If you still with to have them to look like the other GetClass, then suppress the warning with Bool_t /* load /
(To support GetClass(declid, vec, kTRUE /
load */) we will need to generate the name and call GetName(const char *) )

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If we use a vector unconditionally, any GetClass(declid) requires an allocation even though almost all of them return a single element. That's fairly inefficient. So the plan was to return fgMultipleClasses (aka -1) if the caller must provide a vector, but to handle the simple case without vector.

On March 25, 2014 1:01:39 AM CET, pcanal [email protected] wrote:

@@ -2866,6 +2940,34 @@ TClass *TClass::GetClass(ClassInfo_t *info,
Bool_t load, Bool_t silent)
}

//______________________________________________________________________________
+TClass* TClass::GetClass(DeclId_t id, Bool_t load, Bool_t silent,
std::vector<TClass*>* classes)
+{

Wouldn't be simpler/clearer to 'only' return the result in the vector.
Currently if the result is 'zero' it might mean 'no class' or 'multiple
class'.
I recommend the following simpler interface:
bool GetClass(DeclId_t id, std::vector<TClass*>& classes)

(Since load and silent are not used, at least for now, I don't see a
reason to introduce them)
If you still with to have them to look like the other GetClass, then
suppress the warning with Bool_t /* load /
(To support GetClass(declid, vec, kTRUE /
load */) we will need to
generate the name and call GetName(const char *) )


Reply to this email directly or view it on GitHub:
https://github.com/karies/root/pull/59/files#r10912564

short mobile;

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi Axel,

I strongly disagree. With this interface if you do not pass the std::vector you get a random answer
and it is very likely to never be the 'right' behavior. I

Actually looking at the user of TClass::GetClass(DeclId_t) in the patch, I think that the patch is
indeed flawed because it does not always use the std::vector. For example on line 4526,
why does the code only update one (random) TClass's TListOfFunctions?

Cheers,
Philippe.

On 3/25/14, 1:13 AM, karies wrote:

In core/meta/src/TClass.cxx:

@@ -2866,6 +2940,34 @@ TClass *TClass::GetClass(ClassInfo_t *info, Bool_t load, Bool_t silent)
}

//______________________________________________________________________________
+TClass* TClass::GetClass(DeclId_t id, Bool_t load, Bool_t silent, std::vector<TClass*>* classes)
+{
If we use a vector unconditionally, any GetClass(declid) requires an allocation even though almost all of them return a single
element. That's fairly inefficient. So the plan was to return fgMultipleClasses (aka -1) if the caller must provide a vector, but
to handle the simple case without vector.
On March 25, 2014 1:01:39 AM CET, pcanal [email protected] wrote: > @@ -2866,6 +2940,34 @@ TClass
TClass::GetClass(ClassInfo_t *info, Bool_t load, Bool_t silent) > } > >
//
_____________________________________________________________________________ > +TClass_ TClass::GetClass(DeclId_t id, Bool_t
load, Bool_t silent, std::vector<TClass*>* classes) > +{ Wouldn't be simpler/clearer to 'only' return the result in the vector.
Currently if the result is 'zero' it might mean 'no class' or 'multiple class'. I recommend the following simpler interface: bool
GetClass(DeclId_t id, std::vector<TClass*>& classes) (Since load and silent are not used, at least for now, I don't see a reason
to introduce them) If you still with to have them to look like the other GetClass, then suppress the warning with Bool_t /* load
/ (To support GetClass(declid, vec, kTRUE / load */) we will need to generate the name and call GetName(const char *) ) ---
Reply to this email directly or view it on GitHub: https://github.com/karies/root/pull/59/files#r10912564
=== short mobile;


Reply to this email directly or view it on GitHub https://github.com/karies/root/pull/59/files#r10918640.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi Philippe,

At line 4526 it is dealing with global functions. Where classes come in the std::vector is used.
The commented code was miss leading. I removed it and added some comments.
Cheers,
Cristina

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi Cristina,

It was just an example, another example is now at line 4573 ...

Hi Axel,

In other word the current interface requires that any call to this function to
have the pattern:

TClass* cl = TClass::GetClass(RD);
if (cl == (TClass_)(-1)) {
//check -1 and multiple key
std::vector<TClass_> vectTClass;
cl = TClass::GetClass(RD, kTRUE, kTRUE, &vectTClass);
foreach(...) do something
} else if (cl) {
for single do the same ....
}

I find it cumbersome and error prone. I find the 'optimization' of avoid the extra allocation a 'premature' optimization
and if really really you want to avoid the allocation then we could provide a fixed/limited size container to pass
the information back and forth [ class OptimizedArray { size_t fSize; TClass *fValues[maxSize]; }; or whatever :) ]

Cheers,
Philippe.

On 3/25/14, 9:34 AM, CristinaCristescu wrote:

In core/meta/src/TClass.cxx:

@@ -2866,6 +2940,34 @@ TClass *TClass::GetClass(ClassInfo_t *info, Bool_t load, Bool_t silent)
}

//______________________________________________________________________________
+TClass* TClass::GetClass(DeclId_t id, Bool_t load, Bool_t silent, std::vector<TClass*>* classes)
+{

Hi Philippe,

At line 4526 it is dealing with global functions. Where classes come in the std::vector is used.
The commented code was miss leading. I removed it and added some comments.
Cheers,
Cristina


Reply to this email directly or view it on GitHub https://github.com/karies/root/pull/59/files#r10932671.


if (!gROOT->GetListOfClasses()) return 0;

DeclIdMap_t* map = GetDeclIdMap();
// Get all the TClass pointer that have the same DeclId.
DeclIdMap_t::equal_range iter = map->Find(id);
if (iter.first == iter.second) return false;
std::vector<TClass*>::iterator vectIt = classes.begin();
for (DeclIdMap_t::const_iterator it = iter.first; it != iter.second; ++it)
vectIt = classes.insert(vectIt, it->second);
return true;
}

//______________________________________________________________________________
VoidFuncPtr_t TClass::GetDict (const char *cname)
{
Expand Down
138 changes: 115 additions & 23 deletions core/meta/src/TCling.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@
#include "TMemberInspector.h"
#include "TMethod.h"
#include "TMethodArg.h"
#include "TFunctionTemplate.h"
#include "TObjArray.h"
#include "TObjString.h"
#include "TString.h"
Expand Down Expand Up @@ -393,8 +394,7 @@ void TCling__GetNormalizedContext(const ROOT::TMetaUtils::TNormalizedCtxt*& norm
}

extern "C"
void TCling__UpdateListsOnCommitted(const cling::Transaction &T,
cling::Interpreter* interp) {
void TCling__UpdateListsOnCommitted(const cling::Transaction &T, cling::Interpreter*) {

((TCling*)gCling)->UpdateListsOnCommitted(T);
}
Expand Down Expand Up @@ -2184,7 +2184,12 @@ void TCling::SetClassInfo(TClass* cl, Bool_t reload)
if (cl->fClassInfo && !reload) {
return;
}
delete (TClingClassInfo*) cl->fClassInfo;
//Remove the decl_id from the DeclIdToTClass map
TClingClassInfo* TClinginfo = (TClingClassInfo*) cl->fClassInfo;
if (TClinginfo) {
TClass::RemoveClassDeclId(TClinginfo->GetDeclId());
}
delete TClinginfo;
cl->fClassInfo = 0;
std::string name(cl->GetName());
TClingClassInfo* info = new TClingClassInfo(fInterpreter, name.c_str());
Expand Down Expand Up @@ -2252,6 +2257,9 @@ void TCling::SetClassInfo(TClass* cl, Bool_t reload)
// }
}
}
if (cl->fClassInfo) {
TClass::AddClassToDeclIdMap(((TClingClassInfo*)cl->fClassInfo)->GetDeclId(), cl);
}
}

//______________________________________________________________________________
Expand Down Expand Up @@ -2685,6 +2693,10 @@ TClass *TCling::GenerateTClass(ClassInfo_t *classinfo, Bool_t silent /* = kFALSE
// Not quite useful yet, but that what CINT used to do anyway.
cl = new TClass(classinfo, 1, 0, 0, -1, -1, silent);
}
// Add the new TClass to the map of declid and TClass*.
if (cl) {
TClass::AddClassToDeclIdMap(((TClingClassInfo*)classinfo)->GetDeclId(), cl);
}
return cl;
}

Expand Down Expand Up @@ -4337,9 +4349,11 @@ void TCling::UpdateClassInfoWithDecl(const void* vTD)
const TagDecl* tdOld = llvm::dyn_cast_or_null<TagDecl>(cci->GetDecl());
if (!tdOld || (tdDef && tdDef != tdOld)) {
cl->ResetCaches();
TClass::RemoveClassDeclId(cci->GetDeclId());
if (td) {
// It's a tag decl, not a namespace decl.
cci->Init(*cci->GetType());
TClass::AddClassToDeclIdMap(cci->GetDeclId(), cl);
}
}
} else {
Expand All @@ -4348,6 +4362,7 @@ void TCling::UpdateClassInfoWithDecl(const void* vTD)
// the 'type' corresponding to the TClass anyway in order to
// preserve the opaque typedefs (Double32_t)
cl->fClassInfo = (ClassInfo_t *)new TClingClassInfo(fInterpreter, cl->GetName());
TClass::AddClassToDeclIdMap(((TClingClassInfo*)(cl->fClassInfo))->GetDeclId(), cl);
}
}
SetClassAutoloading(storedAutoloading);
Expand Down Expand Up @@ -4479,43 +4494,46 @@ void TCling::UpdateListsOnUnloaded(const cling::Transaction &T)
HandleNewTransaction(T);

// Unload the objects from the lists and update the objects' state.
TGlobal *global = 0;
TFunction *function = 0;
TDataMember* var = 0;
TFunction* function = 0;
TEnum* e = 0;
TListOfDataMembers* globals = (TListOfDataMembers*)gROOT->GetListOfGlobals();
TFunctionTemplate* functiontemplate = 0;
TListOfFunctions* functions = (TListOfFunctions*)gROOT->GetListOfGlobalFunctions();
TListOfFunctionTemplates* functiontemplates = (TListOfFunctionTemplates*)gROOT->GetListOfFunctionTemplates();
TListOfEnums* enums = (TListOfEnums*)gROOT->GetListOfEnums();
TListOfDataMembers* globals = (TListOfDataMembers*)gROOT->GetListOfGlobals();
for(cling::Transaction::const_iterator I = T.decls_begin(), E = T.decls_end();
I != E; ++I)
I != E; ++I) {
for (DeclGroupRef::const_iterator DI = I->m_DGR.begin(),
DE = I->m_DGR.end(); DI != DE; ++DI) {
// Deal with global variables and globa enum constants.
if (isa<VarDecl>(*DI) || isa<EnumConstantDecl>(*DI)) {
clang::ValueDecl* VD = dyn_cast<ValueDecl>(*DI);
global = (TGlobal*)globals->FindObject(VD->getNameAsString().c_str());
if (global && global->IsValid()) {
var = (TDataMember*)globals->FindObject(VD->getNameAsString().c_str());
if (var && var->IsValid()) {
// Unload the global by setting the DataMemberInfo_t to 0
globals->Unload(global);
global->Update(0);
}
} else if (isa<RecordDecl>(*DI) || isa<NamespaceDecl>(*DI)) {
const clang::NamedDecl* ND = dyn_cast<NamedDecl>(*DI);
if (ND) {
std::string buf = ND->getNameAsString();
const char* name = buf.c_str();
TClass* cl = TClass::GetClass(name);
if (cl) {
cl->ResetClassInfo();
}
globals->Unload(var);
var->Update(0);
}
// Deal with global functions.
} else if (const FunctionDecl* FD = dyn_cast<FunctionDecl>(*DI)) {
function = gROOT->GetGlobalFunction(FD->getNameAsString().c_str());
function = (TFunction*)functions->FindObject(FD->getNameAsString().c_str());
if (function && function->IsValid()) {
functions->Unload(function);
function->Update(0);
}
// Deal with global function templates.
} else if (const FunctionTemplateDecl* FTD = dyn_cast<FunctionTemplateDecl>(*DI)) {
functiontemplate = (TFunctionTemplate*)functiontemplates->FindObject(FTD->getNameAsString().c_str());
if (functiontemplate) {
functiontemplates->Unload(functiontemplate);
functiontemplate->Update(0);
}
// Deal with global enums.
} else if (const EnumDecl* ED = dyn_cast<EnumDecl>(*DI)) {
e = (TEnum*)enums->FindObject(ED->getNameAsString().c_str());
if (e && e->IsValid()) {
if (e) {
globals = (TListOfDataMembers*)gROOT->GetListOfGlobals();
TIter iEnumConst(e->GetConstants());
while (TEnumConstant* enumConst = (TEnumConstant*)iEnumConst()) {
// Since the enum is already created and valid that ensures us that
Expand All @@ -4529,8 +4547,82 @@ void TCling::UpdateListsOnUnloaded(const cling::Transaction &T)
enums->Unload(e);
e->Update(0);
}
// Deal with classes. Unload the class and the data members will be not accessible anymore
// Cannot declare the members in a different declaration like redeclarable namespaces.
} else if (const clang::RecordDecl* RD = dyn_cast<RecordDecl>(*DI)) {
std::vector<TClass*> vectTClass;
if (TClass::GetClass(RD, vectTClass)) {
for (std::vector<TClass*>::iterator CI = vectTClass.begin(), CE = vectTClass.end();
CI != CE; ++CI) {
(*CI)->ResetClassInfo();
}
}
// Deal with namespaces. Unload the members of the current redeclaration only.
} else if (const clang::NamespaceDecl* ND = dyn_cast<NamespaceDecl>(*DI)) {
if (ND->isOriginalNamespace()) {
std::vector<TClass*> vectTClass;
if (TClass::GetClass(ND, vectTClass)) {
for (std::vector<TClass*>::iterator CI = vectTClass.begin(), CE = vectTClass.end();
CI != CE; ++CI) {
(*CI)->ResetClassInfo();
}
}
} else {
std::vector<TClass*> vectTClass;
if (TClass::GetClass(ND->getCanonicalDecl(), vectTClass)) {
for (std::vector<TClass*>::iterator CI = vectTClass.begin(), CE = vectTClass.end();
CI != CE; ++CI) {
TClass* cl = (*CI);
TListOfDataMembers* datamembers = (TListOfDataMembers*)cl->GetListOfDataMembers();
TListOfFunctions* functions = (TListOfFunctions*)cl->GetListOfMethods();
TListOfEnums* enums = (TListOfEnums*)cl->GetListOfEnums();
TListOfFunctionTemplates* functiontemplates = (TListOfFunctionTemplates*)cl->GetListOfFunctionTemplates();
// If this is a redeclaration of the namespace, we iterate over the members to unload them
for (DeclContext::decl_iterator RI = ND->decls_begin(), RE = ND->decls_end(); RI != RE; ++RI) {
if (isa<VarDecl>(*RI) || isa<EnumConstantDecl>(*RI)) {
clang::ValueDecl* VD = dyn_cast<ValueDecl>(*RI);
var = (TDataMember*)datamembers->FindObject(VD->getNameAsString().c_str());
if (var) {
// Unload the global by setting the DataMemberInfo_t to 0
datamembers->Unload(var);
var->Update(0);
}
} else if (const FunctionDecl* FD = dyn_cast<FunctionDecl>(*RI)) {
function = (TFunction*)functions->FindObject(FD->getNameAsString().c_str());
if (function) {
functions->Unload(function);
function->Update(0);
}
} else if (const EnumDecl* ED = dyn_cast<EnumDecl>(*RI)) {
e = (TEnum*)enums->FindObject(ED->getNameAsString().c_str());
if (e) {
TIter iEnumConst(e->GetConstants());
while (TEnumConstant* enumConst = (TEnumConstant*)iEnumConst()) {
// Since the enum is already created and valid that ensures us that
// we have the enum constants created as well.
enumConst = (TEnumConstant*)datamembers->FindObject(enumConst->GetName());
if (enumConst && enumConst->IsValid()) {
datamembers->Unload(enumConst);
enumConst->Update(0);
}
}
enums->Unload(e);
e->Update(0);
}
} else if (const FunctionTemplateDecl* FTD = dyn_cast<FunctionTemplateDecl>(*RI)) {
functiontemplate = (TFunctionTemplate*)functiontemplates->FindObject(FTD->getNameAsString().c_str());
if (functiontemplate) {
functiontemplates->Unload(functiontemplate);
functiontemplate->Update(0);
}
}
}
}
}
}
}
}
}
}


Expand Down
Loading