Register VM
This a WIP PR that transitions the current stack based VM to a register based VM.
Changes
- [x] Implement mechanism for allocation registers
- [ ] Transition all opcodes to the register based
- [ ] Fix printing of instructions
- [ ] Remove all stack manipulation opcodes (pop, push, swap, etc...)
- [ ] Remove temporary opcodes and functions used for the transition.
Test262 conformance changes
| Test result | main count | PR count | difference |
|---|---|---|---|
| Total | 50,254 | 50,254 | 0 |
| Passed | 46,067 | 46,072 | +5 |
| Ignored | 1,634 | 1,634 | 0 |
| Failed | 2,553 | 2,548 | -5 |
| Panics | 0 | 0 | 0 |
| Conformance | 91.67% | 91.68% | +0.01% |
Fixed tests (5):
test/language/expressions/super/prop-expr-getsuperbase-before-topropertykey-putvalue-increment.js (previously Failed)
test/language/expressions/super/prop-expr-getsuperbase-before-topropertykey-putvalue-compound-assign.js (previously Failed)
test/staging/sm/class/superPropIncDecElem.js (previously Failed)
test/staging/sm/class/superPropDerivedCalls.js (previously Failed)
test/staging/sm/class/superPropFor.js (previously Failed)
The failing test is due to #3907 , in any case I'll work on always returning i32 for increment.
@HalidOdat Do you have the time to work on this at the moment? If not, I can see if I can make some progress on the PR.
I'm quite busy at the moment, but feel free to work on it! 😊
@jedel1043 @HalidOdat Could you give this a look? I was looking into making some some changes to some opcodes, but didn't want to rebase this all the time, so it would be nice if we could merge it soon.
Can we treat them as "proper" registers, pushing and popping from the stack when we need to avoid clobbering, or are there some limitations with this approach that I'm not seeing right now?
As far as I can see that approach would be a lot more complex, both from the runtime and probably especially in the bytecompiler. With the current approach, we have the benefit of having a pretty simple mapping of ByteCompiler registers and the runtime register storage.
Also, I have not tested this, but I would guess that having a fixed number of registers that spill over to the stack would cause more copys than this approach when copying from and to the stack. Or at least the performance with this approach is probably more consistent, since we have the max number of used registers and can allocate the required registers in one allocation (if alloc is needed).
[...] with the disadvantage of having to reserve a new set of registers each time you make a call, even if you don't use all of them.
Since the register storage is essentially a sliding window, note that after we hit the maxium call depth for a program, there will be no allocations. But the question of avoiding register reservation if we do not use them, because of branching, etc. in the code is definitley interesting. As far as I can see, you are right, solving this would require a more dynamic register storage at runtime. But I'm not sure if that is worth the additional complexity.
[...] I'm wondering why we need to pass the registers as if they were "external state" from the VM.
Do you mean why the extra Registers type exists? I added a section in the PR description. Basically I did this just to avoid having to clone register values when passing them to functions that require &JsValue but also &mut Context.
Some benchmarks
Main
PROGRESS Richards
RESULT Richards 177
PROGRESS DeltaBlue
RESULT DeltaBlue 148
PROGRESS Encrypt
PROGRESS Decrypt
RESULT Crypto 145
PROGRESS RayTrace
RESULT RayTrace 401
PROGRESS Earley
PROGRESS Boyer
RESULT EarleyBoyer 524
PROGRESS RegExp
RESULT RegExp 86.9
PROGRESS Splay
RESULT Splay 644
PROGRESS NavierStokes
RESULT NavierStokes 348
SCORE 250
This PR
PROGRESS Richards
RESULT Richards 184
PROGRESS DeltaBlue
RESULT DeltaBlue 155
PROGRESS Encrypt
PROGRESS Decrypt
RESULT Crypto 146
PROGRESS RayTrace
RESULT RayTrace 378
PROGRESS Earley
PROGRESS Boyer
RESULT EarleyBoyer 497
PROGRESS RegExp
RESULT RegExp 85.1
PROGRESS Splay
RESULT Splay 700
PROGRESS NavierStokes
RESULT NavierStokes 406
SCORE 257