JSR-282 SI 101.0 Passing arguments to enter() and executeInArea() ------------------------------------------------ Summary --------------------- A way to pass arguments to enter() and executeInArea() methods without having to allocate an object per use. Specification References --------------------- 1) A set of new methods in class MemoryArea. 2) One new class Problem being Addressed --------------------- We often run into situations where we need to pass some arguments to enter() or executeInArea() methods, but the only way to do that is to put them in a subclass of Runnable and pass that to enter(). For example, say we want to do a String operation like: int xid .... String sid = "ID="+xid; We are currently working in ImmortalMemory. We are prepared to have the resulting string in ImmortalMemory, but this statement will also create and Integer, a StringBuffer and a char[] object which will all be garbage after this statement. That will be a waste of ImmortalMemory. So we want to do the operation in Heap, or some other reclaimable ScopedMemory, and intern() the result. But even that requires allocating an object of a subclass of Runnable. Proposed Solution Summary --------------------- My proposal for this situation is to have a way to pass arguments to the enter routine, in addition to the Runnable argument, which can then be passed to the run() method without allocating any other object. Then we can have one statically allocated Runnable object and pass the other arguments directly to enter, something like class myr extends .... { public String run(int x) { return ("ID="+x).intern(); } static s = new myr(); } .... String sid = HeapMemory.instance().enter(myr.s, xid); This does not waste any memory. The way we do this is little tricky and not most elegant, but doable. First I will give a small example to explain the basic idea, and then the complete proposal. We define an class similar to Runnable. class RunnableI { public Object run(int i); } Then we add a new method to MemoryArea: public Object enter(RunnableI r, int x). The semantics of this is is to call r.run(x) in the memory area represented by 'this', and return the value returned by the run(int) method. The unelegant part is that we have to add 'several' enter() and executeInArea() methods; one for each argument signature we want, and that set has to be specified in the SPEC. So there will be a tradeoff of how many functions we want to add and how much flexibility we want to give. ============ COMPLETE PROPOSAL =============== class RunnableI { // suggestions for a better name ? public Object run(long a, long b); public Object run(Object a, long b); public Object run(Object a, Object b); // should we add more ? }; Additional methods in MemoryArea: public Object enter(RunnableI r, long a, long b); public Object enter(RunnableI r, Object a, long b); public Object enter(RunnableI r, Object a, Object b); public Object executeInArea(RunnableI r, long a, long b); public Object executeInArea(RunnableI r, Object a, long b); public Object executeInArea(RunnableI r, Object a, Object b); ============================================== Semantics --------------------- The class RunnableI is a real class, not an abstract class or interface. The implementation provides a version of this class, whose methods throw java.lang.UnsupportedOperationException unconditionally. The user needs to make a subclass and override at least one of the methods, and then corresponding enter() or executeInArea() can be called. The enter() or executeInArea() methods call the corresponding run() method of the given RunnableI, passing the incoming arguments, and returns the value returned by the run(). If the return value is not accessible in the caller's context, a ThrowBoundaryError will be thrown. Discussion Points --------------------- 1) Is it worth adding that many extra methods to the MemoryArea class ? There is a consideration of adding extra bulk to the MemoryArea class which will get loaded in the memory, though the amount of the extra bytecode depends on how well the enter and executeInArea are organized in the implementation. 2) Is this set of methods too big or too small ? 3) Why the 'long' arguments ? Because all other integral types can be converted to long, and converted back inside the run() method if needed. Though there is some cost to that conversion and long arguments take more time to be passed. 4) Why RunnableI is not an interface ? Because I do not want to force the users to provide implementations of every run() method in it. We could define multiple interfaces, one for each argument signature supported, and the corresponding enter() method will take the matching interface as its argument. That will add more classes to the implementation. Is there a good reason to have RunnableI an interface ? The idea is that these classes should not have any fields. 5) Do we want 'int' or 'long' returning versions of these methods as well ? Compatibility Issues --------------------- The execution environment would get a little bigger