Remix.run Logo
ufo 4 hours ago

The author seems to complain about a lack of stack manip expressions like dup and rot, but at least for me that's what I would expect from an average programming language stack machine. Even Java, which does have those instructions, doesn't use them --- reuse happens via local variables.

The way I see it, the difference between register and stack vms is all about the instruction encoding. Register VMs have fatter instructions in exchange for needing fewer LOAD and STORE operations. Despite the name, register VMs also have a stack.

pjjpo 3 hours ago | parent | next [-]

> Despite the name, register VMs also have a stack.

Out of curiosity what do you think about this - in spite of the name, stack machines also have yet another stack. Ok I don't like that wording, but locals are basically the stack frames people know of from their computer arch class I think.

It doesn't change the fact that Wasm operations have to have the execution stack as one or more of the operands. Seems like a stack machines to me too, though I don't know more details on why the specific design of Wasm would make optimizing compilers harder to write than JVM as the article suggests (I think?).

ufo 2 hours ago | parent [-]

As you said, it's more like CPU stack frames. In a register VM all instructions can read and write to any position in the stack frame. In a stack VM, most instructions only read and write to the top but they are often combined with LOAD and STORE instructions, which can read and write to any position in the stack frame.

U1F984 3 hours ago | parent | prev [-]

Java does use dup in some cases, e.g.

   public static void test() { 
      new Object();
   }

         0: new           #2                  // class java/lang/Object
         3: dup
         4: invokespecial #1                  // Method java/lang/Object."<init>":()V
         7: pop
         8: return
asibahi 2 hours ago | parent [-]

This `dup` seems entirely useless it actually supports the case for omitting it fron the instruction set.

layer8 an hour ago | parent [-]

The only reason it is useless in this (arguably ill-chosen) example is because the result of “new Object()” is not used (hence the pop), which is an uncommon case. If test() instead returned the new object, or would use it in some other way after the initialization, then the dup would be needed. Invokespecial consumes the object reference on the stack, hence if you want to use it after invokespecial, you have to copy or duplicate it before.