David Chisnall's CPU Feature Wishlist
- Polymorphic Instructions and Typed Memory
- User Mode Traps
- Hardware Sparse Arrays
- Mondrian Memory Protection
- Message Passing Primitives
- Conclusions
The current generation of CPUs are all designed with ALGOL-family languages in mind. With the current transition from x86 to ARM (which already has instruction-set extensions for Java) in a lot of places, it seems like a good time to list a few features I'd like to see added to a modern architecture for better supporting dynamic languages.
The big difference between a typical ALGOL-family language, such as C, and a classical RISC instruction set is that the ALGOL-family language supports subroutines (also called procedures or, misleadingly, functions). Rather than joining bits of the program with a series of conditional jumps, component parts of the program are in semi-isolated components that return control to the last point of execution when they finish. CPUs often include a CALL instruction that encapsulates this behavior.
Dynamic languages have a layer of indirection in the way. On every sub-program invocation (message send or method call), a function is run to determine which subroutine should be executed. This is the main cause of dynamic language programs being slow. The other is related to the type systems used in these languages.
Polymorphic Instructions and Typed Memory
In most existing architectures, memory is seen as an array of bytes (or words) and instructions determine the type of the value when it is operated on in a register. I would like to see this pattern reversed, as it was in architectures like the B5000 and some Lisp machines. Each word should contain a type tag indicating whether it's an integer, a floating-point value, a data pointer, or an object pointer. These four types can be determined with a 2-bit type tag on each word. Instructions would then use these tags. If you issued an ADD instruction, the types of the two values would be used to determine which operation actually took place. This approach allows very efficient implementation of Smallint in Smalltalk and the Number objects in JavaScript. Operations such as sending a + message are mapped to ADD instructions. If the receiver is an object pointer, rather than an integer (or a double), then a trap (more on this in the next section) will allow it to be handled by a message send.
This change is particularly important for a language like JavaScript. JavaScript is a pure object-oriented language, in which everything is an object. When you write a + b in a static language, it knows what the types of a and b are, and it can issue an ADD instruction or (in a language like C++) call the correct function to perform the addition. In JavaScript, the behavior is different depending on the types. If a is a Number, you want to perform a double-precision floating-point addition on the two values. The cost of doing a method lookup is significantly greater than the cost of the addition, so you really don't want to have to do a lookup every time. A modern JavaScript implementation does a lot of tricks—type inference and compiling specialized versions of the code—to avoid this overhead. An instruction set with typed values would eliminate the need for these tricks, and would dramatically reduce instruction cache usage when running these languages.