Re: Scheme Continuations vs Brakes Continuations was Re: Groovy support in Cocoon

2004-04-06 Thread Stephan Michels
Am Mo, den 05.04.2004 schrieb Christopher Oliver um 22:44:
 Why don't use (Object obj, Method method, Object[] args) in the
 constructor of the continuation object.

 That's a possible alternative, but makes prevents making Continuation an 
 abstract class.

Why should the continuation be abstract? The idea of the brakes people
was to create something similar to java.lang.Thread

Thread t = new Thread(new Runnable() {
  void run() {
sendPage(a);
wait();
sendPage(b);
  }
}); 
t.start();


 Continuation.SUICIDE.invoke(null); ?
 
 *you see many question marks over my head*
 
 I hope you have patience with me :)
 
   
 
 The idea of SUICIDE is that it has the effect of unwinding the stack but 
 not executing any further code and directly returns to the entry point 
 (i.e. it is the continuation of the end of some code ). For example (in JS):
 
 var suicide;
 
 function f() {
suicide = arguments.continuation;
 }
 
 f();  // == since there's no code to execute after f(), invoking 
 suicide later will have the effect of simply terminating the script.
 // end of script
 
 
 In the current Rhino implementation creating a Continuation in a 
 top-level script has the same effect (since what comes after the end of 
 the script is - nothing).
 
 This behavior is as in Scheme.

Hmmm, not every intuitive. So your f() has the same role like
Continuation.suspend() ?

With call of suspend() the Continuation goes from the State restoring
into State !restoring  !capturing, and in cases of the 
state !restoring  !capturing into the state capturing.

Stephan.



Scheme Continuations vs Brakes Continuations was Re: Groovy support in Cocoon

2004-04-05 Thread Stephan Michels
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 

Re: Scheme Continuations vs Brakes Continuations was Re: Groovy support in Cocoon

2004-04-05 Thread Christopher Oliver
Stephan Michels wrote:

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..
 

Yes, of course. Sorry for not being more accurate.

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;
 }
 [...]
}
 

OK.

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.
 

See my second message regarding this.

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