Forum Menu




 


Log in Problems?
New User? Sign Up!
AVR Freaks Forum Index

Post new topic   Reply to topic
View previous topic Printable version Log in to check your private messages View next topic
Author Message
JohanEkdahl
PostPosted: Jun 06, 2011 - 08:37 PM
10k+ Postman


Joined: Mar 27, 2002
Posts: 18535
Location: Lund, Sweden

Quote:

I’m sorry to say that, but to me it seems that gcc developers are living in their own word, and it’s a problem to communicate with them.

I'd say that on the list there is more focus on the internals of the compiler, the run-time lib and so on. There is less traffic on "How do I do this with an AVR?"-type questions. It's just different cultures. And when you try to talk on e.g. the avr-gcc list you should have done your reading up.

Here on AVRfreaks the culture is less rough in this respect. (Not that we do not bash the self-inflicted-clueless or the people trying to get school work done with no effort on their on...)

By and large, the people on the avr-gcc/avr-libc/AVRDude lists are just as nice, helpful and polite as here on freaks. Just somewhat different cultures. It always helps to read through old threads or go through a few digests in a mailing-list-archive to get the feel for the way to move in a certain social environment. Remarkably like Real Life [tm], if you ask me...
 
 View user's profile Send private message Visit poster's website 
Reply with quote Back to top
joshperry
PostPosted: Nov 21, 2011 - 06:17 AM
Newbie


Joined: Apr 04, 2008
Posts: 19


Does GCC really copy the vtable to RAM for every instance of a virtual class? Or does it just create a single copy of the vtable in RAM?

Josh
 
 View user's profile Send private message  
Reply with quote Back to top
JohanEkdahl
PostPosted: Nov 21, 2011 - 07:10 AM
10k+ Postman


Joined: Mar 27, 2002
Posts: 18535
Location: Lund, Sweden

Josh! I have not checked, but I would be surprised (to say the least) if it created a copy for every instance. Why would it? I've heard of no C++ compiler that creates v-tables per instance.
 
 View user's profile Send private message Visit poster's website 
Reply with quote Back to top
joshperry
PostPosted: Nov 21, 2011 - 03:25 PM
Newbie


Joined: Apr 04, 2008
Posts: 19


Interesting, I kind of assumed that, but some of the posts made it sound like a majority of their RAM was being taken by vtable copies... I'm not sure this is a huge deal for a microcontroller (at least not for my project), I have maybe 4 distinct classes that have 1, or maybe 2, virtual methods; all my other classes use static dispatch.

If all the work was done to add this GCC feature, would it save me all of 16 bytes of RAM (4 16-bit vtable entries for 4 classes)? I assume there is also a 16-bit vtable pointer that is copied into RAM for each instance, I would think this could add up much more quickly.
 
 View user's profile Send private message  
Reply with quote Back to top
JohanEkdahl
PostPosted: Nov 21, 2011 - 03:39 PM
10k+ Postman


Joined: Mar 27, 2002
Posts: 18535
Location: Lund, Sweden

Quote:

I assume there is also a 16-bit vtable pointer that is copied into RAM for each instance

Yes, it is a part of the "object structure"(i.e. what the this-pointer is pointing to in a called (non-static) member function).

Another way of saying this is that a virtual function call is actually equivalent to something like this (for a call from a member function to a virtual member function):

Code:
this->vtable->func(this, parameter1, parameter2 ...)


Quote:

If all the work was done to add this GCC feature, would it save me all of 16 bytes of RAM (4 16-bit vtable entries for 4 classes)?

Yup.

Quote:

I assume there is also a 16-bit vtable pointer that is copied into RAM for each instance, I would think this could add up much more quickly.

Yup.

Alo: Apart from the RAM consumption, this might be an issue with code size / execution time (if RAM access is more compact or faster than flash access).
 
 View user's profile Send private message Visit poster's website 
Reply with quote Back to top
joshperry
PostPosted: Nov 22, 2011 - 06:54 PM
Newbie


Joined: Apr 04, 2008
Posts: 19


JohanEkdahl wrote:


Another way of saying this is that a virtual function call is actually equivalent to something like this (for a call from a member function to a virtual member function):

Code:
this->vtable->func(this, parameter1, parameter2 ...)




Is the vtable pointer actually variable between instances? Could it technically be implemented as?

Code:
MyClass::vtable->func(this, param1, param2 ...)


I could see going to the work to make the vtable pointer stay in flash being worth the work, more than the vtable iteslf...
 
 View user's profile Send private message  
Reply with quote Back to top
SprinterSB
PostPosted: Nov 22, 2011 - 07:40 PM
Posting Freak


Joined: Dec 21, 2006
Posts: 1483
Location: Saar-Lor-Lux

For the technical aspects you will have to dive into the C++ frontend: http://gcc.gnu.org/viewcvs/trunk/gcc/cp/

(Intrinsic) named address spaces are only mentioned as a language extension to C++, see ISO/IEC DTR 18037, Annex F.2, which is not imlemented in GCC.

PR43745 does not imply to expose named address spaces to the user, yet "bits" of named address suppport in GCC's C++ front end are missing, of course.

As PR43745 is 1 1/2 years old now and no one even managed to supply a small example that shows the problem, I'd guess that PR is bug-rot and can be closed?

_________________
avr-gcc NewsABIOptions4.8-WindowsInline Asm
 
 View user's profile Send private message Visit poster's website 
Reply with quote Back to top
JohanEkdahl
PostPosted: Nov 22, 2011 - 09:31 PM
10k+ Postman


Joined: Mar 27, 2002
Posts: 18535
Location: Lund, Sweden

Quote:

Is the vtable pointer actually variable between instances?

Yes, AFAIK it must be or the polymorphism would not work. The point is that when you have a pointer to a superclass it is not known what subclass the object (pointed to) actually is. Thus each object has to be able to inform about where the applicable vtable is.

Sketchy example:

Code:
class Super
{
public:
   virtual void foo() = 0;
};

class Sub1
{
public:
   virtual void foo() {...}
};

class Sub2
{
public:
   virtual void foo() {...}
};

void main(void)
{
   Super * objects[10];
   for (int i = 0; i < 10; i++)
   {
      if (rand() > 0.5)
      {
         objects[i] = new Sub1();
      }
      else
      {
         objects[i] = new Sub2();
      }
   }

   for (int i = 0; i < 10; i++)
   {
      objects[i]->foo();
   }
}


There is no way to tell at compile time what objects will be created. Thus the compiler must generate code that at run-time determines what foo() is called. Thus every object needs to have information making this possible. Although the C++ standard says nothing specific about how this is to be implemented, but leaves it open to the implementers, the only variant I've seen/heard of is for every object to have a pointer to it's vtable. (With multiple inheritance it might be a little more involved, but the principle about every object knowing still holds.

This is also, at least conceptually, closely related to RTTI.
 
 View user's profile Send private message Visit poster's website 
Reply with quote Back to top
gregd99
PostPosted: Sep 03, 2012 - 05:54 AM
Hangaround


Joined: Oct 10, 2011
Posts: 237
Location: Sydney, Australia

guys,
after the recent activity on another thread http://www.avrfreaks.net/index.php?name=PNphpBB2&file=viewtopic&t=69747&postdays=0&postorder=asc&start=60&sid=16ea510d43297f5a67df48fc92380520 I came across this one.

was there ever a conclusion as to whether this enhancement could be scheduled?


my experimentation with some reasonably simple example (1 x virtual function in base class) shows a cost of 6 bytes per class type plus 2 bytes per class instance.

so.... in a despatcher example for an atmega16 that i have been looking at I have 26 instances and what would be 16 different class types give 16x6 + 26x2 = 148 (of 1024) bytes. That is a big cost.

_________________
regards
Greg
 
 View user's profile Send private message  
Reply with quote Back to top
ChaunceyGardiner
PostPosted: Sep 03, 2012 - 06:40 AM
Posting Freak


Joined: Mar 09, 2012
Posts: 1452
Location: North Carolina, USA

Greg,

The best place to start that research would be to find out if you really need polymorphism. Are you actually calling all of those virtual member functions through a pointer to a base class instance ? Throw in a few examples of how you need it.

_________________
Sid

Life... is a state of mind
 
 View user's profile Send private message  
Reply with quote Back to top
JohanEkdahl
PostPosted: Sep 03, 2012 - 06:50 AM
10k+ Postman


Joined: Mar 27, 2002
Posts: 18535
Location: Lund, Sweden

Chauncey!

Since he mentions a "despatcher" I would speculate that it is "the Run() function" that is virtual.

On e of the school book examples of polymorphism in action.
 
 View user's profile Send private message Visit poster's website 
Reply with quote Back to top
ChaunceyGardiner
PostPosted: Sep 03, 2012 - 07:02 AM
Posting Freak


Joined: Mar 09, 2012
Posts: 1452
Location: North Carolina, USA

Sure. Schoolbooks are useful in the appropriate context - the school - but in reality too much abstraction for a simple problem comes at a cost at more than one level.

I think I read somewhere the other day that some Atmel guys had recently implemented the bubble sort algorithm in assembly. That's a joke if there ever was one.
 
 View user's profile Send private message  
Reply with quote Back to top
gregd99
PostPosted: Sep 03, 2012 - 08:06 AM
Hangaround


Joined: Oct 10, 2011
Posts: 237
Location: Sydney, Australia

JohanEkdahl wrote:
Chauncey!

Since he mentions a "despatcher" I would speculate that it is "the Run() function" that is virtual.

One of the school book examples of polymorphism in action.

This is correct.

I have been converting a small project to cpp mainly as a learning exercise.

I have a small executive where application processes are implemented as state machines in c functions. the despatcher calls the applications processes via an array of pointers to functions where the argument to the function is an event for each application process. this is very straightforward in c.

I have converted all my queues, timers and other support functions to classes. The design is cleaner and the memory usage is reduced!

I am having a look at what would be involved in converting some/all of the application processes to be classes. Although there are some advantages in the application processes the despatcher seems to consume heaps of ram for vtables.

the concept is...
Code:

class base
{
    virtual void run(event);
}

class procN: public base
{
    void run(event)
    {
        // do the stuff for user process N
    }
}

base procTable[] = {pointers to proc1.. procN}

events are delivered by indexing procTable[] with the pid and calling run()

If there is a simpler method I am interested to know it.

The approach outlined above is way expensive with RAM usage.

_________________
regards
Greg
 
 View user's profile Send private message  
Reply with quote Back to top
clawson
PostPosted: Sep 03, 2012 - 09:24 AM
10k+ Postman


Joined: Jul 18, 2005
Posts: 62241
Location: (using avr-gcc in) Finchingfield, Essex, England

Quote:

I have been converting a small project to cpp mainly as a learning exercise.

So is the whole vtables in flash thing brouhaha? If it's not something that actually affects working, concrete examples of real application code on AVRs why does anyone care? And when those folks turn up saying "C++, bloat, "hidden RAM", etc" ask them for their concrete example of where it's happening too.

I'm sure there are areas of the compiler with a stronger justification for research/engineering than some navel fluff examination if that's what this is?

_________________
 
 View user's profile Send private message  
Reply with quote Back to top
JohanEkdahl
PostPosted: Sep 03, 2012 - 10:21 AM
10k+ Postman


Joined: Mar 27, 2002
Posts: 18535
Location: Lund, Sweden

Quote:

Sure. Schoolbooks are useful in the appropriate context - the school - but in reality too much abstraction for a simple problem comes at a cost at more than one level.

OK, let me rephrase: A scheduler is for me an excellent example of where C++ virtual functions really helps make for nice, redable, optimized-for-maintenance code.
 
 View user's profile Send private message Visit poster's website 
Reply with quote Back to top
ChaunceyGardiner
PostPosted: Sep 03, 2012 - 06:16 PM
Posting Freak


Joined: Mar 09, 2012
Posts: 1452
Location: North Carolina, USA

gregd99 wrote:
the concept is...
Code:

class base
{
    virtual void run(event);
}

class procN: public base
{
    void run(event)
    {
        // do the stuff for user process N
    }
}

If there is a simpler method I am interested to know it.

The approach outlined above is way expensive with RAM usage.

Whether a less expensive approach is simpler or not depends on how big N is.

But even for non-small N you still have to create and add each process to your array - and apparently keep a mapping between each process and its place in the array.


gregd99 wrote:
Code:

base procTable[] = {pointers to proc1.. procN}

events are delivered by indexing procTable[] with the pid and calling run()

How are these "events" created ? How is the "pid" for any given event determined ?


It would be easier to suggest a simpler solution if you posted more code.


JohanEkdahl wrote:
OK, let me rephrase: A scheduler is for me an excellent example of where C++ virtual functions really helps make for nice, redable, optimized-for-maintenance code.

To me, it depends on how complicated the alternative would be. Adding abstractions doesn't necessarily make the code easier to read or maintain.

I also look at whether or not I can afford the cost of making the code "easier".

If the code actually is easier - to me, that means simpler - why would that come at a cost ? Code that actually is simpler tend to generate smaller binaries.
 
 View user's profile Send private message  
Reply with quote Back to top
Display posts from previous:     
Jump to:  
All times are GMT + 1 Hour
Post new topic   Reply to topic
View previous topic Printable version Log in to check your private messages View next topic
Powered by PNphpBB2 © 2003-2006 The PNphpBB Group
Credits