First, I'm glad to hear more input ;-) Your mail took some time
to parse it.

Am Mo, den 05.04.2004 schrieb Christopher Oliver um 18:47:
> OK, IIUC there are three modes of execution of the instrumented code:
> 
> 1) isCapturing
> During this mode the JVM call stack is unwound and its state captured in 
> the continuation call stack.
> 2) isRestoring
> During this mode a saved call stack in a continuation is recreated on 
> the JVM stack.
> 3) !isCapturing && !isRestoring
> This is the "normal" execution of the JVM  - no modifications are made 
> to the JVM call stack or to the continuation call stack.

Correct.

> This is achieved by inserting code before each invoke instruction to 
> copy local variables from the continuation stack to the JVM stack and to 
> reset the program counter to the value saved in the continuation stack 
> if "isRestoring" is true, and by inserting code after each invoke 
> instruction to copy the values of local variables from the JVM call 
> stack as well as the program counter into the continuation call stack if 
> "isCapturing" is true.

Yes, but the code for the restore procedure is at the begining of the
method not the before the invocation, but anyway..

I need some pseudo code for myself ;-) Current situation:

void myFlow() {
  if (continuation.isRestoring()) {
     continuation.getStack().popLocalVariables();
     continuation.getStack().popOperandStack();
     continuation.getStack().popReference(); // used for the  
                                        //method invocation
     push(null) as many null object as the method invovation need for 
                the parameters
     goto continuation.getStack().popLastProcessCounter();
  }

  [...]

label 1:
  invoke MySubFlow.bla();

  if (continuation.isCapturing() {
     remove the return value (is unimportant)
     continuation.getStack().pushLocalVariables();
     continuation.getStack().pushOperandStack();
     continuation.getStack().pushLastProcessCounter(label 1);
     continuation.getStack().pushReference(this);
     return null or void;
  }

  [...]
}

> To make continuations more "Scheme-like" it must be possible to 
> construct a continuation without modifying the JVM call stack (thus the 
> current method invocation can "continue as normal").
> 
> To make this possible the byte-code transformer could work like this:
> 1) Insert code before an invoke instruction to push local vars and the 
> pc onto the continuation stack if (!isRestoring && !isCapturing)
> 2) Insert code after an invoke instruction to pop those values from the 
> continuation stack if (!isRestoring && !isCapturing)
> 3) If (isRestoring == true) the pre-invoke code would work as it does now.
> 4) If (isCapturing == true) the post-invoke code would simply cause the 
> current method invocation to return to its caller without modifying the 
> continuation stack - since it is already set up from (1). When the JVM 
> stack is completely unwound another continuation will take the place of 
> this one and that new continuation would be in "isRestoring" mode until 
> it is recreated on the JVM stack at which point it would enter 
> (!isRestoring && !isCapturing) mode.

Okay to recapitulate IIUC. Your proposal:

void myFlow() {
  if (continuation.isRestoring()) {
     continuation.getStack().popLocalVariables();
     continuation.getStack().popOperandStack();
     goto continuation.getStack().popLastProcessCounter();
  }

  [...]

  continuation.getStack().pushLocalVariables();
  continuation.getStack().pushOperandStack();
  continuation.getStack().pushLastProcessCounter(label 1);

label 1:
  invoke MySubFlow.bla();

  if (continuation.isCapturing() {
     return null or void;
  } else {
     continuation.getStack().popLocalVariables();
     continuation.getStack().popOperandStack();
     continuation.getStack().popLastProcessCounter();
  }

  [...]
}

Yes, this has the benefit to call "uninstrumented" code, but
the complete frame must be captured and restored for every invocation.

> The user interface to this might look something like this:
> 
> public class Continuation {
>         // Empty continuation for use as an escape procedure
>         public static final Continuation SUICIDE;

I didn't get the role of SUICIDE.

>         // Invoke a captured continuation - it will replace the current 
> continuation. I.e. the current JVM call stack will be unwound, the call 
> stack saved in this object will be recreated on the JVM call stack, and 
> the method invocation in which this object was created will return with 
> "returnValue".
>         public void invoke(Object returnValue);

Do you want to use the "returnValue" to return the WebContinuation in
sendPageAndWait() ? The problem I see is that you suspend the thread
at a method invocation not at the end of the method.

>         // Get the current continuation -
>         public static Continuation getCurrentContinuation();
>         // Entry point to the instrumented code (precondition: cannot be 
> called recursively and method.getDeclaringClass() must be instrumented)
>         public static Object invoke(Object obj, Method method, Object[] 
> args);
> }

Why don't use (Object obj, Method method, Object[] args) in the
constructor of the continuation object.

Something like that:

// Start continuation
Continuation c = new Continuation(Object obj, Method method, Object[]
args)
c.invoke();

if (c.isSusended()) {
  // Continue the continuation
  c = new Continuation(c);
  c.continue();
}


> public class Cocoon {
>      // ...
>      public WebContinuation sendPageAndWait(String uri, Object biz, long 
> ttl) {
>               Continuation kont = Continuation.getCurrentContinuation();
>               WebContinuation wk = 
> continuationsMgr.createWebContinuation(kont,
>                                            parentWebContinuation,
>                                            ttl,
>                                            null);
>                sendPage(uri, biz);
>                Continuation.SUICIDE.invoke(null);
>                return wk; // never reached
>      }

Continuation.SUICIDE.invoke(null); ?

*you see many question marks over my head*

I hope you have patience with me :)

Stephan Michels.

Reply via email to