1

I have a following code to emulate basic system on my pc (x86):

typedef void (*op_fn) ();

void add()
{
   //add Opcode
   //fetch next opcode
   opcodes[opcode]();
}

void nop()
{
   //NOP opcode
   //fetch next opcode
   opcodes[opcode]();
}

const op_fn opcodes[256] =
{
    add,
    nop,
    etc...
};

and i call this "table" via opcodes[opcode]() I am trying to improve performance of my interpreter. What about inlining every function, like

inline void add()
inline void nop()

Is there any benefits of doing it?

Is there anyway to make it go faster? Thanks

nmzik
  • 141
  • 1
  • 1
  • 9
  • question on working code are maybe better for http://codereview.stackexchange.com/ – 463035818_is_not_an_ai Apr 27 '16 at 13:39
  • 1
    Can you create a toy example of actual working code that matches your pattern? Even with 3 opcodes? As written, large performance issues can be hidden by your pseudo-code. Also, "make it better" is a poor question; explicit ways your code fails is better, or why something is unexpected. – Yakk - Adam Nevraumont Apr 27 '16 at 13:39
  • @tobi303 this is example/pseudo-code which is off-topic on Code Review, on that site we require real, working code. See [A guide to Code Review for Stack Overflow users](http://meta.codereview.stackexchange.com/questions/5777/a-guide-to-code-review-for-stack-overflow-users) – Phrancis Apr 27 '16 at 13:42
  • 1
    If each opcode function calls the next function you will (most likely) eventually run out of stack space. Move the fetch-and-dispatch code out of the opcode implementations. – molbdnilo Apr 27 '16 at 13:51

3 Answers3

3

Just because you flag a method as inline it doesn't require the compiler to do so - it's more of a hint than an order.

Given that you are storing the opcode handlers in an array the compiler will need to place the address of the function into the array, therefore it can't inline it.

There's actually nothing wrong with your approach. If you really think you've got performance issues then get some metrics, otherwise don't worry (at this point!). The concept of a table of pointers to functions is nothing new - it's actually how C++ implement virtual functions (ie the vtable).

Sean
  • 60,939
  • 11
  • 97
  • 136
2

"Inline" means "don't emit a function call; instead, substitute the function body at compile time."

Calling through a function pointer means "do a function call, the details of which won't be known until runtime."

The two features are fundamentally opposed. (The best you could hope for is that a sufficiently advanced compiler could statically determine which function is being called through a function pointer in very limited circumstances and inline those.)

switch blocks are typically implemented as jump tables, which could have less overhead than function calls, so replacing your function pointer array with a switch block and using inline might make a difference.

Josh Kelley
  • 56,064
  • 19
  • 146
  • 246
1

inline is just a hint to your compiler, it does not guarantee any inlining being done. You should read up on inlining (maybe at the ISO C++ FAQ), as too much inlining can actually make your code slower (through code bloat and associated virtual memory trashing ).