Placement of vtables, inlines and such

Jim Dehnert dehnert at baalbek.engr.sgi.com
Tue Jun 29 06:15:07 UTC 1999


A variety of questions and observations on this thread...

> From: Jason Merrill <jason at cygnus.com>
> Date: 24 Jun 1999 04:36:42 -0700
> 
> 1) Emit them everywhere and only use one.
> 2) Use some heuristic to decide where to emit them.
> 3) Use a database to decide where to emit them.
> 4) Generate them at link time.
> 
> #3 and #4 are feasible for templates, but I consider them too heavyweight
> to be used for other things.

Does that remain true if you're already using them for templates?
> 
> The way to handle this in standard ELF is weak symbols.  If all definitions
> are marked weak, the linker will choose one and the others will just sit
> there taking up space.

It has become apparent in the base IA-64 ABI discussions that weak
symbols are problematic.  Different vendors treat them differently,
both in terms of whether they cause archive objects to be extracted,
and in terms of how they are handled in DSOs (some vendors treat them
like normal globals once linked, some also defer to non-weak at
runtime.)

> Christophe mentioned the other day that the HP compiler used the typical
> heuristic above, and handled the case of different results by encoding the
> key function in the vtable name.  But this seems unnecessary when we can
> just choose one of multiple defns.

It would be helpful to me if someone would describe the "typical
heuristic" (or any heuristic being used).

> The GNU ELF toolchain does a variant of #1 here; any sections with names
> beginning with ".gnu.linkonce." are treated as COMDAT sections.  It seems
> more sensible to me to key off of the section name than the first symbol
> name as in PE.

Keying off section names is evil.  If we're going to use (the
equivalent of) COMDAT sections, let's mark them with a section header
flag.

> I further propose that we not use heuristics to cut down the number of
> copies ahead of time; they usually work fine, but can cause problems in
> some situations, such as when not all of the class's members are in the
> same symbol space.

What do you mean by the same symbol space?

> Does the ia64 ABI provide for controlling which symbols
> are exported from a shared library?

Yes.  We have changed the gABI to add an export class to the symbol
record (in st_other).  The compiler (or linker) may mark a symbol
PROTECTED, preventing preemption, or HIDDEN, preventing export.
(The latter is converted to LOCAL binding at link time.)

> A side issue: What do we want to do with dynamically-initialized variables?
> The same thing, or use COMMON?  I propose COMMON.

COMMON is another problem, due to different treatment across DSOs by
different vendors.  But I don't really know what you're suggesting
here.  What is the issue with dynamically-initialized variables?  There
should still be a unique definition, shouldn't there?  (Except in cases
which have nothing to do with the dynamic definition, like statics in
inlines, classes, etc.)  So COMMON doesn't seem to help.  Furthermore,
if you were to optimize an initialization that were partially static,
you can't use COMMON, which doesn't have iniital values.
> 
> Jason


> From: Christophe de Dinechin <ddd at cup.hp.com>
> 
> From: Jason Merrill <jason at cygnus.com>
>
> I don't know if catching a problem  
> "sometimes" is better than "never", or if it is actually worse...

Usually better, I'd say...

> It looks to me like garbage collection requires one extra operation,  
> namely selecting the "blessed" symbol that will not be discarded,  
> right? Isn't that some other form of COMDATing? In other words, isn't  
> garbage collection just an additional optimization which may be  
> placed on top of COMDATs?
> 
> 
> > I further propose that we not use heuristics to cut down the number of 
> > copies ahead of time; they usually work fine, but can cause problems in 
> > some situations, such as when not all of the class's members are in the 
> > same symbol space.
> 
> As you said, "they usually work fine".

Again, could I please have an explanation of what the heuristics being
discussed are, and what "usually" means?

> The problem is that some compiler may be smarter at inlining that  
> another, and figure out that it actually can initialize it  
> statically. In that case, it cannot go into COMMON (or you force that  
> smart compiler to not do that optimization for binary compatibility  
> reasons...). For instance:
> 
> 	inline int f() { return 1; }
> 	static int i = f();

We would certainly inline this one...

> Christophe


> From: Jason Merrill <jason at cygnus.com>
> 
>  If one implementation uses COMMON, and another uses
> COMDAT, they will be combined by the linker (I think; does a weak symbol
> take precedence over COMMON?)

Depends on the vendor, and on whether they are in the same DSO.  Yecch.
> 
> Jason


> From: Daveed Vandevoorde <daveed at edg.com>
> 
> Jason Merrill wrote:
> [...]
> > No.  gc works by sweeping from main, finding all the referenced symbols;
> > any sections that haven't provided any symbols are discarded.  If we use
> > weak symbols for vtables and put them in separate sections, gc will keep at
> > most one copy, as needed.  There is no notion of a special symbol.
> 
> How does this work in shared libraries? Is GC done at load time?
> 
> > gc is a more general solution, as it also can discard normal code that
> > isn't actually needed.  It also allows us to discard all copies in cases
> > where that is appropriate, such as when we can get the vtable from one of
> > our shared libs. 
> 
> I guess that means the answer to the above is "yes"?

I don't think you can do GC at load time.  However, at that point, the
extra copies should disappear by virtue of preemption, if you've done
it all with exported global symbols.

> 	Daveed

-	    Jim Dehnert		dehnert at sgi.com
				(650)933-4272




More information about the cxx-abi-dev mailing list