4 ms·
I use Uxn's self-modification powers quite a bit, I use them mostly for routines that runs thousands of times per frames, so I don't have to pull literals from
by entaloneralie 4y ago
I use Uxn's self-modification powers quite a bit, I use them mostly for routines that runs thousands of times per frames, so I don't have to pull literals from the stack, I just can just write myself a literal in the future and have it available. I wonder, what about this makes a native code compiler difficult, is it because most programs protect against this sort of behaviors? or that programs are stored in read-only memory?
Some of the emulator sandbox the file device, it is likely to be the way that all the emulators will work eventually.
- csande17 4y ago> I wonder, what about this makes a native code compiler difficult, is it because most programs protect against this sort of behaviors? or that programs are stored in read-only memory? Say you're trying to "translate" a Uxn program into x86 code. The easiest way to do this is by going through each of the instructions in the program one by one, then converting it to an equivalent sequence of x86 instructions. (There is a little complexity around handling jumps/branches, but it's not too bad.) But if the Uxn program is allowed to change its own code at runtime, that kind of conversion won't work. The Uxn program can't change the x86 code because it doesn't know what x86 code looks like--it only knows about Uxn code. There are some ways around this, but either they're really slow (eg by switching back to an interpreter when the Uxn code has been modified) or much more complex (eg a JIT compiler) or don't work all the time (due to the halting problem).
- syntheweave 4y agoIt's ultimately a hardware-dependent answer. Self-modifying code fell out of fashion in the 1990's, once pipelined and cached code execution became the norm in desktop computing. From that point forward, correct answers to how to optimally use your hardware become complex to reason about, but generally follow the paradigms of "data-driven" coding: you're designing code that the CPU understands how to pipeline(and therefore is light on branching and indirection during inner loops), and data that the CPU can cache predictably(which leads to flat, array-like structures that a loop will traverse forward through). Therefore what compilers will actually do is reorder program behavior towards optimal pipeline usage(where doing so doesn't break the spec). This has clear downsides for any programming style that relies on knowing instruction-level behavior. And it is so hard to keep up with the exactly optimal instructions across successive generations of CPU that in the majority of cases, humans just never get around to attempting hand optimization. The benefit of defining a VM is that you can define whatever is optimal in terms of pragmatic convenience - if you want to write programs that have a certain approach to optimization, you can make some instructions, uses of memory or styles of coding relatively faster or slower, and this leads to an interesting play space for programmers who wish to puzzle through optimization problems. But unless it also happens to represent the actual hardware, it's not going to achieve any particular goal for real performance or energy usage - at least, not immediately. Widespread adoption motivates successively more optimal implementations. But that logic makes it hard to justify any "starting over" kind of effort, because then you end up at the conclusion that the market is actually succeeding at gaining efficiency through its fast-moving generational improvements, even if it does simultaneously result in an environment of obsolescence as the ecosystem-as-a-whole moves forward and leaves some parts behind. An alternate path forward, one which can integrate with the market, is to define a much more narrow language for each application you have in mind, and be non-particular about the implementation, thus allowing the implementation to become as optimal as possible given a general specification. This task leads, in the large scale, towards something like the VPRI STEPS project, where layers of small languages build off of each other into a graphical desktop environment.