[Hi kayamon, I am presuming you're Richard, if I'm mistaken in that please let me know.]
Collected together for one response ...
> On a machine where programs are supplied as bytecode,
> there are indeed two disjoint regions.
> The bytecode sits in it's own region. You can't
> touch it from the data region.
Doesn't that depend on how you define the byte code? If I define byte codes as follows,
0x01 0xnn 0xmm load a byte from offset 0xnnmm in memory.
0x02 0xqq load qq into accumulator immediate
0x03 0xnn 0xmm store accumulator into 0xnnmm in memory
0x04 0xnn 0xmm set program counter to 0xnnmm
0x05 increment accumulator
Then I put
02 00 05 03 00 01 04 00 00
Into memory, and "run" my byte code, This program self modifies the load immediate value continuously.
When Java defined its byte code it went out of its way to avoid 'pointer arithmetic' to make the language safer but even in Java's heap model the memory to store data and executable content is the same memory, it is an artifact of the Java byte code definition that it doesn't allow for self modifying Java code, it has nothing to say about byte code in general. And the point where things get confusing for me is that architecture is reasoning about structure in general, where as implementation is reasoning about structure in specifics. So there is nothing architecturally significant about byte codes with respect to computer architecture, other than you can simulate a variety of architectural choices by how you define your byte codes.
> So every program needs to be wrapped in an
> additional VM?
No. The point was that your blog post conflated computer architecture with an implementation choice made by a particular vendor. Many vendors have chosen to create implementations which make implementing self modifying code difficult. They have their reasons, and you elucidated on two of them, rights management and security.
That they have done so, gives them some benefit, and it comes at some cost to you, the developer.
When looked at from a cost / benefit point of view, I would be interested to read about how those design choices constrain your ability to deliver a compelling game experience, or a needed capability. To often these things are only discussed in terms of what they do for party A or party B and rarely do we get some thinking on what we cannot have because of the constraints imposed by their implementation choice.
You're absolutely right that bytecodes in general are just like any other instruction set, so can be modified etc.
I guess I'm using the term 'bytecode' to refer to systems such as Java, where they don't let you mess around with it much. It's almost always the case for any implementation of a bytecode system that they don't treat it as writeable data.