Re: virtual machine efficiency

"cr88192" <>
31 Dec 2004 13:06:27 -0500

          From comp.compilers

Related articles
[2 earlier articles]
Re: virtual machine efficiency (2004-12-30)
Re: virtual machine efficiency (2004-12-30)
Re: virtual machine efficiency (cr88192) (2004-12-30)
Re: virtual machine efficiency (Chris F Clark) (2004-12-30)
Re: virtual machine efficiency (2004-12-30)
Re: virtual machine efficiency (Calum Grant) (2004-12-30)
Re: virtual machine efficiency (cr88192) (2004-12-31)
Re: virtual machine efficiency (cr88192) (2004-12-31)
Re: virtual machine efficiency (John R. Strohm) (2005-01-01)
Re: virtual machine efficiency (Chris Dollin) (2005-01-12)
Re: virtual machine efficiency (cr88192) (2005-01-14)
Re: virtual machine efficiency (Chris Dollin) (2005-01-15)
Re: virtual machine efficiency (2005-01-30)
| List of all articles for this month |

From: "cr88192" <>
Newsgroups: comp.compilers,comp.lang.misc
Date: 31 Dec 2004 13:06:27 -0500
Organization: Compilers Central
References: 04-12-151 04-12-170
Keywords: VM
Posted-Date: 31 Dec 2004 13:06:27 EST

"Calum Grant" <> wrote in message
> ed_davis2 wrote:
>> I have developed a simple stack based virtual machine. I would like
>> it to be as efficient as possible, in terms of both speed and object
>> code size. Size, as in size of the object code the VM processes
>> (byte-code), and not necessarily the size of the VM.
>> Is there a way I can have both fast loading of operands, and small
>> byte-code size?
> 1) You could inserts nops before the op-code to ensure that the value
> was always word-aligned. However this would be too slow since your
> interpreter would need to handle the nops.

maybe useful for hw, I doubt so for interpreters...

> 2) You could still align your data on a word-boundary. The interpreter
> would notice the alignment of the op-code, and implicitly skip 0-3
> bytes. The compiler would need to insert appropriate padding to ensure
> the correct alignment.
> case OP_LD:
> if(IP&3) IP = (IP&~3) + 4;
> operand = *(int*)IP;


I typically realign slightly differently, eg:
the check seems like a slight timewaster, it is imo better just to realign
and not worry about it than check and realign, as presumably the realign
would be needed in 75% of the calls anyways.

> 3) You could have variable-width op-codes. Have 4 load instructions
> with widths 1,2,3 and 4 that align the data following the op-code. But
> I don't see much advantage over 2).

yes, I don't see an advantage either.

> case OP_LD0:
> operand = *(int*)IP;
> IP += 4;
> ...
> break;
> case OP_LD1:
> IP ++;
> operand = *(int*)IP;
> IP += 4;
> ...
> break;
> case OP_LD2:
> IP += 2;
> operand = *(int*)IP;
> IP += 4;
> ...
> break;
> case OP_LD3:
> IP += 3;
> operand = *(int*)IP;
> IP += 4;
> ...
> break;
> 4) You could store values out-of-stream. But this is slightly less
> efficient.

not sure why really.
I would guess this depends on the implementation of the interpreter, and
mine typically being unoptimized enough to where it shouldn't matter (of all
things the interpreter looks up binding dynamically).

to me though this still seems like a "splitting hairs case":
vs, eg:
i=*(int *)(ip+1);

ip1=(byte *)(((long)ip+4)&(~3));
i=*(int *)ip;

I personally see other strong reasons for keeping values out of
stream, with the only main detractor I can think of being that one has
to keep tract of the out of band values table...

> 5) (copied from Anton Ertl's post) reorder op-codes and move
> word-aligned data away from its op-code.

imo this idea is cool, but I can imagine it being difficult to work with.
it would likely make a lot more sense, eg, if one could "packet" opcodes,
but imo this doesn't make much sense in an interpreter (it being serial and

> I think in the cases of 2) and 3), although there is occasional
> padding, the interpreter has much less to do than in the more complex
> schemes.

personally I chose something like 4, imo it makes the most sense, eg,
in the dynamicly typed and dynamically compiled case, and the case
where opcodes don't really have associated types.

I think an important point is whether one views it as more sensible to have
a generic "load" operator, or "load.i2", "load.i4", "load.f8", ...

but whatever, I may just be stupid.

Post a followup to this message

Return to the comp.compilers page.
Search the comp.compilers archives again.