| ▲ | fweimer a day ago | |||||||
It's still beneficial on some x86-64 implementations to rewrite indirect jumps (as used in PLT stubs) to direct jumps when feasible. For example, AMD says this about the Zen 4 architecture: > Only a limited number of indirect targets that cross a 64MB aligned boundary relative to the branch address can be tracked in the indirect target predictor. Software should limit the number of indirect branch targets that cross such a boundary. And one way doing this is to replace the indirect branch with a direct branch, which supports a 32-bit signed displacement. | ||||||||
| ▲ | inigyou a day ago | parent [-] | |||||||
It's pretty much always beneficial to do something more directly. Doing less work is always better than doing more work. The slowness of modern software is the result of a stack of abstractions acting like a stack of interpreters. You write something in React, that manipulates a React object tree and shadows it to a DOM, which gets shadowed to an internal object tree which gets laid out and shadowed to a stack of GPU layers which gets written out as drawing commands... When you want to scroll up there's so much work to do. To make it fast, cut through layers and minimize work. In the 1990s, scrolling up meant calculating how many pixels to scroll, blitting that many pixels in the main framebuffer (usually GPU accelerated) and then rendering the new pixels at the bottom. There wasn't even a double buffer. Very little abstraction there, just the shortest path to achieve the desired result. The GPU driver did abstract the blit and rendering operations, of course, and the mouse driver abstracted the scrollwheel event, and you may have a wrapper component in your GUI tree that manages a viewport over a larger virtual component, but it's all kept as direct as practical. I can't imagine any electron app using the blit-pixels-up approach. I remember once learning of a runtime environment that would inline class functions. For example they wrote an OS, and if you had an object of a SATA hard drive class, it would copy the function code and inline the drive ID. I don't remember how well it worked for them. A related idea is the "tracing JIT". You know how you expect a JIT to translate one function at a time? A tracing JIT doesn't - it follows the program logic wherever it goes, through whatever control flow, and compiles all of it until it decides to stop. The most well known implementation is probably LuaJIT. | ||||||||
| ||||||||