Re: [Pharo-project] test crashing the cog vm
On Mar 22, 2011, at 2:35 PM, Alexandre Bergel wrote:
I am not saying that this is feasible with the current VM. But I am doubtful that the bytecode verification can only be done in the VM. If something get wrong, why not to raise a primitiveFailed, as 1/0 will do?
Because checking all these things at runtime will make interpretation slow.
I have the impression that you give a particular status to the bytecodes. I have the feeling that we should not.
Yes, to be interpretable without having to check at runtime.
I can realize a division, and time to time it get wrong (/0). But the VM does not crash. So, why if I evaluate the wrong bytecodes, the VM should crash?
Because we don't want to check everything, else it is too slow.
You could have the necessary guards in the VM.
Slow. Marcus -- Marcus Denker -- http://www.marcusdenker.de INRIA Lille -- Nord Europe. Team RMoD.
Exactly! :) On 03/22/2011 02:40 PM, Marcus Denker wrote:
On Mar 22, 2011, at 2:35 PM, Alexandre Bergel wrote:
I am not saying that this is feasible with the current VM. But I am doubtful that the bytecode verification can only be done in the VM. If something get wrong, why not to raise a primitiveFailed, as 1/0 will do?
Because checking all these things at runtime will make interpretation slow.
I have the impression that you give a particular status to the bytecodes. I have the feeling that we should not. Yes, to be interpretable without having to check at runtime.
I can realize a division, and time to time it get wrong (/0). But the VM does not crash. So, why if I evaluate the wrong bytecodes, the VM should crash? Because we don't want to check everything, else it is too slow.
You could have the necessary guards in the VM. Slow.
Marcus
-- Marcus Denker -- http://www.marcusdenker.de INRIA Lille -- Nord Europe. Team RMoD.
I am not saying that this is feasible with the current VM. But I am doubtful that the bytecode verification can only be done in the VM. If something get wrong, why not to raise a primitiveFailed, as 1/0 will do?
Because checking all these things at runtime will make interpretation slow.
But could not it be at compile time? I am not expert in VM. But something that I learnt from all over these years, is that if we copy what other people do, then we will just have a pale copy. Innovation begins by doing what other think it is impossible to do. Smalltalk has classes as object, whereas Java and C++ took a different stance. Smalltalk has the debugger and the profiler in the image; again, java people have a different opinion. Now, if someone say that bytecode verification can only be done in the VM, I am skeptic.
You could have the necessary guards in the VM.
Slow.
I do not know. There are guards for arrays, message sent, primitive calls, ... And it is not that slow. Alexandre -- _,.;:~^~:;._,.;:~^~:;._,.;:~^~:;._,.;:~^~:;._,.;: Alexandre Bergel http://www.bergel.eu ^~:;._,.;:~^~:;._,.;:~^~:;._,.;:~^~:;._,.;:~^~:;.
On 03/22/2011 04:52 PM, Alexandre Bergel wrote:
I am not saying that this is feasible with the current VM. But I am doubtful that the bytecode verification can only be done in the VM. If something get wrong, why not to raise a primitiveFailed, as 1/0 will do?
Because checking all these things at runtime will make interpretation slow. But could not it be at compile time?
I am not expert in VM. But something that I learnt from all over these years, is that if we copy what other people do, then we will just have a pale copy. Innovation begins by doing what other think it is impossible to do. Smalltalk has classes as object, whereas Java and C++ took a different stance. Smalltalk has the debugger and the profiler in the image; again, java people have a different opinion. Now, if someone say that bytecode verification can only be done in the VM, I am skeptic. Ok, I very much understand this point of view. That's exactly why I started Pinocchio.
I'm currently building my 4rd iteration. I started building a Smalltalk by having AST evaluation (actually I started out with self-evaluating AST objects that got evaluated by sending message... :D) . Then moved on to stack-based bytecodes. Then moved on to registered-based bytecodes (where I am now). All of my progress has been made by careful scrutinizing of the problems at hand. I did reevaluate and question all steps; and I'm a bit sad that I ended up doing it this way... But then I guess there is some inevitability in it. For example the register-based bytecodes, I had no idea that what I was doing were register-based bytecodes until I read the Lua VM description and noticed that it was exactly the same. However I do think that I learned a lot by doing it. I made the trade-offs myself and understand them a lot better than I did before. What I'm defending in this discussion isn't based on estimates but experience from building it from the ground up. And this is where I welcome everyone to do the same! It took me 2 years to get to where I am now, but maybe it goes faster for you ;) It is definitely a very worthwhile exercise. And I think because of it I'm finally at the point where I can contribute something... cheers, Toon
I see your point and I suspected you spoke according to your experience. I am just trying to make people innovate, in my own way. Another thing. Keeping the VM small will definitely help when moving to a different executing platform. It would be amazing to have the Pharo running on Javascript VM. Alexandre
Ok, I very much understand this point of view. That's exactly why I started Pinocchio.
I'm currently building my 4rd iteration. I started building a Smalltalk by having AST evaluation (actually I started out with self-evaluating AST objects that got evaluated by sending message... :D) . Then moved on to stack-based bytecodes. Then moved on to registered-based bytecodes (where I am now). All of my progress has been made by careful scrutinizing of the problems at hand. I did reevaluate and question all steps; and I'm a bit sad that I ended up doing it this way... But then I guess there is some inevitability in it.
For example the register-based bytecodes, I had no idea that what I was doing were register-based bytecodes until I read the Lua VM description and noticed that it was exactly the same.
However I do think that I learned a lot by doing it. I made the trade-offs myself and understand them a lot better than I did before. What I'm defending in this discussion isn't based on estimates but experience from building it from the ground up.
And this is where I welcome everyone to do the same! It took me 2 years to get to where I am now, but maybe it goes faster for you ;) It is definitely a very worthwhile exercise. And I think because of it I'm finally at the point where I can contribute something...
cheers, Toon
-- _,.;:~^~:;._,.;:~^~:;._,.;:~^~:;._,.;:~^~:;._,.;: Alexandre Bergel http://www.bergel.eu ^~:;._,.;:~^~:;._,.;:~^~:;._,.;:~^~:;._,.;:~^~:;.
On 03/22/2011 05:10 PM, Alexandre Bergel wrote:
I see your point and I suspected you spoke according to your experience. I am just trying to make people innovate, in my own way.
Another thing. Keeping the VM small will definitely help when moving to a different executing platform. It would be amazing to have the Pharo running on Javascript VM. That's not even that hard. I even had Pharo running on top of my own SchemeTalk already, after 2 days of hacking. I only stopped where I bumped into traits, since I didn't find any bootstrapping script for traits.
I would basically compile all the smalltalk code to equivalent schemetalk code (very easy since the models are very similar), and compile all the natives to function-calls that perform what the native should perform. These functions had names that wouldn't clash with the Smalltalk names so you couldn't refer to it directly. Obviously in the end you would have all the smalltalk code running with SchemeTalk syntax, but all the code was virgin Pharo code. Very fun stuff :) And if you do it this way, it doesn't really depend on your VM anyway, since I was executing Smalltalk code as Scheme code, not as Smalltalk bytecodes interpreted by schemecode. That's a lot faster. cheers, Toon
Alexandre
Ok, I very much understand this point of view. That's exactly why I started Pinocchio.
I'm currently building my 4rd iteration. I started building a Smalltalk by having AST evaluation (actually I started out with self-evaluating AST objects that got evaluated by sending message... :D) . Then moved on to stack-based bytecodes. Then moved on to registered-based bytecodes (where I am now). All of my progress has been made by careful scrutinizing of the problems at hand. I did reevaluate and question all steps; and I'm a bit sad that I ended up doing it this way... But then I guess there is some inevitability in it.
For example the register-based bytecodes, I had no idea that what I was doing were register-based bytecodes until I read the Lua VM description and noticed that it was exactly the same.
However I do think that I learned a lot by doing it. I made the trade-offs myself and understand them a lot better than I did before. What I'm defending in this discussion isn't based on estimates but experience from building it from the ground up.
And this is where I welcome everyone to do the same! It took me 2 years to get to where I am now, but maybe it goes faster for you ;) It is definitely a very worthwhile exercise. And I think because of it I'm finally at the point where I can contribute something...
cheers, Toon
I tried to have a look at SchemeTalk. Apparently the website is not up to date. I reached http://www.iam.unibe.ch/~verwaest/blog/?p=6 from http://scg.unibe.ch/research/schemetalk Alexandre On 22 Mar 2011, at 11:16, Toon Verwaest wrote:
On 03/22/2011 05:10 PM, Alexandre Bergel wrote:
I see your point and I suspected you spoke according to your experience. I am just trying to make people innovate, in my own way.
Another thing. Keeping the VM small will definitely help when moving to a different executing platform. It would be amazing to have the Pharo running on Javascript VM. That's not even that hard. I even had Pharo running on top of my own SchemeTalk already, after 2 days of hacking. I only stopped where I bumped into traits, since I didn't find any bootstrapping script for traits.
I would basically compile all the smalltalk code to equivalent schemetalk code (very easy since the models are very similar), and compile all the natives to function-calls that perform what the native should perform. These functions had names that wouldn't clash with the Smalltalk names so you couldn't refer to it directly.
Obviously in the end you would have all the smalltalk code running with SchemeTalk syntax, but all the code was virgin Pharo code. Very fun stuff :) And if you do it this way, it doesn't really depend on your VM anyway, since I was executing Smalltalk code as Scheme code, not as Smalltalk bytecodes interpreted by schemecode. That's a lot faster.
cheers, Toon
Alexandre
Ok, I very much understand this point of view. That's exactly why I started Pinocchio.
I'm currently building my 4rd iteration. I started building a Smalltalk by having AST evaluation (actually I started out with self-evaluating AST objects that got evaluated by sending message... :D) . Then moved on to stack-based bytecodes. Then moved on to registered-based bytecodes (where I am now). All of my progress has been made by careful scrutinizing of the problems at hand. I did reevaluate and question all steps; and I'm a bit sad that I ended up doing it this way... But then I guess there is some inevitability in it.
For example the register-based bytecodes, I had no idea that what I was doing were register-based bytecodes until I read the Lua VM description and noticed that it was exactly the same.
However I do think that I learned a lot by doing it. I made the trade-offs myself and understand them a lot better than I did before. What I'm defending in this discussion isn't based on estimates but experience from building it from the ground up.
And this is where I welcome everyone to do the same! It took me 2 years to get to where I am now, but maybe it goes faster for you ;) It is definitely a very worthwhile exercise. And I think because of it I'm finally at the point where I can contribute something...
cheers, Toon
-- _,.;:~^~:;._,.;:~^~:;._,.;:~^~:;._,.;:~^~:;._,.;: Alexandre Bergel http://www.bergel.eu ^~:;._,.;:~^~:;._,.;:~^~:;._,.;:~^~:;._,.;:~^~:;.
Grmbl. Seems broken indeed. I reinstalled it. Still some work to be done on coloring :) If you are interesting in the translation part from Smalltalk to Schemetalk, it can be found at: https://www.iam.unibe.ch/scg/svn_repos/Sources/SchemeTalk/smalltalk The parser is basically a petit-parser like PEG parser written in Schemetalk. The translator compiles the pharo filed-out sources to schemetalk code and/or loads the generated code. Then there's some stuff that avoids "bad" definitions that only serve to make pharo run fast on the pharo VM, such as "fixtemps" and whileFalse:, whileTrue: which don't convey their proper semantics but rather just recursively end up in the same method hoping that the bytecode evaluation will do the proper thing. Unfortunately I didn't write about the squeak->schemetalk conversion; since I just considered it a silly exercise ... I guess I could if someone's interested. cheers, Toon On 03/22/2011 05:23 PM, Alexandre Bergel wrote:
I tried to have a look at SchemeTalk. Apparently the website is not up to date. I reached http://www.iam.unibe.ch/~verwaest/blog/?p=6 from http://scg.unibe.ch/research/schemetalk
Alexandre
On 22 Mar 2011, at 11:16, Toon Verwaest wrote:
On 03/22/2011 05:10 PM, Alexandre Bergel wrote:
I see your point and I suspected you spoke according to your experience. I am just trying to make people innovate, in my own way.
Another thing. Keeping the VM small will definitely help when moving to a different executing platform. It would be amazing to have the Pharo running on Javascript VM. That's not even that hard. I even had Pharo running on top of my own SchemeTalk already, after 2 days of hacking. I only stopped where I bumped into traits, since I didn't find any bootstrapping script for traits.
I would basically compile all the smalltalk code to equivalent schemetalk code (very easy since the models are very similar), and compile all the natives to function-calls that perform what the native should perform. These functions had names that wouldn't clash with the Smalltalk names so you couldn't refer to it directly.
Obviously in the end you would have all the smalltalk code running with SchemeTalk syntax, but all the code was virgin Pharo code. Very fun stuff :) And if you do it this way, it doesn't really depend on your VM anyway, since I was executing Smalltalk code as Scheme code, not as Smalltalk bytecodes interpreted by schemecode. That's a lot faster.
cheers, Toon
Alexandre
Ok, I very much understand this point of view. That's exactly why I started Pinocchio.
I'm currently building my 4rd iteration. I started building a Smalltalk by having AST evaluation (actually I started out with self-evaluating AST objects that got evaluated by sending message... :D) . Then moved on to stack-based bytecodes. Then moved on to registered-based bytecodes (where I am now). All of my progress has been made by careful scrutinizing of the problems at hand. I did reevaluate and question all steps; and I'm a bit sad that I ended up doing it this way... But then I guess there is some inevitability in it.
For example the register-based bytecodes, I had no idea that what I was doing were register-based bytecodes until I read the Lua VM description and noticed that it was exactly the same.
However I do think that I learned a lot by doing it. I made the trade-offs myself and understand them a lot better than I did before. What I'm defending in this discussion isn't based on estimates but experience from building it from the ground up.
And this is where I welcome everyone to do the same! It took me 2 years to get to where I am now, but maybe it goes faster for you ;) It is definitely a very worthwhile exercise. And I think because of it I'm finally at the point where I can contribute something...
cheers, Toon
Ok Alexandre On 22 Mar 2011, at 11:40, Toon Verwaest wrote:
Grmbl. Seems broken indeed. I reinstalled it. Still some work to be done on coloring :)
If you are interesting in the translation part from Smalltalk to Schemetalk, it can be found at: https://www.iam.unibe.ch/scg/svn_repos/Sources/SchemeTalk/smalltalk
The parser is basically a petit-parser like PEG parser written in Schemetalk. The translator compiles the pharo filed-out sources to schemetalk code and/or loads the generated code. Then there's some stuff that avoids "bad" definitions that only serve to make pharo run fast on the pharo VM, such as "fixtemps" and whileFalse:, whileTrue: which don't convey their proper semantics but rather just recursively end up in the same method hoping that the bytecode evaluation will do the proper thing.
Unfortunately I didn't write about the squeak->schemetalk conversion; since I just considered it a silly exercise ... I guess I could if someone's interested.
cheers, Toon
On 03/22/2011 05:23 PM, Alexandre Bergel wrote:
I tried to have a look at SchemeTalk. Apparently the website is not up to date. I reached http://www.iam.unibe.ch/~verwaest/blog/?p=6 from http://scg.unibe.ch/research/schemetalk
Alexandre
On 22 Mar 2011, at 11:16, Toon Verwaest wrote:
On 03/22/2011 05:10 PM, Alexandre Bergel wrote:
I see your point and I suspected you spoke according to your experience. I am just trying to make people innovate, in my own way.
Another thing. Keeping the VM small will definitely help when moving to a different executing platform. It would be amazing to have the Pharo running on Javascript VM. That's not even that hard. I even had Pharo running on top of my own SchemeTalk already, after 2 days of hacking. I only stopped where I bumped into traits, since I didn't find any bootstrapping script for traits.
I would basically compile all the smalltalk code to equivalent schemetalk code (very easy since the models are very similar), and compile all the natives to function-calls that perform what the native should perform. These functions had names that wouldn't clash with the Smalltalk names so you couldn't refer to it directly.
Obviously in the end you would have all the smalltalk code running with SchemeTalk syntax, but all the code was virgin Pharo code. Very fun stuff :) And if you do it this way, it doesn't really depend on your VM anyway, since I was executing Smalltalk code as Scheme code, not as Smalltalk bytecodes interpreted by schemecode. That's a lot faster.
cheers, Toon
Alexandre
Ok, I very much understand this point of view. That's exactly why I started Pinocchio.
I'm currently building my 4rd iteration. I started building a Smalltalk by having AST evaluation (actually I started out with self-evaluating AST objects that got evaluated by sending message... :D) . Then moved on to stack-based bytecodes. Then moved on to registered-based bytecodes (where I am now). All of my progress has been made by careful scrutinizing of the problems at hand. I did reevaluate and question all steps; and I'm a bit sad that I ended up doing it this way... But then I guess there is some inevitability in it.
For example the register-based bytecodes, I had no idea that what I was doing were register-based bytecodes until I read the Lua VM description and noticed that it was exactly the same.
However I do think that I learned a lot by doing it. I made the trade-offs myself and understand them a lot better than I did before. What I'm defending in this discussion isn't based on estimates but experience from building it from the ground up.
And this is where I welcome everyone to do the same! It took me 2 years to get to where I am now, but maybe it goes faster for you ;) It is definitely a very worthwhile exercise. And I think because of it I'm finally at the point where I can contribute something...
cheers, Toon
-- _,.;:~^~:;._,.;:~^~:;._,.;:~^~:;._,.;:~^~:;._,.;: Alexandre Bergel http://www.bergel.eu ^~:;._,.;:~^~:;._,.;:~^~:;._,.;:~^~:;._,.;:~^~:;.
Can you explain rapidly register-case byte code? Stef On Mar 22, 2011, at 4:02 PM, Toon Verwaest wrote:
On 03/22/2011 04:52 PM, Alexandre Bergel wrote:
I am not saying that this is feasible with the current VM. But I am doubtful that the bytecode verification can only be done in the VM. If something get wrong, why not to raise a primitiveFailed, as 1/0 will do?
Because checking all these things at runtime will make interpretation slow. But could not it be at compile time?
I am not expert in VM. But something that I learnt from all over these years, is that if we copy what other people do, then we will just have a pale copy. Innovation begins by doing what other think it is impossible to do. Smalltalk has classes as object, whereas Java and C++ took a different stance. Smalltalk has the debugger and the profiler in the image; again, java people have a different opinion. Now, if someone say that bytecode verification can only be done in the VM, I am skeptic. Ok, I very much understand this point of view. That's exactly why I started Pinocchio.
I'm currently building my 4rd iteration. I started building a Smalltalk by having AST evaluation (actually I started out with self-evaluating AST objects that got evaluated by sending message... :D) . Then moved on to stack-based bytecodes. Then moved on to registered-based bytecodes (where I am now). All of my progress has been made by careful scrutinizing of the problems at hand. I did reevaluate and question all steps; and I'm a bit sad that I ended up doing it this way... But then I guess there is some inevitability in it.
For example the register-based bytecodes, I had no idea that what I was doing were register-based bytecodes until I read the Lua VM description and noticed that it was exactly the same.
However I do think that I learned a lot by doing it. I made the trade-offs myself and understand them a lot better than I did before. What I'm defending in this discussion isn't based on estimates but experience from building it from the ground up.
And this is where I welcome everyone to do the same! It took me 2 years to get to where I am now, but maybe it goes faster for you ;) It is definitely a very worthwhile exercise. And I think because of it I'm finally at the point where I can contribute something...
cheers, Toon
It depends what you want to get from a bytecode verifier. May be with a sealing semantics at package level (compiledMethod that can only be created once...) or something like that you could get the code loaded, the package verified and installed without having to make the vm more complex. Stef
It's a very simple idea really. Where your bytecode would previously look like pushTemp: 1 pushTemp: 2 add now it looks like: add 1, 2, 3 where 3 is the start of your original stack, for example. So rather than pushing and popping etc, you just abstractly interpret the bytecodes and figure out the stack locations where they would be pushed. And then you use this number as arguments to a copy bytecode, rather than calling "push". This avoids having to maintain a stack where you up front already know what the target index will be. You know this up front since your code is static by itself. The advantage is that you don't need to do stack-tricks to keep data around, since all the operation are simple things such as copy, loadFromOuterScope, storeInOuterScope, loadFromField, storeInField, ... So conversely to what you might have thought beforehand, you don't have "real registers" around, you just consider a stackframe to be a set of registers. And you operate on them with easy bytecodes. The advantage, in addition to it being less work and thus slightly faster by itself, is that it will later on also map better on the real hardware. The operations already look like what normal assembler operations would look like. cheers, Toon On 03/22/2011 07:00 PM, Stéphane Ducasse wrote:
Can you explain rapidly register-case byte code?
Stef
On Mar 22, 2011, at 4:02 PM, Toon Verwaest wrote:
On 03/22/2011 04:52 PM, Alexandre Bergel wrote:
I am not saying that this is feasible with the current VM. But I am doubtful that the bytecode verification can only be done in the VM. If something get wrong, why not to raise a primitiveFailed, as 1/0 will do?
Because checking all these things at runtime will make interpretation slow. But could not it be at compile time?
I am not expert in VM. But something that I learnt from all over these years, is that if we copy what other people do, then we will just have a pale copy. Innovation begins by doing what other think it is impossible to do. Smalltalk has classes as object, whereas Java and C++ took a different stance. Smalltalk has the debugger and the profiler in the image; again, java people have a different opinion. Now, if someone say that bytecode verification can only be done in the VM, I am skeptic. Ok, I very much understand this point of view. That's exactly why I started Pinocchio.
I'm currently building my 4rd iteration. I started building a Smalltalk by having AST evaluation (actually I started out with self-evaluating AST objects that got evaluated by sending message... :D) . Then moved on to stack-based bytecodes. Then moved on to registered-based bytecodes (where I am now). All of my progress has been made by careful scrutinizing of the problems at hand. I did reevaluate and question all steps; and I'm a bit sad that I ended up doing it this way... But then I guess there is some inevitability in it.
For example the register-based bytecodes, I had no idea that what I was doing were register-based bytecodes until I read the Lua VM description and noticed that it was exactly the same.
However I do think that I learned a lot by doing it. I made the trade-offs myself and understand them a lot better than I did before. What I'm defending in this discussion isn't based on estimates but experience from building it from the ground up.
And this is where I welcome everyone to do the same! It took me 2 years to get to where I am now, but maybe it goes faster for you ;) It is definitely a very worthwhile exercise. And I think because of it I'm finally at the point where I can contribute something...
cheers, Toon
On 22 March 2011 19:43, Toon Verwaest <toon.verwaest@gmail.com> wrote:
It's a very simple idea really.
Where your bytecode would previously look like
pushTemp: 1 pushTemp: 2 add
now it looks like:
add 1, 2, 3
where 3 is the start of your original stack, for example.
So rather than pushing and popping etc, you just abstractly interpret the bytecodes and figure out the stack locations where they would be pushed. And then you use this number as arguments to a copy bytecode, rather than calling "push". This avoids having to maintain a stack where you up front already know what the target index will be. You know this up front since your code is static by itself.
The advantage is that you don't need to do stack-tricks to keep data around, since all the operation are simple things such as copy, loadFromOuterScope, storeInOuterScope, loadFromField, storeInField, ...
So conversely to what you might have thought beforehand, you don't have "real registers" around, you just consider a stackframe to be a set of registers. And you operate on them with easy bytecodes. The advantage, in addition to it being less work and thus slightly faster by itself, is that it will later on also map better on the real hardware. The operations already look like what normal assembler operations would look like.
So, as i understood , a code like: someMethod | temp1 temp2 | ^ self send: temp1+temp2 with: temp2. could be represented by following: (we need 5 temps on stack: ) 1. temp1 2. temp2 3. receiver 4. - first arg for send 5. - second arg bytecode: 1.storeSelf: 3 2. storeTemp: 1 to: 4 3. storeTemp: 2 to: 5 4. send #+ to: 4 5. storeTemp: 2 to: 5 6. send #send:with: to: 3 7. return: 3 (note here, that given bytecode already contains an optimization - a context slot #5 are not overridden by #+ send, the same argument temp2 is simply reused for subsequent send (#send:with:), which is quite nice).
cheers, Toon
-- Best regards, Igor Stasenko AKA sig.
On 22 March 2011 23:20, Igor Stasenko <siguctua@gmail.com> wrote:
On 22 March 2011 19:43, Toon Verwaest <toon.verwaest@gmail.com> wrote:
It's a very simple idea really.
Where your bytecode would previously look like
pushTemp: 1 pushTemp: 2 add
now it looks like:
add 1, 2, 3
where 3 is the start of your original stack, for example.
So rather than pushing and popping etc, you just abstractly interpret the bytecodes and figure out the stack locations where they would be pushed. And then you use this number as arguments to a copy bytecode, rather than calling "push". This avoids having to maintain a stack where you up front already know what the target index will be. You know this up front since your code is static by itself.
The advantage is that you don't need to do stack-tricks to keep data around, since all the operation are simple things such as copy, loadFromOuterScope, storeInOuterScope, loadFromField, storeInField, ...
So conversely to what you might have thought beforehand, you don't have "real registers" around, you just consider a stackframe to be a set of registers. And you operate on them with easy bytecodes. The advantage, in addition to it being less work and thus slightly faster by itself, is that it will later on also map better on the real hardware. The operations already look like what normal assembler operations would look like.
So, as i understood , a code like:
someMethod
 | temp1 temp2 |
 ^ self send: temp1+temp2 with: temp2.
could be represented by following: (we need 5 temps on stack: )
1. temp1 2. temp2 3. receiver 4. - first arg for send 5. - second arg
bytecode:
1.storeSelf: 3 2. storeTemp: 1 to: 4 3. storeTemp: 2 to: 5 4. send #+ to: 4 5. storeTemp: 2 to: 5 6. send #send:with: to: 3 7. return: 3
(note here, that given bytecode already contains an optimization - a context slot #5 are not overridden by #+ send, the same argument temp2 is simply reused for subsequent send (#send:with:), which is quite nice).
oh... a little mistake i meant that instruction #5 could be optimized away, because slot #5 contents == temp2 are unchanged.
cheers, Toon
-- Best regards, Igor Stasenko AKA sig.
-- Best regards, Igor Stasenko AKA sig.
So, as i understood , a code like:
someMethod
| temp1 temp2 |
^ self send: temp1+temp2 with: temp2.
could be represented by following: (we need 5 temps on stack: )
1. temp1 2. temp2 3. receiver 4. - first arg for send 5. - second arg
bytecode:
1.storeSelf: 3 2. storeTemp: 1 to: 4 3. storeTemp: 2 to: 5 4. send #+ to: 4 5. storeTemp: 2 to: 5 6. send #send:with: to: 3 7. return: 3 Exactly. You will probably need to say how many arguments you want to pass to +, for validation purposes. And yes, as you automatically did, you would get the return value back as the location of the first argument. This has as an advantage that a "return self" does not not to do anything at all; it was already the first "argument" of the send anyway.
There are even more optimizations that could be done; such as knowing that the receiver is actually at location -1 if this is in the context of the method; thus not even needing to copy any values ... You could just apply the first send in 2, and the second one in -1 :) But obviously in that case I expect a lot of knowledge of what you do, and this might not always be possible. cheers, Toon
On 22 Mar 2011, at 19:00, Stéphane Ducasse wrote:
Can you explain rapidly register-case byte code?
And for those who still wonder why that might be useful, an article titled: 'Virtual Machine Showdown: Stack Versus Registers' @article{1328197, address = {New York, NY, USA}, author = {Yunhe Shi and Kevin Casey and M. Anton Ertl and David Gregg}, interhash = {5fbfc20a2129ec1897d295cace8e3595}, intrahash = {e329d8905cc5c93be9782963125d9644}, journal = {ACM Trans. Archit. Code Optim.}, number = 4, pages = {1--36}, publisher = {ACM}, title = {Virtual Machine Showdown: Stack Versus Registers}, url = {http://portal.acm.org/citation.cfm?id=1328195.1328197}, volume = 4, year = 2008, added-at = {2008-09-03T21:02:27.000+0200}, issn = {1544-3566}, description = {Virtual machine showdown}, biburl = {http://www.bibsonomy.org/bibtex/2e329d8905cc5c93be9782963125d9644/gron}, doi = {http://doi.acm.org/10.1145/1328195.1328197} } -- 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
participants (6)
-
Alexandre Bergel -
Igor Stasenko -
Marcus Denker -
Stefan Marr -
Stéphane Ducasse -
Toon Verwaest