5 comments

  • jhallenworld an hour ago

    >V8 emits a near-jump for all forward jumps. If the target ends up too far away, the near-jump target is adjusted to a jump pool entry that contains a long-jump to the actual target

    This sounds weird to me... Why not assume that all jumps need to be long to start with (so that the code is valid), then relax them to short jumps during an N-pass optimization stage- so that you get the smallest possible code?

  • brucehoult a month ago

    Quote, because unlike on Reddit I couldn't figure out how to do multi para > quotes with code here.

    ------

    Compressed pointers reduce the need for memory by storing pointers as 32-bit unsigned offsets relative to a base register. Decompressing the pointers just consists of adding the offset and register together. As simple as this sounds, it comes with a small complication on our RISC-V 64-bit port. By construction, 32-bit values are always loaded into the 64-bit registers as signed values. This means that we need to zero-extend the 32-bit offset first. Until recently this was done by bit-anding the register with 0xFFFF_FFFF:

        li   t3,1
        slli t3, t3, 32
        addi t3, t3, -1
        and  a0, a0, t3
    
    Now, this code uses the `zext.w` instruction from the Zba extension:

        zext.w a0, a0
    
    -----

    This is so strange. Does no one at Google know RISC-V? This has *never* needed more than...

        slli a0, a0, 32
        srli a0, a0, 32
    
    And if they're going to use `Zba`, and zero-extend it and then add it to another register, then why use a separate `zext.w` instruction and `add` instead of ...

        add.uw decompressed, compressed, base
    
    ... to zero extend and add in one instruction??

    After all, `zext.w` is just an alias for `add.uw` with the `zero` register as the last argument...

    They also could have always simply stored the 32 bit offset as signed and pointed the base register 2GB into the memory area instead of using x86/Arm-centric design.

      floitsch 5 hours ago

      You are absolutely right, and a follow-up CL fixed the non-Zba code path. At the time of writing of the blog post, the generated code was however still using the 4 instructions instead of just two.

      V8 is a huge project and ports almost have to start from backends of existing architectures. Over time we (I recently worked on the RISC-V port) improve the situation.

      Note that it's also crucial to stay somehow similar to the x86 and ARM backends as the V8 team frequently makes changes to these and keeping up with them would be a nightmare if the RISC-V backend was too different.

      "Does no one at Google know RISC-V" This work wasn't done by Google. Also, you don't hire RISC-V experts, but V8 experts (or other similar VMs) for such a port. I, for example, had never worked with RISC-V before. As such, it can happen that some code of the RISC-V backend is written by engineers that aren't yet experts in RISC-V.

      dzaima 4 hours ago

      And, even if not that, the 0x0000_0000_FFFF_FFFF constant could be generated via 2 instrs of

          li    a0, -1
          srli  a0, a0, 32
      
      That said, codegen of constants in RISC-V is a whole insane crazy art-form to do well (especially for a JIT where "try a hundred different strategies" means slow compilation), all to have the hardware rediscover what was already perfectly-known in the first place. (granted, there's a size benefit in cases where there is a good compact form)
      spankalee 21 hours ago

      > Does no one at Google know RISC-V?

      These are not current Googlers.