2 ms·
> I've yet to see a bytecode that consistently beats a well-designed modern machine code for size, over an entire real world program, not just some set of cherr
by jcalvinowens 3y ago
> I've yet to see a bytecode that consistently beats a well-designed modern machine code for size, over an entire real world program, not just some set of cherry-picked toy examples.
This feels like a bit of a cop out to me, because one of the biggest ways you get the size advantage from a bytecode is by making it less general purpose than the machine it's running on.
Imagine a micro driving a single LED in some long arbitrary pattern. One way to do that is to just have a one-bit PCM array describing the pattern. Maybe this is semantic... but I call that a one-bit instruction bytecode with two instructions (LED ON and LED OFF), and I guarantee you no hardware ever manufactured can beat it using native code (if the pattern is over a certain length).
Sure, that's a toy example if you compare it to a general purpose CPU, but there are a lot of real microcontrollers out there doing jobs that simple.
- kragen 3y agothat's a thing you can do, and there are lots of sources of inspiration for that kind of thing; i'd point at the pico/rp2040's pioasm instruction set, the vt52's instruction set (see the dec manuals on bitsavers), and ken shirriff's analysis of the 8086's microcode http://www.righto.com/2023/04/8086-microcode-string-operations.html http://www.righto.com/2023/04/8086-microcode-string-operatio... for examples but i think you can also often get some advantage by going in the other direction; for example, the smalltalk-80 virtual machine has bytecode range 176–207 dedicated to 'send arithmetic message' and 'send special message' bytecodes which i think send messages with the selectors +, -, <, >, <=, >=, =, ~=, *, /, \\\\, @, bitShift:, //, bitAnd:, bitOr:, at:, at:put:, size, next, nextPut:, atEnd, ==, class, blockCopy:, value, value:, do:, new, new:, x, and y. almost all of the time these boil down to a regular cpu instruction or two, because the receivers are built-in classes with primitive methods implementing those messages, but a method containing them can also be applied to objects that implement different methods for them (large integers being the most common example). this implicitly makes smalltalk methods for things like sorting, data structures, and numerical algorithms polymorphic over arbitrary data types, as in ocaml. so you can get by with a single generic version of the subroutine instead of various specialized versions