[HN Gopher] A JVM in Rust part 5 - Executing instructions
       ___________________________________________________________________
        
       A JVM in Rust part 5 - Executing instructions
        
       Author : andreabergia
       Score  : 66 points
       Date   : 2023-08-28 18:59 UTC (4 hours ago)
        
 (HTM) web link (andreabergia.com)
 (TXT) w3m dump (andreabergia.com)
        
       | bialpio wrote:
       | Rust noob here so please be gentle - can someone explain why in
       | `Vm<'a>` the lifetime is needed? I see that in tests,
       | `Vm<'static>` gets created, presumably because there's nowhere to
       | grab a better lifetime from? But if that's the case, would it be
       | possible to express this in a different way? ISTM that Vm owns
       | everything it needs, so is there a way to avoid bubbling the
       | lifetime up?
       | 
       | Similar question applies to ClassManager - it already owns all
       | the classes (they are in an arena), so it looks like a lifetime
       | is needed because there's no way to say "things live as long as
       | ClassManager lives" w/o introducing the lifetime at
       | `ClassManager<'a>` level...
        
         | andreabergia wrote:
         | The problem arises by the fact that `Class` needs to refer to
         | other classes:                   pub struct Class<'a> {
         | pub superclass: Option<ClassRef<'a>>,         }         pub
         | type ClassRef<'a> = &'a Class<'a>;
         | 
         | Given that classes are managed by the arena, I know the
         | reference will not be dangling thanks to the 'a lifetime.
         | 
         | Initially I had implemented this with raw pointers, without
         | lifetimes, but then I switched to the reference because it felt
         | more "idiomatic" and I had to put the lifetimes just about
         | everywhere to make the compiler happy.
         | 
         | If there are better ways to do this, I would be really happy to
         | learn, though!
        
           | bialpio wrote:
           | Yeah, I think I understand why you had to write it this way,
           | but the fact that this lifetime needs to be bubbled up so far
           | up is really non-intuitive to me.
           | 
           | > If there are better ways to do this, I would be really
           | happy to learn, though!
           | 
           | Me, too. :) I find myself limited by my way of thinking here,
           | coming from C++ ("I _know_ it lives long enough, why don't
           | you let me express this?").
        
         | skitter wrote:
         | You're right there - It looks like the author is trying to
         | express "this lifetime lasts as long as the VM exists", which
         | isn't possible to express in Rust. For VM::new, the callsite
         | just picks a lifetime that lasts long enough - even if that
         | outlasts the VM, making the lifetime useless. This is a bug and
         | unsound.
        
           | bialpio wrote:
           | My understanding is that if Rust let you compile it, then
           | there is no bug with a lifetime (the code doesn't use
           | `unsafe`). There may be something magical happening under the
           | hood that I do not fully understand, but in Rust I trust. ;)
        
             | skitter wrote:
             | Your understanding of Rust is correct, but the code uses
             | unsafe: https://github.com/andreabergia/rjvm/blob/93e7e48db
             | 085e780b0...
             | 
             | As a result, when the VM gets dropped, the memory gets
             | deallocated even if there are still objects that reference
             | it.
             | 
             | Somewhat related, there also is the issue that when you
             | create multiple VMs, you can use classes/objects/...
             | created by one VM with another.
        
               | bialpio wrote:
               | IIUC this should be fine - MemoryChunk doesn't seem to
               | deallocate the memory (so we leak), unless there's a
               | dealloc somewhere (sorry, not logged in to GH so cannot
               | search). Which is not the worst outcome here, because as
               | you said, we don't want to deallocate this memory since
               | there may be places that still refer to it...
               | 
               | As for where the static lifetime gets into play, VM
               | creation doesn't use unsafe & compiler is happy about it,
               | even though ISTM that there could be a tighter bound on
               | the lifetime? https://github.com/andreabergia/rjvm/blob/9
               | 3e7e48db085e780b0...
        
               | skitter wrote:
               | VM creation is using unsafe (the line I pointed out
               | above). You're right, I can't find any deallocation
               | either - but weirdly it /does/ segfault (or sometimes
               | have other memory related errors) if I drop the VM while
               | it's heap is still referenced.
               | 
               | The thing with a tighter bound on the lifetime is that VM
               | carrying a lifetime for itself is fundamentally flawed. A
               | solution would be to remove said lifetime, and have all
               | methods on VM that return lifetimed objects take said
               | lifetime from the reference to the VM.
        
       | skitter wrote:
       | When storing an object in an array, the value is checked to be a
       | Value::Object (which can't be null), but you also have
       | Value::Null, so storing null in an array fails (I think). Storing
       | null in local variables, a static field or an instance field
       | works fine.
        
       | hnarn wrote:
       | From the first post in the series:
       | 
       | > I am very happy with what I have learned, about Rust and about
       | how to implement a virtual machine. In particular, I am super
       | happy about having implemented a real, working, garbage
       | collector. It's quite mediocre, but it's mine and I love it.
       | Given that I have achieved what I set out to do originally, I
       | have decided to stop the project here. I know there are bugs, but
       | I do not plan to fix them.
       | 
       | Toy projects are fine, but I just think this should be pointed
       | out clearly that this is not a serious, ongoing project.
        
         | andreabergia wrote:
         | Well, I think it is written rather clearly in the first blog
         | post of the series and in the github readme, whose second line
         | is:
         | 
         | > Important note: this is a hobby project, built for fun and
         | for learning purposes.
         | 
         | I am not going to repeat that in every part of the series. :-)
        
           | hnarn wrote:
           | I never said you should, but I probably would because another
           | top level comment on this post currently says that they're
           | "curious how far it will progress". Clearly it's not obvious.
        
             | pvg wrote:
             | You can reply to toplevel comments.
        
         | [deleted]
        
       | unwind wrote:
       | Nice and detailed, thanks! As a struggling Rust n00b it's
       | instructive with these kinds of walk-throughs.
       | 
       | Found a typo: "[...] and the program counter will be
       | implemented." -- the last word qouted should be "incremented",
       | right?
        
         | andreabergia wrote:
         | Thanks, fixed!
        
       | tracker1 wrote:
       | Pretty interesting to see the progress on this. Wonder if any of
       | the JVM devs are looking at this, and curious how far it will
       | progress.
        
         | whizzter wrote:
         | Maybe they bookmarked to see if there'll appear fun stuff
         | later, it's still pretty much in the gruntwork phase of adding
         | definitions/loading/basic interpretation to Rust. (Not working
         | on any official projects myself but the experiments I did was
         | in C or Java itself and with the latter you get tools like ASM
         | doing gruntwork quickly)
         | 
         | One funny/annoying part of implementing a Java runtime is that
         | you want mostly coherent handling of basic classes like Object,
         | Class, String,etc.. (don't want tons of special cases in a
         | JIT,etc) but the reflection data that defines Object and Class
         | contains String's (That inherits from Object for a fun circular
         | dependency).
         | 
         | For the most complete runtime I did (supported basic
         | reflection,etc) I went with faux-object's,strings,etc when
         | starting up created from C definitions that mirrored the real
         | object shapes and then once far into loading walked the heap to
         | modify the faux-objects to point the vtables to the actually
         | loaded types for those classes.
        
       | FrustratedMonky wrote:
       | So can we have a JVM written in Rust, running on WASM, running
       | some Java, running MineCraft?
        
         | bhawks wrote:
         | With Minecraft simulating a 8bit games -
         | https://www.pcworld.com/article/559794/8-bit-computer-proces...
        
         | [deleted]
        
         | airstrike wrote:
         | only if that MineCraft runs Terraria running Pong
        
           | worrycue wrote:
           | Take it full circle. Minecraft running Terraria emulating a
           | 32-bit RISC-V CPU running Pong written in Rust - someone
           | already did the latter part I believe,
           | https://youtu.be/zXPiqk0-zDY?si=M0IHSzRLkaddwwKC
        
       ___________________________________________________________________
       (page generated 2023-08-28 23:01 UTC)