300 likes | 313 Views
An in-depth discussion about code layout, data structures, bytecode variables, and execution regarding CINT parts and Reflection at the ROOT Team Meeting. Covering a wide range of topics like parser generation, dictionary reflection data, and interpreting load processes. It gives insights into a complex coding environment at the CERN PH/SFT, including the interplay between CINT-Reflex and other utility tools for C++ code management. This session explored over 80k lines of code for the CINT project, highlighting the critical aspects and challenges faced by the team in integrating reflection, parsing, and data manipulation into their workflow effectively.
E N D
Crienftlex Crienftlex Extended Version. And also Director’s Cut. ROOT Team Meeting Axel Naumann • CERN PH/SFT
Outline • CINT’s parts, content-wise • CINT’s layout, code-wise • Reflex, where it fits in • The CINT-Reflex interface • Reflection Data vs. CINT Utility Info • CINT Parts not in Reflex • AOB: The ROOT Reflection interface • CINT Outlook WARNING: Summaries in between!Not the end of talk yet! ROOT Team Meeting
CINT Parts Reflection 23k lines Execution 63k lines bytecode variables interpreter vtbl expression-eval Parsing 21k lines pragma file i/o Other 70k lines preproc tokenizer ROOT Team Meeting
CINT And Reflection rootcint gccxml Auto-Load C++ Parser Generate Dictionary Reflection Data Interpreter Load Dictionary ROOT Compiled Function Call Uses ReflectionC++ API Dict Gen Data flow ROOT Team Meeting
CINT Code Layout Data struct types: G__tagtable, G__typedef, G__ifunc_table, G__var_array, G__param, G__friendtag, G__inheritance, G__commentinfo, G__RootSpecial Utility struct types: G__input_file, G__value, G__tempobject_list, G__linked_taginfo, G__bytecodefunc, G__funcentry That was the structured part. Structured? ROOT Team Meeting
CINT Code Layout - G__ifunc_table G__SIGNEDCHAR_T type[G__MAXIFUNC];/* type of return value */ short p_tagtable[G__MAXIFUNC]; short p_typetable[G__MAXIFUNC]; G__SIGNEDCHAR_T reftype[G__MAXIFUNC]; short para_nu[G__MAXIFUNC]; G__SIGNEDCHAR_T isconst[G__MAXIFUNC]; G__SIGNEDCHAR_T isexplicit[G__MAXIFUNC]; char para_reftype[G__MAXIFUNC][G__MAXFUNCPARA]; char para_type[G__MAXIFUNC][G__MAXFUNCPARA]; char para_isconst[G__MAXIFUNC][G__MAXFUNCPARA]; short para_p_tagtable[G__MAXIFUNC][G__MAXFUNCPARA]; short para_p_typetable[G__MAXIFUNC][G__MAXFUNCPARA]; G__value *para_default[G__MAXIFUNC][G__MAXFUNCPARA]; char *para_name[G__MAXIFUNC][G__MAXFUNCPARA]; char *para_def[G__MAXIFUNC][G__MAXFUNCPARA]; char iscpp[G__MAXIFUNC]; char ansi[G__MAXIFUNC];/* ANSI or standard header format */ struct G__ifunc_table *next; short page; G__SIGNEDCHAR_T access[G__MAXIFUNC]; /*private, protected, public*/ char staticalloc[G__MAXIFUNC]; int tagnum; G__SIGNEDCHAR_T globalcomp[G__MAXIFUNC]; void* userparam[G__MAXIFUNC]; /* user parameter array */ short vtblindex[G__MAXIFUNC]; short vtblbasetagnum[G__MAXIFUNC]; ROOT Team Meeting
CINT Code – C Arrays G__SIGNEDCHAR_T type[G__MAXIFUNC];/* type of return value */ short p_tagtable[G__MAXIFUNC]; short p_typetable[G__MAXIFUNC]; G__SIGNEDCHAR_T reftype[G__MAXIFUNC]; short para_nu[G__MAXIFUNC]; G__SIGNEDCHAR_T isconst[G__MAXIFUNC]; G__SIGNEDCHAR_T isexplicit[G__MAXIFUNC]; char para_reftype[G__MAXIFUNC][G__MAXFUNCPARA]; char para_type[G__MAXIFUNC][G__MAXFUNCPARA]; char para_isconst[G__MAXIFUNC][G__MAXFUNCPARA]; short para_p_tagtable[G__MAXIFUNC][G__MAXFUNCPARA]; short para_p_typetable[G__MAXIFUNC][G__MAXFUNCPARA]; G__value *para_default[G__MAXIFUNC][G__MAXFUNCPARA]; char *para_name[G__MAXIFUNC][G__MAXFUNCPARA]; char *para_def[G__MAXIFUNC][G__MAXFUNCPARA]; char iscpp[G__MAXIFUNC]; char ansi[G__MAXIFUNC];/* ANSI or standard header format */ struct G__ifunc_table *next; short page; G__SIGNEDCHAR_T access[G__MAXIFUNC]; /*private, protected, public*/ char staticalloc[G__MAXIFUNC]; int tagnum; G__SIGNEDCHAR_T globalcomp[G__MAXIFUNC]; void* userparam[G__MAXIFUNC]; /* user parameter array */ short vtblindex[G__MAXIFUNC]; short vtblbasetagnum[G__MAXIFUNC]; ROOT Team Meeting
CINT Code – Reflection, Utility G__SIGNEDCHAR_T type[G__MAXIFUNC];/* type of return value */ short p_tagtable[G__MAXIFUNC]; short p_typetable[G__MAXIFUNC]; G__SIGNEDCHAR_T reftype[G__MAXIFUNC]; short para_nu[G__MAXIFUNC]; G__SIGNEDCHAR_T isconst[G__MAXIFUNC]; G__SIGNEDCHAR_T isexplicit[G__MAXIFUNC]; char para_reftype[G__MAXIFUNC][G__MAXFUNCPARA]; char para_type[G__MAXIFUNC][G__MAXFUNCPARA]; char para_isconst[G__MAXIFUNC][G__MAXFUNCPARA]; short para_p_tagtable[G__MAXIFUNC][G__MAXFUNCPARA]; short para_p_typetable[G__MAXIFUNC][G__MAXFUNCPARA]; G__value *para_default[G__MAXIFUNC][G__MAXFUNCPARA]; char *para_name[G__MAXIFUNC][G__MAXFUNCPARA]; char *para_def[G__MAXIFUNC][G__MAXFUNCPARA]; char iscpp[G__MAXIFUNC]; char ansi[G__MAXIFUNC];/* ANSI or standard header format */ struct G__ifunc_table *next; short page; G__SIGNEDCHAR_T access[G__MAXIFUNC]; /*private, protected, public*/ char staticalloc[G__MAXIFUNC]; int tagnum; G__SIGNEDCHAR_T globalcomp[G__MAXIFUNC]; void* userparam[G__MAXIFUNC]; /* user parameter array */ short vtblindex[G__MAXIFUNC]; short vtblbasetagnum[G__MAXIFUNC]; ROOT Team Meeting
CINT Code – Reflection, Tools? To be replaced by Reflex Reflection: describes. Persistent, part of dictionary.E.g. type, name, parameters, enclosing scope Utilities: used by CINT functions. Temporary, context dependent, volatile.E.g. address of compiled function, call parameters To be mashed with Reflex, using Reflex::PropertyList ROOT Team Meeting
CINT Code - Unstructured Cint/inc/global.h alone contains >253 globals. struct G__tagtable G__struct; struct G__typedef G__newtype; struct G__ifunc_table G__ifunc ; struct G__ifunc_table *G__p_ifunc; char G__var_type;/*var decl type*/ char G__var_typeB;/*var decl type for func return */ int G__prerun; /* pre-run flag */ int G__funcheader; /*func header mode*/ Reflection Utility ROOT Team Meeting
CINT Code - Functions G__using_namespace(...) { var=G__searchvariable(buf,hash,G__p_local, &G__global,&struct_offset, &store_struct_offset,&ig15,0); store_globalvarpointer = G__globalvarpointer; G__globalvarpointer = var->p[ig15]; G__letvariable(varname,G__null,&G__global, G__p_local); G__globalvarpointer = store_globalvarpointer; avar = G__searchvariable(varname,ahash,G__p_local, &G__global,&astruct_offset, &astore_struct_offset,&aig15,0); ROOT Team Meeting
CINT Code - Functions G__using_namespace(...) { /* boring version */ var= Searchvar(); temp = G__globalvarpointer; G__globalvarpointer = var->p[ig15]; Letvariable(); G__globalvarpointer = temp; avar = Searchvar (); - Side effects,- Globals rule,- Data not visible,- No separation of Reflection & Utility data ROOT Team Meeting
CINT Code - Summary • This job is damn difficult. • We understand the internal structure of CINT. • We know how to replace what (coming up). • There is NO WAY we can do several things in one go. ROOT Team Meeting
Reflex – Where It Fits In 1:1 match between Cint reflection structs and Reflex classes: ROOT Team Meeting
CINT & Reflex Reflection data structures are NOT the problem. But utility data need adaptation:interpreter’s values, stack, function call args,… And globals. And all of these types cannot stay C (use Reflex now) So functions become C++, too (already now compiled as C++, but C by spirit). So Cint API becomes C++, too. ROOT Team Meeting
CINT & Reflex, Example (Data) Core reflection data: “int” → Reflex::Type C → C++ ROOT Team Meeting
CINT & Reflex, Example (Info) Some parts easier than others… In Reflex, Properties part of Type object, not of reference! ROOT Team Meeting
CINT & Reflex, Example (Info) Transitional translation functions ROOT Team Meeting
CINT & Reflex Plugging - Summary Many translations are obvious, but even those have long tail of consequences Need changes in small steps → “buffer” changes by introducing wrappers No fundamental problems, “just” coding & debugging Major usage of wrappers: CINT’s lookup G__defined_tagname, G__defined_typename:int tagnum = G__defined_tagname(“TObject”) → Introduce central lookup function in Reflex ROOT Team Meeting
The Purity Of Reflex – CINT Helpers Reflex is about reflection – not about interpreting, documenting, serializing,… CINT’s little helpers have no place in Reflex:comments, file position, compiled/interpreted? etc Use Reflex “value dump” PropertyList to store class G__RflxProperties { int filenum, linenum; char globalcomp; char iscpplink; G__comment_info comment;}; ROOT Team Meeting
CINT Helpers & Reflex PropertyList Good idea to store CINT Helpers in PropertyList? + Extensible + Easy ? But fast? ? Should e.g. doc, decl / impl location be part of Reflex API? For now: use PropertyList, wrap access from CINT ROOT Team Meeting
The Path – Leaving Home • C to C++, Cint in namespace • Migrate only CINT typedef info to Reflex::Type • Don’t change any CINT function to use Reflex data (but use CINT info to Reflex wrappers) – only use Reflex object as replacement for “int typenum” • Replace lookup, so we don’t suffer from CINT/Reflex incompatible string-ization of types: “int*const*” or “int * const *” or “int ** const”? • TEST. (need enclosing scope in CINT & Reflex) ROOT Team Meeting
The Path – On The Road • Same for G__tagtable, G__ifunc_table, G__var_array, G__param • Test after each step • Remove wrappers, use Reflex directly • Test Curtain First Act. ROOT Team Meeting
Things Not Part Of The Game • Make CINT thread safe • Make CINT use parameters instead of globals They only make sense after Crienftlex – BUT they don’t benefit. They really are different projects. Don’t expect Crienftlex to give a new Cint! ROOT Team Meeting
ROOT And CINT Reflection • ROOT wraps CINT C++ API • CINT C++ API wraps CINT G__tagtable etc C++ API will be backward compatible! No need (code-wise) to change ROOT’s CINT reflection access BUT: huge gain from doing so! Again, independent, and for after Crienftlex! ROOT Team Meeting
CINT’s Future (1/2) • Fallbacks + scaffolding (wrappers etc) removed – 1st half 2007 • Re-structure CINT functions: convert globals to function parameters; generate dictionaries from & into Reflex • “Cint context” + “Cint back office” class for thread safety; context for dictionary (macros) & execution: new TCint()->Process(“new TObject”) ROOT Team Meeting
CINT’s Future (2/2) • Call it CINT2 • Celebrate New Year’s Eve of the next century • Ability to generate dictionarieson the fly, no need to put them into your lib (key for templated classes) • Function wrappers removed, call directly into lib • Dictionaries persistent (not .o, but .root) • Revisit parser ROOT Team Meeting
The Final Summary (1/2) CINT’s complexity, data layout, function style is major obstacle for the merge – after all, they were the reason for the merge. Do one small step after another, always test for consistency Separate as many tasks and steps as possible ROOT Team Meeting
The Final Summary (2/2) End of June: CINT API is C++ (no extern “C” anymore), wrappers + typedef tested We will try to have struct G__* replaced, still with wrappers, but faster, smaller memory footprint, tested, in September, rightafter the production release! Probably introducing cintold + cint[new] in ROOT, allowing dynamic switch as user fallback ROOT Team Meeting
What Now? Philippe, Stefan, and I believe we’ve determined all necessary ingredients to get the merge done, now we just need time. Work Food Life ROOT Team Meeting