next up previous
Next: Timeless objects Up: JiST- Java in Simulation Previous: Object model and execution

Simulation time invocation

To illustrate the extended JiST object model and simulation time invocation, we return to our hello program and describe its execution step-by-step. Omitting unnecessary complexity in the interests of clarity, below are the basic operations that occur when one executes:

java jist.runtime.Main hello

There are a number of additional observations to make regarding the execution of our primitive simulation program. Note, for example, that there is no mention of concurrency. In fact, there may be multiple threads that share the simulation event queue and execute the events in parallel. The JiST kernel, however, does guarantee that events are atomic. Thus, events on the same entity are executed to completion without interruption. Entity invocations do not interrupt event processing; the invocation is merely enqueued. Also, other events may not interrupt processing, even during a sleep call. The sleep merely advances the local simulation clock. For instance, take two events $ t_1$ and $ t_2$, at times $ t=1$ and $ t=2$, respectively. Assume that the first event, during the course of its execution, calls sleep for 3 time quanta. Nevertheless, $ t_2$ will be invoked only after $ t_1$ processing is complete. In effect, the sleep call is used for scheduling outgoing invocations with delay, but not for delaying internal operations. Thus, all operations on the state of an entity occur atomically, at the simulation time of the current event.

There are also some intricacies with respect to the extended object model. For instance, only invocations on public methods of entities are rewritten into event dispatches. An entity represents an event-based interface around some internal state. This external interface, as with regular Java objects, is considered to be the set of public methods. Non-public methods are considered to be regular object methods, not entity methods, and have the regular Java invocation semantics. Furthermore, since entity method invocations are event-based, they are performed without continuation. Consequently, there can be no continuation defined. In other words, public entity methods must return void and can not statically declare any throwable exceptions. If, at runtime, an exception nevertheless occurs and escapes outside the boundary of an entity to the kernel event loop, then the system will immediately terminate the faulty simulation. For a similar reason, entities may not expose public fields. Specifically, a remote field access is equivalent to an accessor method, with a non-void return type. Likewise, static fields represent state shared across entities and are disallowed. Finally, entity constructors are treated specially. They instantiate the desired entity, but return a separator object referencing the newly created entity, in place of the object itself. In fact, it is not the constructor that is actually modified, rather the constructor calling-point right after a corresponding new instruction.

Finally, while the semantics of simulation time invocation are sufficient to use the system, it is important to understand the underlying implementation of simulation time invocation, at least at a high level. The simulation time invocations are introduced by the rewriter, which inspects all method invocation instructions to find invocations on targets that are entities. At this program location, the stack will contain the target reference (in fact, the separator object) and any arguments. The rewriter inserts bytecode instructions to pack the arguments into an object array and to rearrange the stack to hold three items: the target, a method reflection object and the invocation argument array. The invocation instruction is then converted into a call to the simulation kernel, which creates and schedules a simulation event with this information. For performance, method reflection objects are pre-generated statically, object arrays are pooled to avoid object instantiation as are the event objects, the expensive Java reflection access checks are performed once and then safely disabled and synchronization locks are escalated wherever possible. Unfortunately, the Java type system and reflection interface forces us to wrap primitive types in their object counterparts to be placed in the argument array, which incurs a small, but notable overhead. It would be nice to have the JVM extended to support the efficient ``boxing'' of primitive types, as in the CLR. Simulation developers may wish to note this fact and pass along objects instead of primitives, but only when this can be achieved without an additional object instantiation.


next up previous
Next: Timeless objects Up: JiST- Java in Simulation Previous: Object model and execution
2006-01-18