VM
The VM is configurable, to include more or less support of high-level programming features. For small devices only minimal configuration will be used. Some high-level features and legacy application’s support (unmodified Java or .NET applications) will be installable – in fact, they will be designed as ‘system libraries’ that will provide extension’s support through unsafe code. See Appendix 1.
Some parts of VM may be splittable between a host (server) and a target (small device). For instance, verification and compilation stages may be fully done on host and uploaded to the target as native binary (normally for weakest devices), or partially verifier/compiled on host and partially on target, or completely verified and compiled on target. See Appendix 2.
Added features for low-level programming (available to system code and for trusted/signed applications):
- Support for unsafe instructions and target-specific native code.
- Support for wider range of instructions – unsigned integers, rotation of bits, access to packed fields and so on.
- Support for manual memory management (memory areas with manual allocation and releasing of data, for non-movable data, for read-only data and so on) – additional to GC. Application-level hints to GC. See Appendix 3.
- Support of structures, unions and tuples, allocated in heap, stack, as array elements.
- Tagged structures (object instances, tagged unions, tuples, etc) with only 1 word header.
- Separate ‘types’ from ‘classes’ – classes are templates, types are concrete types.
- Run-time types have information and methods for safe checking of parameterized types, immutable data, memory class (heap/stack/const areas or memory), and others constraints.
- Support of manual scheduling (disable/enable preemption, asynchronous calls, fibers), and wider range of synchronization primitives (mutexes, semaphores, critical sections, etc).
- Pointers and pointer arithmetic. Like in .NET, there will be managed and unmanaged pointers.
- Inner methods, pointers to methods and closures. Pointers to stack frames (to be used by closures and inner methods, non-inlinable ‘finally’ blocks, for frames allocated in heap).
- Wider range of call primitives, for instance – tail-recursion calls. There will be hints for call-conventions (like passing arguments through reserved registers and so on).
Distribution format will be compact and portable. There will be minimal redundant information in distribution code, mostly optimization hints or verification helpers. Optimization hints (often unsafe – like ‘do not check for null this reference’) can be proved by host computer, but small devices will be too weak to verify them. For untrusted libraries and applications these unsafe hints will be ignored and run-time checks will be used. Alternatively, the device will be able to ask a trusted host computer to verify these unsafe optimization hints and use them even for untrusted applications. See Appendix 2.
For small devices the whole code will be compile into native code, which will be as optimized as native code (due to optimization hints). Weakest devices will be able to ask trusted host computers to compile portable code into their native code. High-level devices may use mixed interpreted/native execution model. See Appendix 4.
Legacy applications support (optional):
Most of Java/.NET features will be emulated. For example, a structure of Java/.NET object will include additional fields for synchronization and hash code; types will have pointers to virtual tables and so on. Each Java/.NET class will store information for reflection support, serialization, and so on – while native applications will be able explicitly specify which classes needs these additional info, So, each Java/.NET object and class will typically require more memory. Classes from standard Java or .NET libraries will be implemented as thin wrappers over our standard libraries.
For native applications code will be pre-linked and pre-compiled (into device-specific bytecode and native code), initialization of applications will be static. Java/.NET applications will use dynamic initialization of classes by run-time checks before each of static method and field access, that is will follow Java/.NET semantic by the price of slower execution.
Unlike Java/.NET there will be no signatures for methods. This is to save space, and due to significantly extended type system in our VM (see ‘programming language’). Signatures are, in fact, a kind of method constraints, and like all others constrains in our VM, may or may not be stored on the target. See Appendix 2.
The VM will support both multithreading and multitasking, and will be designed to share between processes as much data and code as possible (see ‘libraries’). The multitasking will be done inside a single instance of VM, this will be possible due to redesigned library (see ‘libraries’).
Additional features for high-level programming (optional, installable, see Appendix 1, 4):
- Changing object’s ‘state’ by changing its vtable.
- Extendable set of method’s invocations – multimethod calls, pattern-matching calls, sending messages and so on.
- Native support for ‘reflection’ calls and field’s access (mostly for scripts and languages with semantic close to SmallTalk).
- Stack frames allocated in heap (accessed through frame pointers). May be used for continuation, backtracking and finit-automatos, method’s serialization.
- Multiple inheritance: a) using ‘interfaces’ that have fields (accessible by getter/setter calls) and default implementation of methods; b) using delegation.
- Dynamic object, to which methods and data can be added/changed at run-time.
- Mixed interpreted and native code execution. Interpreted bytecode may make code size significantly smaller (more then 2 times), and can be used for space-optimized code.