Multiple Bytecode Sets

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
5 messages Options
Reply | Threaded
Open this post in threaded view
|

Multiple Bytecode Sets

Stefan Marr-3

Hi Eliot:

May I ask you to give me a brief, high-level description of how the support for multiple bytecode sets works?

Do you switch between different dispatch tables based on the method flag?
Or do you extend the existing one and include the bit into the dispatch?

Do you have any performance numbers, or pointers to literature?

I found hints to Smalltalk/X, VisualAgeJava/Smalltalk, and I think MagLev/Gemstone might also use that kind of technique.
But, unfortunately, Google is a bit shy about papers, or interesting references.

Thanks a lot
Stefan


--
Stefan Marr
Software Languages Lab
Vrije Universiteit Brussel
Pleinlaan 2 / B-1050 Brussels / Belgium
http://soft.vub.ac.be/~smarr
Phone: +32 2 629 2974
Fax:   +32 2 629 3525

Reply | Threaded
Open this post in threaded view
|

Re: Multiple Bytecode Sets

Eliot Miranda-2
 
Hi Stefan,

On Tue, Oct 16, 2012 at 12:11 PM, Stefan Marr <[hidden email]> wrote:
Hi Eliot:

May I ask you to give me a brief, high-level description of how the support for multiple bytecode sets works?

sure.
 
Do you switch between different dispatch tables based on the method flag?
Or do you extend the existing one and include the bit into the dispatch?

This scheme is suggested by Claus Gittinger, and he uses something very similar in Smalltalk/X.  The idea is merely to include an offset that selects the bytecode set in the dispatch and set this offset on every send and return.  So with two bytecode sets there are 512 cases in the interpreter's dispatch loop and the offset is either 0 or 256.  In the Squeak VM this means code such as

StackInterpreter methods
fetchNextBytecode
"This method fetches the next instruction (bytecode)."
currentBytecode := self fetchByte + bytecodeSetSelector

setMethod: aMethodObj
"Set the method and determine the bytecode set based on the method header's sign."
<inline: true>
method := aMethodObj.
self assert: (objectMemory isOopCompiledMethod: method).
bytecodeSetSelector := (self methodUsesAlternateBytecodeSet: method)
ifTrue: [256]
ifFalse: [0]

methodUsesAlternateBytecodeSet: aMethodObj
<api>
<inline: true>
"A negative header selects the alternate bytecode set."
^self headerIndicatesAlternateBytecodeSet: (self headerOf: aMethodObj)

headerIndicatesAlternateBytecodeSet: methodHeader
"A negative header selects the alternate bytecode set."
^(objectMemory integerValueOf: methodHeader) < 0

Do you have any performance numbers, or pointers to literature?

I couldn't see much of an impact when I measured it, but I don't have my measurements handy.  Modern processors cache the read so well that even in the interpreter impact is minimal (it was certainly less than 10%, probably less than 5%, in a pure interpreter), and of course in the JIT it matters not at all.  But the impact was enough that I ended up conditionalizing the code so it reads

fetchNextBytecode
"This method fetches the next instruction (bytecode). Each bytecode method is responsible for fetching the next bytecode, preferably as early as possible to allow the memory system time to process the request before the next dispatch."

self cppIf: MULTIPLEBYTECODESETS
ifTrue: [currentBytecode := self fetchByte + bytecodeSetSelector]
ifFalse: [currentBytecode := self fetchByte]

That was easier than trying to define bytecodeSetSelector as 0, e.g. via a macro.

I found hints to Smalltalk/X, VisualAgeJava/Smalltalk, and I think MagLev/Gemstone might also use that kind of technique.
But, unfortunately, Google is a bit shy about papers, or interesting references.

I don't suppose its something people do a lot.  Claus' VM is the only one I was aware of.  I think its useful to support multiple languages and to support migrating the bytecode set using incremental development, but in a production VM if one didn't need the support I think one would end up disabling it.

Thanks a lot
Stefan

--
cheers,
Eliot

Reply | Threaded
Open this post in threaded view
|

Re: Multiple Bytecode Sets

Stefan Marr-3

Hi Eliot:

On 16 Oct 2012, at 22:32, Eliot Miranda wrote:

> StackInterpreter methods
> fetchNextBytecode
> "This method fetches the next instruction (bytecode)."
> currentBytecode := self fetchByte + bytecodeSetSelector

Thanks, that's what I was looking for.

> I couldn't see much of an impact when I measured it, but I don't have my measurements handy.  Modern processors cache the read so well that even in the interpreter impact is minimal (it was certainly less than 10%, probably less than 5%, in a pure interpreter), and of course in the JIT it matters not at all.  But the impact was enough that I ended up conditionalizing the code so it reads

Hm, ok. Sounds better than the 5-30% hit I have for having a check inside the bytecodes to have different semantics.

> I don't suppose its something people do a lot.  Claus' VM is the only one I was aware of.  I think its useful to support multiple languages and to support migrating the bytecode set using incremental development, but in a production VM if one didn't need the support I think one would end up disabling it.

The other example I found is the LuaJIT2 interpreter.
It is used to enable and disable debugging hooks, as far as I understand.
But since it is written in assembler, it is just patching the dispatch table
and let's the bytecode jump to different code when the debugging hooks are enabled.
But I didn't see any performance numbers for that. Would guess it would take some interaction with the OS to deactivate protection on executable memory pages to change the dispatch table.

Thanks
Stefan

--
Stefan Marr
Software Languages Lab
Vrije Universiteit Brussel
Pleinlaan 2 / B-1050 Brussels / Belgium
http://soft.vub.ac.be/~smarr
Phone: +32 2 629 2974
Fax:   +32 2 629 3525

Reply | Threaded
Open this post in threaded view
|

Re: Multiple Bytecode Sets

Guido Chari
 
Claus' VM? I don't know it and i'm interested on the topic, any precise pointer?

Cheers,
Guido.

2012/10/16 Stefan Marr <[hidden email]>

Hi Eliot:

On 16 Oct 2012, at 22:32, Eliot Miranda wrote:

> StackInterpreter methods
> fetchNextBytecode
>       "This method fetches the next instruction (bytecode)."
>       currentBytecode := self fetchByte + bytecodeSetSelector

Thanks, that's what I was looking for.

> I couldn't see much of an impact when I measured it, but I don't have my measurements handy.  Modern processors cache the read so well that even in the interpreter impact is minimal (it was certainly less than 10%, probably less than 5%, in a pure interpreter), and of course in the JIT it matters not at all.  But the impact was enough that I ended up conditionalizing the code so it reads

Hm, ok. Sounds better than the 5-30% hit I have for having a check inside the bytecodes to have different semantics.

> I don't suppose its something people do a lot.  Claus' VM is the only one I was aware of.  I think its useful to support multiple languages and to support migrating the bytecode set using incremental development, but in a production VM if one didn't need the support I think one would end up disabling it.

The other example I found is the LuaJIT2 interpreter.
It is used to enable and disable debugging hooks, as far as I understand.
But since it is written in assembler, it is just patching the dispatch table
and let's the bytecode jump to different code when the debugging hooks are enabled.
But I didn't see any performance numbers for that. Would guess it would take some interaction with the OS to deactivate protection on executable memory pages to change the dispatch table.

Thanks
Stefan

--
Stefan Marr
Software Languages Lab
Vrije Universiteit Brussel
Pleinlaan 2 / B-1050 Brussels / Belgium
http://soft.vub.ac.be/~smarr
Phone: +32 2 629 2974
Fax:   +32 2 629 3525


Reply | Threaded
Open this post in threaded view
|

Re: Multiple Bytecode Sets

Eliot Miranda-2
 


On Tue, Oct 16, 2012 at 1:48 PM, Guido Chari <[hidden email]> wrote:
 
Claus' VM? I don't know it and i'm interested on the topic, any precise pointer?

Not sure how much there is on the VM, but you could try

 

Cheers,
Guido.

2012/10/16 Stefan Marr <[hidden email]>

Hi Eliot:

On 16 Oct 2012, at 22:32, Eliot Miranda wrote:

> StackInterpreter methods
> fetchNextBytecode
>       "This method fetches the next instruction (bytecode)."
>       currentBytecode := self fetchByte + bytecodeSetSelector

Thanks, that's what I was looking for.

> I couldn't see much of an impact when I measured it, but I don't have my measurements handy.  Modern processors cache the read so well that even in the interpreter impact is minimal (it was certainly less than 10%, probably less than 5%, in a pure interpreter), and of course in the JIT it matters not at all.  But the impact was enough that I ended up conditionalizing the code so it reads

Hm, ok. Sounds better than the 5-30% hit I have for having a check inside the bytecodes to have different semantics.

> I don't suppose its something people do a lot.  Claus' VM is the only one I was aware of.  I think its useful to support multiple languages and to support migrating the bytecode set using incremental development, but in a production VM if one didn't need the support I think one would end up disabling it.

The other example I found is the LuaJIT2 interpreter.
It is used to enable and disable debugging hooks, as far as I understand.
But since it is written in assembler, it is just patching the dispatch table
and let's the bytecode jump to different code when the debugging hooks are enabled.
But I didn't see any performance numbers for that. Would guess it would take some interaction with the OS to deactivate protection on executable memory pages to change the dispatch table.

Thanks
Stefan

--
Stefan Marr
Software Languages Lab
Vrije Universiteit Brussel
Pleinlaan 2 / B-1050 Brussels / Belgium
http://soft.vub.ac.be/~smarr
Phone: <a href="tel:%2B32%202%20629%202974" value="+3226292974" target="_blank">+32 2 629 2974
Fax:   <a href="tel:%2B32%202%20629%203525" value="+3226293525" target="_blank">+32 2 629 3525






--
best,
Eliot