Access to arguments in the stack vm

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

Access to arguments in the stack vm

Hernan Wilkinson-3
 
Hi,
 In the implementation of the dynamically typed vm I'm doing (to give it a name) I need to get the parameters when a method gets activated.
 To do it I implemented a not-inlined method that sends the message #internalStackValue: 
 The problem is that the code for that method is not generated. The method gets removed from the methods to generate code because it access "localSP" although not directly but due to inlining #internalStackValue:
 
 How should I access the arguments then? Why I can not use "localSP"?

 The method source is:
keepArgumentTypes

<inline: false>
| additionalMethodState tempVarsTypes |
additionalMethodState := self additionalMethodStateOf: newMethod.
additionalMethodState = objectMemory nilObject ifTrue: [ ^self ].
tempVarsTypes := objectMemory followObjField: 2 ofObject: additionalMethodState.
tempVarsTypes = objectMemory nilObject ifTrue: [ ^self ].
0 to: argumentCount-1 do: [ :argIndex | 
self keepTypeInformationIn: tempVarsTypes at: argIndex for: (self internalStackValue: argIndex) ].
 I manage to solve the problem passing localSP as parameter and doing the following, but I should not be doing that:
keepArgumentTypes: sp

<inline: false>
| additionalMethodState tempVarsTypes |
additionalMethodState := self additionalMethodStateOf: newMethod.
additionalMethodState = objectMemory nilObject ifTrue: [ ^self ].
tempVarsTypes := objectMemory followObjField: 2 ofObject: additionalMethodState.
tempVarsTypes = objectMemory nilObject ifTrue: [ ^self ].
0 to: argumentCount-1 do: [ :argIndex | 
self keepTypeInformationIn: tempVarsTypes at: argIndex for: (stackPages longAtPointer: sp + (argIndex * objectMemory bytesPerOop)) ].

--
Hernán Wilkinson
Agile Software Development, Teaching & Coaching
Phone: +54-011-4893-2057
Twitter: @HernanWilkinson
Address: Alem 896, Floor 6, Buenos Aires, Argentina
Reply | Threaded
Open this post in threaded view
|

Re: Access to arguments in the stack vm

Clément Béra
 
Hi,

I think the general idea is that only the methods inlined in interpret can use localSP/localFP which are mapped to registers but only in the interpret method to make the interpreter quicker. In the rest of the code you need to used framePointer/stackPointer. Getting out of inlining in the interpreter requires a call to a method such as externalizeFPandSP which moves from the registers the value to variables, and internalizeIPandSP does the other way around.

So in your case you need to see if for interpreter performance you want your code to be inlined if the main interpreter loop, if so, then use localSP, else, use stackPointer.

Hope this helps!

Best!


On Mon, Oct 8, 2018 at 8:51 PM Hernan Wilkinson <[hidden email]> wrote:
 
Hi,
 In the implementation of the dynamically typed vm I'm doing (to give it a name) I need to get the parameters when a method gets activated.
 To do it I implemented a not-inlined method that sends the message #internalStackValue: 
 The problem is that the code for that method is not generated. The method gets removed from the methods to generate code because it access "localSP" although not directly but due to inlining #internalStackValue:
 
 How should I access the arguments then? Why I can not use "localSP"?

 The method source is:
keepArgumentTypes

<inline: false>
| additionalMethodState tempVarsTypes |
additionalMethodState := self additionalMethodStateOf: newMethod.
additionalMethodState = objectMemory nilObject ifTrue: [ ^self ].
tempVarsTypes := objectMemory followObjField: 2 ofObject: additionalMethodState.
tempVarsTypes = objectMemory nilObject ifTrue: [ ^self ].
0 to: argumentCount-1 do: [ :argIndex | 
self keepTypeInformationIn: tempVarsTypes at: argIndex for: (self internalStackValue: argIndex) ].
 I manage to solve the problem passing localSP as parameter and doing the following, but I should not be doing that:
keepArgumentTypes: sp

<inline: false>
| additionalMethodState tempVarsTypes |
additionalMethodState := self additionalMethodStateOf: newMethod.
additionalMethodState = objectMemory nilObject ifTrue: [ ^self ].
tempVarsTypes := objectMemory followObjField: 2 ofObject: additionalMethodState.
tempVarsTypes = objectMemory nilObject ifTrue: [ ^self ].
0 to: argumentCount-1 do: [ :argIndex | 
self keepTypeInformationIn: tempVarsTypes at: argIndex for: (stackPages longAtPointer: sp + (argIndex * objectMemory bytesPerOop)) ].

--
Hernán Wilkinson
Agile Software Development, Teaching & Coaching
Phone: +54-011-4893-2057
Twitter: @HernanWilkinson
Address: Alem 896, Floor 6, Buenos Aires, Argentina


--
Reply | Threaded
Open this post in threaded view
|

Re: Access to arguments in the stack vm

Hernan Wilkinson-3
 
Thanks Clément! it worked perfectly!
I did not know about the externalize/internalize stuff, I saw them everywhere but I did not understand it :-)
I there documentation or something to read about those kind of things?

Thanks!
Hernan

On Mon, Oct 8, 2018 at 4:12 PM Clément Béra <[hidden email]> wrote:
 
Hi,

I think the general idea is that only the methods inlined in interpret can use localSP/localFP which are mapped to registers but only in the interpret method to make the interpreter quicker. In the rest of the code you need to used framePointer/stackPointer. Getting out of inlining in the interpreter requires a call to a method such as externalizeFPandSP which moves from the registers the value to variables, and internalizeIPandSP does the other way around.

So in your case you need to see if for interpreter performance you want your code to be inlined if the main interpreter loop, if so, then use localSP, else, use stackPointer.

Hope this helps!

Best!


On Mon, Oct 8, 2018 at 8:51 PM Hernan Wilkinson <[hidden email]> wrote:
 
Hi,
 In the implementation of the dynamically typed vm I'm doing (to give it a name) I need to get the parameters when a method gets activated.
 To do it I implemented a not-inlined method that sends the message #internalStackValue: 
 The problem is that the code for that method is not generated. The method gets removed from the methods to generate code because it access "localSP" although not directly but due to inlining #internalStackValue:
 
 How should I access the arguments then? Why I can not use "localSP"?

 The method source is:
keepArgumentTypes

<inline: false>
| additionalMethodState tempVarsTypes |
additionalMethodState := self additionalMethodStateOf: newMethod.
additionalMethodState = objectMemory nilObject ifTrue: [ ^self ].
tempVarsTypes := objectMemory followObjField: 2 ofObject: additionalMethodState.
tempVarsTypes = objectMemory nilObject ifTrue: [ ^self ].
0 to: argumentCount-1 do: [ :argIndex | 
self keepTypeInformationIn: tempVarsTypes at: argIndex for: (self internalStackValue: argIndex) ].
 I manage to solve the problem passing localSP as parameter and doing the following, but I should not be doing that:
keepArgumentTypes: sp

<inline: false>
| additionalMethodState tempVarsTypes |
additionalMethodState := self additionalMethodStateOf: newMethod.
additionalMethodState = objectMemory nilObject ifTrue: [ ^self ].
tempVarsTypes := objectMemory followObjField: 2 ofObject: additionalMethodState.
tempVarsTypes = objectMemory nilObject ifTrue: [ ^self ].
0 to: argumentCount-1 do: [ :argIndex | 
self keepTypeInformationIn: tempVarsTypes at: argIndex for: (stackPages longAtPointer: sp + (argIndex * objectMemory bytesPerOop)) ].

--
Hernán Wilkinson
Agile Software Development, Teaching & Coaching
Phone: +54-011-4893-2057
Twitter: @HernanWilkinson
Address: Alem 896, Floor 6, Buenos Aires, Argentina


--


--
Hernán Wilkinson
Agile Software Development, Teaching & Coaching
Phone: +54-011-4893-2057
Twitter: @HernanWilkinson
Address: Alem 896, Floor 6, Buenos Aires, Argentina
Reply | Threaded
Open this post in threaded view
|

Re: Access to arguments in the stack vm

Clément Béra
 
Hi,

Not sure there is documentation specifically about that. I think the 2 sentences in the previous mail I wrote basically cover the whole idea, there are not really hidden tricks.

There's documentation about the context to stack mapping in the interpreter though which involves a lot of internal/external code, but it's a more complicated concept.

I think the general problem is that interpreters are very different from standard C programs and C compilers struggle really hard to produce good code for any interpreter that anyone writes. For good interpreter performance you need to write the exact good sequence of native instructions that execute each bytecode instruction. So people tend to write interpreters in their own abstract assembly (See V8's ignition, JSC LLInt or the openJDK assembly templates) to work around the C compiler. In OpenSmalltalkVM, it was decided to use C + GNU extension. GNU extensions allow to fix registers (IP/SP/FP) in the main interpreter loop. You can see the Gnuifier>>gnuify method in VMMaker which basically does the GNU transformation in the C code. That solves part of the problem. The StackInterpreter is between 0% and 20% slower than the OpenJDK interpreter on a wide range of benchmarks, so I'd say it's quite a good trick given the engineering power we have compared to the OpenJDK. Obviously the difference is higher in the JIT.

One of my dream is to rewrite the interpreter on top of Cog's back-end in a similar way that ignition is built on top of Turbofan backend in V8. That would allow us to boost interpreter performance but also to have quick interactions between the interpreter and jitted code allowing to use the interpreter more extensively for non frequently used code and that way we could share more code between the interpreter and the JIT. That would mean we won't really have those internal/external code. But there are so many things to do :-). 

I'm glad I could help,

Best!


On Tue, Oct 9, 2018 at 1:47 PM Hernan Wilkinson <[hidden email]> wrote:
 
Thanks Clément! it worked perfectly!
I did not know about the externalize/internalize stuff, I saw them everywhere but I did not understand it :-)
I there documentation or something to read about those kind of things?

Thanks!
Hernan

On Mon, Oct 8, 2018 at 4:12 PM Clément Béra <[hidden email]> wrote:
 
Hi,

I think the general idea is that only the methods inlined in interpret can use localSP/localFP which are mapped to registers but only in the interpret method to make the interpreter quicker. In the rest of the code you need to used framePointer/stackPointer. Getting out of inlining in the interpreter requires a call to a method such as externalizeFPandSP which moves from the registers the value to variables, and internalizeIPandSP does the other way around.

So in your case you need to see if for interpreter performance you want your code to be inlined if the main interpreter loop, if so, then use localSP, else, use stackPointer.

Hope this helps!

Best!


On Mon, Oct 8, 2018 at 8:51 PM Hernan Wilkinson <[hidden email]> wrote:
 
Hi,
 In the implementation of the dynamically typed vm I'm doing (to give it a name) I need to get the parameters when a method gets activated.
 To do it I implemented a not-inlined method that sends the message #internalStackValue: 
 The problem is that the code for that method is not generated. The method gets removed from the methods to generate code because it access "localSP" although not directly but due to inlining #internalStackValue:
 
 How should I access the arguments then? Why I can not use "localSP"?

 The method source is:
keepArgumentTypes

<inline: false>
| additionalMethodState tempVarsTypes |
additionalMethodState := self additionalMethodStateOf: newMethod.
additionalMethodState = objectMemory nilObject ifTrue: [ ^self ].
tempVarsTypes := objectMemory followObjField: 2 ofObject: additionalMethodState.
tempVarsTypes = objectMemory nilObject ifTrue: [ ^self ].
0 to: argumentCount-1 do: [ :argIndex | 
self keepTypeInformationIn: tempVarsTypes at: argIndex for: (self internalStackValue: argIndex) ].
 I manage to solve the problem passing localSP as parameter and doing the following, but I should not be doing that:
keepArgumentTypes: sp

<inline: false>
| additionalMethodState tempVarsTypes |
additionalMethodState := self additionalMethodStateOf: newMethod.
additionalMethodState = objectMemory nilObject ifTrue: [ ^self ].
tempVarsTypes := objectMemory followObjField: 2 ofObject: additionalMethodState.
tempVarsTypes = objectMemory nilObject ifTrue: [ ^self ].
0 to: argumentCount-1 do: [ :argIndex | 
self keepTypeInformationIn: tempVarsTypes at: argIndex for: (stackPages longAtPointer: sp + (argIndex * objectMemory bytesPerOop)) ].

--
Hernán Wilkinson
Agile Software Development, Teaching & Coaching
Phone: +54-011-4893-2057
Twitter: @HernanWilkinson
Address: Alem 896, Floor 6, Buenos Aires, Argentina


--


--
Hernán Wilkinson
Agile Software Development, Teaching & Coaching
Phone: +54-011-4893-2057
Twitter: @HernanWilkinson
Address: Alem 896, Floor 6, Buenos Aires, Argentina


--
Reply | Threaded
Open this post in threaded view
|

Re: Access to arguments in the stack vm

Hernan Wilkinson-3
 
Thank you again! pretty clear!
And yeah, we all have to many thing to do :-)

Cheers!
Hernan.

On Tue, Oct 9, 2018 at 9:33 AM Clément Béra <[hidden email]> wrote:
 
Hi,

Not sure there is documentation specifically about that. I think the 2 sentences in the previous mail I wrote basically cover the whole idea, there are not really hidden tricks.

There's documentation about the context to stack mapping in the interpreter though which involves a lot of internal/external code, but it's a more complicated concept.

I think the general problem is that interpreters are very different from standard C programs and C compilers struggle really hard to produce good code for any interpreter that anyone writes. For good interpreter performance you need to write the exact good sequence of native instructions that execute each bytecode instruction. So people tend to write interpreters in their own abstract assembly (See V8's ignition, JSC LLInt or the openJDK assembly templates) to work around the C compiler. In OpenSmalltalkVM, it was decided to use C + GNU extension. GNU extensions allow to fix registers (IP/SP/FP) in the main interpreter loop. You can see the Gnuifier>>gnuify method in VMMaker which basically does the GNU transformation in the C code. That solves part of the problem. The StackInterpreter is between 0% and 20% slower than the OpenJDK interpreter on a wide range of benchmarks, so I'd say it's quite a good trick given the engineering power we have compared to the OpenJDK. Obviously the difference is higher in the JIT.

One of my dream is to rewrite the interpreter on top of Cog's back-end in a similar way that ignition is built on top of Turbofan backend in V8. That would allow us to boost interpreter performance but also to have quick interactions between the interpreter and jitted code allowing to use the interpreter more extensively for non frequently used code and that way we could share more code between the interpreter and the JIT. That would mean we won't really have those internal/external code. But there are so many things to do :-). 

I'm glad I could help,

Best!


On Tue, Oct 9, 2018 at 1:47 PM Hernan Wilkinson <[hidden email]> wrote:
 
Thanks Clément! it worked perfectly!
I did not know about the externalize/internalize stuff, I saw them everywhere but I did not understand it :-)
I there documentation or something to read about those kind of things?

Thanks!
Hernan

On Mon, Oct 8, 2018 at 4:12 PM Clément Béra <[hidden email]> wrote:
 
Hi,

I think the general idea is that only the methods inlined in interpret can use localSP/localFP which are mapped to registers but only in the interpret method to make the interpreter quicker. In the rest of the code you need to used framePointer/stackPointer. Getting out of inlining in the interpreter requires a call to a method such as externalizeFPandSP which moves from the registers the value to variables, and internalizeIPandSP does the other way around.

So in your case you need to see if for interpreter performance you want your code to be inlined if the main interpreter loop, if so, then use localSP, else, use stackPointer.

Hope this helps!

Best!


On Mon, Oct 8, 2018 at 8:51 PM Hernan Wilkinson <[hidden email]> wrote:
 
Hi,
 In the implementation of the dynamically typed vm I'm doing (to give it a name) I need to get the parameters when a method gets activated.
 To do it I implemented a not-inlined method that sends the message #internalStackValue: 
 The problem is that the code for that method is not generated. The method gets removed from the methods to generate code because it access "localSP" although not directly but due to inlining #internalStackValue:
 
 How should I access the arguments then? Why I can not use "localSP"?

 The method source is:
keepArgumentTypes

<inline: false>
| additionalMethodState tempVarsTypes |
additionalMethodState := self additionalMethodStateOf: newMethod.
additionalMethodState = objectMemory nilObject ifTrue: [ ^self ].
tempVarsTypes := objectMemory followObjField: 2 ofObject: additionalMethodState.
tempVarsTypes = objectMemory nilObject ifTrue: [ ^self ].
0 to: argumentCount-1 do: [ :argIndex | 
self keepTypeInformationIn: tempVarsTypes at: argIndex for: (self internalStackValue: argIndex) ].
 I manage to solve the problem passing localSP as parameter and doing the following, but I should not be doing that:
keepArgumentTypes: sp

<inline: false>
| additionalMethodState tempVarsTypes |
additionalMethodState := self additionalMethodStateOf: newMethod.
additionalMethodState = objectMemory nilObject ifTrue: [ ^self ].
tempVarsTypes := objectMemory followObjField: 2 ofObject: additionalMethodState.
tempVarsTypes = objectMemory nilObject ifTrue: [ ^self ].
0 to: argumentCount-1 do: [ :argIndex | 
self keepTypeInformationIn: tempVarsTypes at: argIndex for: (stackPages longAtPointer: sp + (argIndex * objectMemory bytesPerOop)) ].

--
Hernán Wilkinson
Agile Software Development, Teaching & Coaching
Phone: +54-011-4893-2057
Twitter: @HernanWilkinson
Address: Alem 896, Floor 6, Buenos Aires, Argentina


--


--
Hernán Wilkinson
Agile Software Development, Teaching & Coaching
Phone: +54-011-4893-2057
Twitter: @HernanWilkinson
Address: Alem 896, Floor 6, Buenos Aires, Argentina


--


--
Hernán Wilkinson
Agile Software Development, Teaching & Coaching
Phone: +54-011-4893-2057
Twitter: @HernanWilkinson
Address: Alem 896, Floor 6, Buenos Aires, Argentina