Ind

va_list business

Recommended Posts

for no particular reason at ~4:20 am i stumbled upon http://svn.netlabs.org/repos/gl2/include/cstdarg and then realized all the va_stuff business rathena makes use of in all map_foreachin<whatever> procedures, for instance: map_foreachinmap

for(i=blockcount;i<bl_list_count;i++)
	if(bl_list[i]->prev)
	{
		va_list ap;
		va_start(ap, type);
		returnCount += func(bl_list[i], ap);
		va_end(ap);
	}

wouldnt

va_list ap;
va_start(ap, type);
for(i=blockcount;i<bl_list_count;i++)
	if(bl_list[i]->prev) {
		returnCount += func(bl_list[i], ap);
	}
va_end(ap);

be way more efficient? the arguments being passed are never changed during the loop, whats the point in recreating the damn thing bl_list_count times?

Share this post


Link to post
Share on other sites

There is no practical performance gain as va_start just do some pointer arithmetic and va_end does nothing, btw the code will be more beautiful if the va_list were created just one time.

Share this post


Link to post
Share on other sites

There is no practical performance gain as va_start just do some pointer arithmetic and va_end does nothing, btw the code will be more beautiful if the va_list were created just one time.

+1

Share this post


Link to post
Share on other sites

After some tests I realized va_arg moves the va_lists' internal offset whenever you retrieve a arg (moves equivalent to the size of that arg), so indeed the va_start must be re-run (we can't simply zero the offset because the offset field is platform-dependant). I'll move the va_list outside the loop as you suggested

Share this post


Link to post
Share on other sites

Actually if it is passed as a argument it wont change on the next use, btw the va is just a pointer on the stack to the arguments.

Share this post


Link to post
Share on other sites

Actually if it is passed as a argument it wont change on the next use, btw the va is just a pointer on the stack to the arguments.

but va_list type is also system dependent at times it is a pointer, at times it isnt: (be aware its 5am i might have missed something D: bear with me)

#if defined(__PPC__)
#if defined(__NT__)
   typedef char * __va_list;
#else
   typedef struct {
     char  __gpr;
     char  __fpr;
     char  __reserved[2];
     char *__input_arg_area;
     char *__reg_save_area;
   } __va_list;
 #endif
#elif defined(__AXP__)
 typedef struct {
   char *__base;
   int   __offset;
 } __va_list;
#elif defined(__MIPS__)
 typedef struct {
   char *__base;
   int   __offset;
 } __va_list;
#elif defined(__HUGE__) || defined(__SW_ZU)
 typedef char _WCFAR *__va_list[1];
#else
 typedef char *__va_list[1];
#endif


it appears my table from above is outdated; I've used gdb to take a look at my current one and its like this (not like any of the above):

ap = {{
   gp_offset = 24, 
   fp_offset = 48, 
   overflow_arg_area = 0x7fff5fbfc500, 
   reg_save_area = 0x7fff5fbfc400
 }}


I've found some more about the above one in Apple's Darwin stuff: http://opensource.apple.com/source/cc/cc-798/cc/ginclude/va-ppc.h

Share this post


Link to post
Share on other sites

Strange, atleast on x86 systems it should be just a pointer walking through the stack.

Share this post


Link to post
Share on other sites

What could be implemented was done in r16933

Share this post


Link to post
Share on other sites