1 diff --git a/src/share/classes/javax/stack/CoRunnable.java b/src/share/classes/javax/stack/CoRunnable.java
4 +++ b/src/share/classes/javax/stack/CoRunnable.java
7 +public interface CoRunnable {
10 \ No newline at end of file
11 diff --git a/src/share/classes/javax/stack/Continuable.java b/src/share/classes/javax/stack/Continuable.java
14 +++ b/src/share/classes/javax/stack/Continuable.java
17 + * Copyright 2007-2009 Sun Microsystems, Inc. All Rights Reserved.
18 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
20 + * This code is free software; you can redistribute it and/or modify it
21 + * under the terms of the GNU General Public License version 2 only, as
22 + * published by the Free Software Foundation.
24 + * This code is distributed in the hope that it will be useful, but WITHOUT
25 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
26 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
27 + * version 2 for more details (a copy is included in the LICENSE file that
28 + * accompanied this code).
30 + * You should have received a copy of the GNU General Public License version
31 + * 2 along with this work; if not, write to the Free Software Foundation,
32 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
34 + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
35 + * CA 95054 USA or visit www.sun.com if you need additional information or
36 + * have any questions.
40 +import java.lang.annotation.*;
43 +@Retention(RetentionPolicy.RUNTIME)
44 +@Target(ElementType.METHOD)
45 +public @interface Continuable {
46 + ContinuableAccess value() default ContinuableAccess.HIDDEN;
48 diff --git a/src/share/classes/javax/stack/ContinuableAccess.java b/src/share/classes/javax/stack/ContinuableAccess.java
51 +++ b/src/share/classes/javax/stack/ContinuableAccess.java
54 + * Copyright 2007-2009 Sun Microsystems, Inc. All Rights Reserved.
55 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
57 + * This code is free software; you can redistribute it and/or modify it
58 + * under the terms of the GNU General Public License version 2 only, as
59 + * published by the Free Software Foundation.
61 + * This code is distributed in the hope that it will be useful, but WITHOUT
62 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
63 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
64 + * version 2 for more details (a copy is included in the LICENSE file that
65 + * accompanied this code).
67 + * You should have received a copy of the GNU General Public License version
68 + * 2 along with this work; if not, write to the Free Software Foundation,
69 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
71 + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
72 + * CA 95054 USA or visit www.sun.com if you need additional information or
73 + * have any questions.
77 +public enum ContinuableAccess {
78 + HIDDEN, READONLY, READWRITE
80 diff --git a/src/share/classes/javax/stack/Continuation.java b/src/share/classes/javax/stack/Continuation.java
83 +++ b/src/share/classes/javax/stack/Continuation.java
86 + * Copyright 2007-2009 Sun Microsystems, Inc. All Rights Reserved.
87 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
89 + * This code is free software; you can redistribute it and/or modify it
90 + * under the terms of the GNU General Public License version 2 only, as
91 + * published by the Free Software Foundation.
93 + * This code is distributed in the hope that it will be useful, but WITHOUT
94 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
95 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
96 + * version 2 for more details (a copy is included in the LICENSE file that
97 + * accompanied this code).
99 + * You should have received a copy of the GNU General Public License version
100 + * 2 along with this work; if not, write to the Free Software Foundation,
101 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
103 + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
104 + * CA 95054 USA or visit www.sun.com if you need additional information or
105 + * have any questions.
107 +package javax.stack;
110 + * @author lukas.stadler@jku.at
112 +@SuppressWarnings("unused")
113 +public class Continuation {
114 + private static class CONTINUATION_CAPTURED {
117 + public static final Object CAPTURED = CONTINUATION_CAPTURED.class;
118 + private Object data;
119 + private Thread thread;
121 + private static native void registerNatives();
128 + * Saves the current thread state into the continuation object
129 + * @return null if the continuation was saved or the value given to resume if it was resumed
131 + public final native Object save();
134 + * Restores the stack to the state that it had when the continuation was saved.
135 + * @param retValue the value that the save method should return
137 + public final native void resume(Object retValue);
140 + * Yields to the given target continuation, passing along the current continuation
141 + * @param target the continuation that will be reinstated
144 + public static final void yield(Continuation target) {
145 + Continuation c = new Continuation();
146 + if (c.save() == null)
151 + * This method will be called by startDelimited
154 + private static final Object startDelimitedInternal(DelimitedRunnable runnable, Object firstValue) {
155 + Continuation cont = new Continuation();
156 + Object ret = cont.save();
157 + if (ret == CAPTURED)
158 + runnable.run(cont, firstValue);
162 + public static final native Object startDelimited(DelimitedRunnable runnable, Object firstValue);
165 + * This method will be called by continueDelimited
168 + private static final Object continueDelimitedInternal(Continuation cont, Object value) {
169 + cont.resume(value);
173 + public static final native Object continueDelimited(Continuation continuation, Object value);
175 + public final native Object dump();
177 + private static final native Object storeFrameObject(Object retValue);
179 + private static final native void storeFrameVoid();
181 + private static final native boolean storeFrameBoolean(boolean retValue);
183 + private static final native byte storeFrameByte(byte retValue);
185 + private static final native char storeFrameChar(char retValue);
187 + private static final native short storeFrameShort(short retValue);
189 + private static final native int storeFrameInt(int retValue);
191 + private static final native long storeFrameLong(long retValue);
193 + private static final native float storeFrameFloat(float retValue);
195 + private static final native double storeFrameDouble(double retValue);
197 + private static final native Throwable unwind(Throwable e);
200 diff --git a/src/share/classes/javax/stack/ContinuationPermission.java b/src/share/classes/javax/stack/ContinuationPermission.java
203 +++ b/src/share/classes/javax/stack/ContinuationPermission.java
206 + * Copyright 2007-2009 Sun Microsystems, Inc. All Rights Reserved.
207 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
209 + * This code is free software; you can redistribute it and/or modify it
210 + * under the terms of the GNU General Public License version 2 only, as
211 + * published by the Free Software Foundation.
213 + * This code is distributed in the hope that it will be useful, but WITHOUT
214 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
215 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
216 + * version 2 for more details (a copy is included in the LICENSE file that
217 + * accompanied this code).
219 + * You should have received a copy of the GNU General Public License version
220 + * 2 along with this work; if not, write to the Free Software Foundation,
221 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
223 + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
224 + * CA 95054 USA or visit www.sun.com if you need additional information or
225 + * have any questions.
227 +package javax.stack;
229 +import java.security.BasicPermission;
231 +/* name is either "resumeSecure" or "resumeUnsecure" */
232 +public class ContinuationPermission extends BasicPermission {
233 + private static final long serialVersionUID = -3608714945512368738L;
235 + public ContinuationPermission(String name) {
239 \ No newline at end of file
240 diff --git a/src/share/classes/javax/stack/Coroutine.java b/src/share/classes/javax/stack/Coroutine.java
243 +++ b/src/share/classes/javax/stack/Coroutine.java
245 +package javax.stack;
246 +import javax.stack.Continuable;
247 +import javax.stack.Continuation;
250 + * Experimental coroutine implementation using the continuation framework.
252 + * This class works very much like the {@link Thread} class, it can either be supplied with a {@link CoRunnable} upon creation or
253 + * the run method can be overridden.<br/>
254 + * All coroutines belonging to a context are kept in a doubly-linked ring data structure. Due to this there is an ordering of
255 + * coroutines, and the next and previous coroutines are known.
257 + * @author lukas.stadler@jku.at
259 +public class Coroutine {
260 + // exception used to terminate/close coroutines, created only once because exception creation is expensive
261 + private static final CoroutineExitException exitException = new CoroutineExitException();
263 + // contains the actual stack frames, local variables, etc.
264 + private Continuation data;
266 + // the context this coroutine belongs to
267 + private CoroutineContext context;
269 + // the code that will be executed if run isn't overridden
270 + private CoRunnable runnable;
272 + // the pointers for the doubly-linked ring data structure
273 + private Coroutine last;
274 + private Coroutine next;
276 + // if this is non-null then an exception will be raised when this coroutine is resumed
277 + private RuntimeException exception;
280 + * Creates a new coroutine that belongs to the currently active {@link CoroutineContext}. This constructor is only useful if
281 + * the run method is overridden. The coroutine will be inserted after the current coroutine of the context, or as the first
282 + * coroutine if it is the first one added to the context.
283 + * @throws IllegalThreadStateException if there is no current context
285 + public Coroutine() {
286 + initialize(CoroutineContext.getCurrent());
290 + * Creates a new coroutine that belongs to the currently active {@link CoroutineContext}. The coroutine will execute the given
291 + * CoRunnable (if it is non-null). The coroutine will be inserted after the current coroutine of the context, or as the first
292 + * coroutine if it is the first one added to the context.
293 + * @throws IllegalThreadStateException if there is no current context
295 + public Coroutine(CoRunnable runnable) {
296 + this.runnable = runnable;
297 + initialize(CoroutineContext.getCurrent());
301 + * Creates a new coroutine that belongs to the given {@link CoroutineContext}. This constructor is only useful if the run
302 + * method is overridden. The coroutine will be inserted after the current coroutine of the context, or as the first coroutine
303 + * if it is the first one added to the context.
304 + * @throws IllegalArgumentException if context is null
306 + public Coroutine(CoroutineContext context) {
307 + if (context == null)
308 + throw new IllegalArgumentException("context cannot be null");
309 + initialize(context);
313 + * Creates a new coroutine that belongs to the given {@link CoroutineContext}. The coroutine will execute the given CoRunnable
314 + * (if it is non-null). The coroutine will be inserted after the current coroutine of the context, or as the first coroutine
315 + * if it is the first one added to the context.
316 + * @throws IllegalArgumentException if context is null
318 + public Coroutine(CoroutineContext context, CoRunnable runnable) {
319 + if (context == null)
320 + throw new IllegalArgumentException("context cannot be null");
321 + this.runnable = runnable;
322 + initialize(context);
326 + * Adds this coroutine into the doubly-linked ring of the given context.
328 + private void initialize(CoroutineContext context) {
329 + if (context == null)
330 + throw new IllegalThreadStateException("Cannot create Coroutine without CoroutineContext");
331 + context.coroutineAdded(this);
332 + this.context = context;
333 + if (context.getCurrentCoroutine() == null) {
336 + context.setCurrentCoroutine(this);
339 + Coroutine current = context.getCurrentCoroutine();
340 + last = current.last;
342 + current.last = this;
348 + * Yields to the target coroutine, without changing the order of the coroutines
349 + * @param target the coroutine that will be current after this call
350 + * @param value the value that is passed to the target coroutine
351 + * @return the value passed to the yield that makes this coroutine active again
354 + private Object yieldToInternal(Coroutine target, Object value) {
355 + assert target != null;
356 + // System.out.println("yield to " + target + ", value="+value);
357 + context.setCurrentCoroutine(target);
359 + data = new Continuation();
360 + Object ret = data.save();
362 + // System.out.println("ret="+ret);
363 + if (ret == Continuation.CAPTURED) {
364 + if (target.data == null)
365 + context.startCoroutine.resume(value);
367 + // System.out.println("target resume");
368 + target.data.resume(value);
376 + if (exception != null) {
377 + // System.out.println("throwing exception in coroutine " + this + ": " + exception);
384 + * Closes the coroutine. This will resume the coroutine and throw a {@link CoroutineExitException}. If it propagates down to
385 + * the starting method the coroutine will end. Thus coroutines can veto the close operation if they catch the
386 + * CoroutineExitException.
389 + public final void close() {
391 + exception = exitException;
392 + if (context == CoroutineContext.getCurrent()) {
393 + if (this == Coroutine.getCurrent())
397 + yieldTo(this, null);
399 + catch (CoroutineExitException e) {
407 + * @return the currently active coroutine, or null if there is no current coroutine context
409 + public static Coroutine getCurrent() {
410 + CoroutineContext currentContext = CoroutineContext.getCurrent();
411 + return currentContext == null ? null : currentContext.getCurrentCoroutine();
415 + * @return true if this coroutine hasn't ended yet
417 + public final boolean isActive() {
418 + assert (next != null) == (last != null);
419 + return next != null;
423 + * @return the coroutine that is scheduled to be executed after this one
425 + public final Coroutine getNext() {
430 + * @return the coroutine that was executed before this one
432 + public final Coroutine getLast() {
437 + * @return the context this coroutine belongs to
439 + public final CoroutineContext getContext() {
444 + * Yields to the next scheduled coroutine (as determined by the scheduling behavior of the coroutine context)
445 + * @param value the value to be passed to the next coroutine
446 + * @return the value passed to this coroutine when it is resumed
449 + public static Object yield(Object value) {
450 + Coroutine current = getCurrent();
451 + return yieldTo(current.context.scheduleNext(current), value);
455 + * Yields to the last coroutine. This can be used to implement coroutines that generate values for a caller.
456 + * @param value the value to be passed to the next coroutine
457 + * @return the value passed to this coroutine when it is resumed
460 + public static Object yieldReturn(Object value) {
461 + Coroutine current = getCurrent();
462 + // System.out.println("current=" + current);
463 + // System.out.println("last=" + current.last);
464 + return current.yieldToInternal(current.last, value);
468 + * Yields to the next coroutine (ignoring the scheduling behavior of the coroutine context). This does not change the
470 + * @param value the value to be passed to the next coroutine
471 + * @return the value passed to this coroutine when it is resumed
474 + public static Object yieldNext(Object value) {
475 + Coroutine current = getCurrent();
476 + return current.yieldToInternal(current.next, value);
480 + * Yields to the given coroutine (ignoring the scheduling behavior of the coroutine context). The coroutine order will be
481 + * changed so that the given coroutine is the next one.
482 + * @param target the coroutine to be executed next
483 + * @param value the value to be passed to the next coroutine
484 + * @return the value passed to this coroutine when it is resumed
487 + public static Object yieldTo(Coroutine target, Object value) {
488 + Coroutine current = getCurrent();
489 + if (target != current.next) {
490 + // remove target from its current position
491 + target.last.next = target.next;
492 + target.next.last = target.last;
493 + // add target at the current position
494 + target.last = current;
495 + target.next = current.next;
496 + target.last.next = target;
497 + target.next.last = target;
499 + return current.yieldToInternal(target, value);
503 + * This method starts the coroutine execution. It catches exception and handles a return from the run method.
506 + final void start(Object value) {
508 + RuntimeException e = null;
512 + catch (Throwable t) {
513 + if (t != exitException) {
514 + t.printStackTrace();
515 + e = new RuntimeException("coroutine terminated by exception", t);
520 + context.coroutineRemoved(this);
522 + catch (Throwable t) {
523 + t.printStackTrace();
525 + if (last != this) {
528 + Coroutine temp = last;
532 + temp.exception = e;
533 + yieldToInternal(temp, ret);
539 + * This implementation of the run method calls the CoRunnable.run method.
540 + * @param value the value passed via yield
541 + * @return the value that will be passed to the next coroutine
543 + protected Object run(Object value) {
544 + if (runnable != null)
545 + return runnable.run();
550 diff --git a/src/share/classes/javax/stack/CoroutineContext.java b/src/share/classes/javax/stack/CoroutineContext.java
553 +++ b/src/share/classes/javax/stack/CoroutineContext.java
555 +package javax.stack;
556 +import javax.stack.Continuable;
557 +import javax.stack.Continuation;
560 + * This class provides a context in which coroutines can be executed. Coroutines are added to a context either explicitly by
561 + * passing the context to the coroutine's constructor or implicitly by creating a coroutine while another coroutine of the context
564 + * @author lukas.stadler@jku.at
566 +public class CoroutineContext {
567 + private static ThreadLocal<CoroutineContext> current = new ThreadLocal<CoroutineContext>();
569 + private CoroutineContext last;
570 + private Coroutine currentCoroutine;
572 + Continuation startCoroutine = new Continuation();
575 + private void runInternal(Object value) {
576 + Object ret = startCoroutine.save();
577 + if (ret == Continuation.CAPTURED) {
578 + // System.out.println("start initial coroutine: " + value);
579 + currentCoroutine.start(value);
582 + // System.out.println("start subsequent coroutine: " + ret);
583 + currentCoroutine.start(ret);
588 + * Starts the coroutine execution. The first coroutine that was created for this context will be the first one to run.
590 + public void start(Object value) {
591 + if (currentCoroutine == null)
592 + throw new IllegalStateException("Cannot start a context with no coroutines");
593 + last = current.get();
595 + runInternal(value);
601 + * This method will be called every time a coroutine is added to this context
603 + void coroutineAdded(Coroutine coroutine) {
607 + * This method will be called every time a coroutine ends (and is thus removed)
609 + void coroutineRemoved(Coroutine coroutine) {
613 + * This method can be overridden to change the default scheduling behavior of a coroutine context.
614 + * @param current the coroutine that is currently executed
615 + * @return the coroutine to be executed next
617 + Coroutine scheduleNext(Coroutine current) {
618 + return current.getNext();
622 + * @return the current context of the current thread, or null if there is no active context
624 + public static CoroutineContext getCurrent() {
625 + return current.get();
629 + * @return the currently executing coroutine of this context (or the coroutine that will be executed first, if the context
630 + * hasn't started yet)
632 + public Coroutine getCurrentCoroutine() {
633 + return currentCoroutine;
636 + void setCurrentCoroutine(Coroutine coroutine) {
637 + currentCoroutine = coroutine;
640 diff --git a/src/share/classes/javax/stack/CoroutineExitException.java b/src/share/classes/javax/stack/CoroutineExitException.java
643 +++ b/src/share/classes/javax/stack/CoroutineExitException.java
645 +package javax.stack;
646 +public class CoroutineExitException extends RuntimeException {
647 + private static final long serialVersionUID = -9155842264591995913L;
650 diff --git a/src/share/classes/javax/stack/DelimitedRunnable.java b/src/share/classes/javax/stack/DelimitedRunnable.java
653 +++ b/src/share/classes/javax/stack/DelimitedRunnable.java
656 + * Copyright 2007-2009 Sun Microsystems, Inc. All Rights Reserved.
657 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
659 + * This code is free software; you can redistribute it and/or modify it
660 + * under the terms of the GNU General Public License version 2 only, as
661 + * published by the Free Software Foundation.
663 + * This code is distributed in the hope that it will be useful, but WITHOUT
664 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
665 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
666 + * version 2 for more details (a copy is included in the LICENSE file that
667 + * accompanied this code).
669 + * You should have received a copy of the GNU General Public License version
670 + * 2 along with this work; if not, write to the Free Software Foundation,
671 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
673 + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
674 + * CA 95054 USA or visit www.sun.com if you need additional information or
675 + * have any questions.
677 +package javax.stack;
679 +public interface DelimitedRunnable {
680 + public void run(Continuation start, Object firstValue);
682 diff --git a/src/share/classes/javax/stack/Fiber.java b/src/share/classes/javax/stack/Fiber.java
685 +++ b/src/share/classes/javax/stack/Fiber.java
688 + * Copyright 2007-2009 Sun Microsystems, Inc. All Rights Reserved.
689 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
691 + * This code is free software; you can redistribute it and/or modify it
692 + * under the terms of the GNU General Public License version 2 only, as
693 + * published by the Free Software Foundation.
695 + * This code is distributed in the hope that it will be useful, but WITHOUT
696 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
697 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
698 + * version 2 for more details (a copy is included in the LICENSE file that
699 + * accompanied this code).
701 + * You should have received a copy of the GNU General Public License version
702 + * 2 along with this work; if not, write to the Free Software Foundation,
703 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
705 + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
706 + * CA 95054 USA or visit www.sun.com if you need additional information or
707 + * have any questions.
709 +package javax.stack;
711 +public abstract class Fiber {
712 + private Continuation returnContinuation;
713 + private Continuation continuation = new Continuation();
715 + private class FiberRunnable implements DelimitedRunnable {
717 + public final void run(Continuation start, Object firstValue) {
718 + returnContinuation = start;
719 + Object lastRetValue;
721 + lastRetValue = generate(firstValue);
723 + catch (RuntimeException e) {
724 + e.printStackTrace();
725 + lastRetValue = null;
727 + returnContinuation = null;
728 + start.resume(lastRetValue);
733 + protected abstract Object generate(Object firstIn);
736 + protected Object yield(Object returnValue) {
737 + Object o = continuation.save();
738 + if (o == Continuation.CAPTURED)
739 + returnContinuation.resume(returnValue);
744 + public Object resume(Object value) {
745 + if (returnContinuation == null)
746 + return Continuation.startDelimited(new FiberRunnable(), value);
748 + return Continuation.continueDelimited(continuation, value);
751 + public void dump() {
752 + continuation.dump();
756 diff --git a/test/javax/stack/ContinuationTest1.java b/test/javax/stack/ContinuationTest1.java
759 +++ b/test/javax/stack/ContinuationTest1.java
761 +package javax.stack;
763 +import static org.junit.Assert.assertEquals;
765 +import org.junit.Before;
766 +import org.junit.Test;
768 +public class ContinuationTest1 extends ContinuationTestTools {
770 + public ContinuationTest1() {
771 + interpreted = this;
772 + if (compiled == null)
773 + compiled = new ContinuationTest1Compiled();
777 + public void setUp() throws Exception {
781 + @Continuable(ContinuableAccess.HIDDEN)
782 + public Object subSave(Continuation cont, int a, int b, int c, int d, int e) {
791 + assertEquals(15, i);
792 + assertEquals(ContinuationTest1.class, this.getClass());
793 + assertEquals(Continuation.class, cont.getClass());
797 + private int cnt = 0;
800 + @Continuable(ContinuableAccess.HIDDEN)
801 + public void testRec() {
802 + Integer i = 100000;
803 + Continuation cont = new Continuation();
804 + assertEquals(10102, compiled.subSave(cont, 1, 2, 3, 4, 5));
805 + assertEquals(ContinuationTest1.class, this.getClass());
809 + assertEquals(100000, i);
813 + @Continuable(ContinuableAccess.HIDDEN)
814 + public void testSimple() {
815 + Continuation cont = new Continuation();
817 + if (cont.save() == Continuation.CAPTURED) {
826 + assertActions(new int[] { 1, 2, 3, 4 });
829 + @Continuable(ContinuableAccess.HIDDEN)
830 + int intSub(Continuation c, int code1, Integer code2, int depth) {
836 + lastSaveReturn = c.save();
838 + assertEquals(thisTemp, this);
839 + assertEquals(intTemp, code1);
840 + assertEquals(objTemp, code2);
843 + if ((depth & 3) == 0)
844 + compiled.intSub(c, code1, code2, depth - 1);
846 + intSub(c, code1, code2, depth - 1);
851 + @Continuable(ContinuableAccess.HIDDEN)
852 + Integer objSub(Continuation c, int code1, Integer code2, int depth) {
858 + lastSaveReturn = c.save();
859 + assertEquals(thisTemp, this);
860 + assertEquals(intTemp, code1);
861 + assertEquals(objTemp, code2);
865 + if ((depth & 3) == 0)
866 + compiled.objSub(c, code1, code2, depth - 1);
868 + objSub(c, code1, code2, depth - 1);
873 + @Continuable(ContinuableAccess.HIDDEN)
874 + void resumeRec(Continuation c, Object retValue, int depth) {
879 + if ((depth & 3) == 0)
880 + compiled.resumeRec(c, retValue, depth - 1);
882 + resumeRec(c, retValue, depth - 1);
886 + @Continuable(ContinuableAccess.HIDDEN)
887 + public void testParamsReturnInternal(int resumeDepth, int saveDepth) {
888 + Continuation c = new Continuation();
890 + action(intSub(c, 2, 3, saveDepth));
891 + if (lastSaveReturn == Continuation.CAPTURED) {
893 + if (resumeDepth == 0)
896 + resumeRec(c, null, resumeDepth);
900 + action(compiled.intSub(c, 6, 7, saveDepth));
901 + if (lastSaveReturn == Continuation.CAPTURED) {
903 + if (resumeDepth == 0)
906 + resumeRec(c, null, resumeDepth);
910 + action(objSub(c, 10, 11, saveDepth));
911 + if (lastSaveReturn == Continuation.CAPTURED) {
913 + if (resumeDepth == 0)
916 + resumeRec(c, null, resumeDepth);
920 + action(compiled.objSub(c, 14, 15, saveDepth));
921 + if (lastSaveReturn == Continuation.CAPTURED) {
923 + if (resumeDepth == 0)
926 + resumeRec(c, null, resumeDepth);
930 + assertActions(new int[] { 1, 2, 3, 101, 4, 3, 101, 5, 6, 7, 102, 8, 7, 102, 9, 10, 11, 201, 12, 11, 201, 13, 14, 15, 202,
931 + 16, 15, 202, 17 });
935 + public void testParamsReturn() {
936 + for (int i2 = 1; i2 < 50; i2++) {
937 + for (int i = 0; i < 50; i++) {
938 +// System.out.println("resume: " + i + ", save: " + i2);
940 + testParamsReturnInternal(i, i2);
947 + @Continuable(ContinuableAccess.HIDDEN)
948 + public void testManyParams() {
949 + Continuation cont = new Continuation();
950 + if (manyParamsSub(cont, 5, true, false, 1, (short) 2, (byte) 3, (char) 4, (long) 5, 6, (short) 7, (byte) 8, (char) 9,
951 + (long) 10, (float) 11, (double) 12, (float) 13, (double) 14, 15, 16, 17, 18, 19, 20) == Continuation.CAPTURED)
955 + @Continuable(ContinuableAccess.HIDDEN)
956 + private Object manyParamsSub(Continuation cont, int depth, boolean a, boolean b, int c, short d, byte e, char f,
957 + long g, Integer h, Short i, Byte j, Character k, Long l, float m, double n, Float o, Double p, Integer q, int r,
958 + int s, int t, int u, int v) {
961 + ret = manyParamsSub(cont, depth - 1, a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v);
964 + assertEquals(cont.getClass(), Continuation.class);
965 + assertEquals(a, true);
966 + assertEquals(b, false);
967 + assertEquals(c, 1);
968 + assertEquals(d, (short) 2);
969 + assertEquals(e, (byte) 3);
970 + assertEquals(f, (char) 4);
971 + assertEquals(g, (long) 5);
972 + assertEquals(h, 6);
973 + assertEquals(i, (short) 7);
974 + assertEquals(j, (byte) 8);
975 + assertEquals(k, (char) 9);
976 + assertEquals(l, (long) 10);
977 + assertEquals(m, (float) 11);
978 + assertEquals(n, (double) 12);
979 + assertEquals(o, (float) 13);
980 + assertEquals(p, (double) 14);
981 + assertEquals(q, 15);
982 + assertEquals(r, 16);
983 + assertEquals(s, 17);
984 + assertEquals(t, 18);
985 + assertEquals(u, 19);
986 + assertEquals(v, 20);
990 diff --git a/test/javax/stack/ContinuationTest1Compiled.java b/test/javax/stack/ContinuationTest1Compiled.java
993 +++ b/test/javax/stack/ContinuationTest1Compiled.java
995 +package javax.stack;
997 +import static org.junit.Assert.assertEquals;
999 +import org.junit.Before;
1000 +import org.junit.Test;
1002 +public class ContinuationTest1Compiled extends ContinuationTestTools {
1004 + public ContinuationTest1Compiled() {
1006 + if (interpreted == null)
1007 + interpreted = new ContinuationTest1();
1011 + public void setUp() throws Exception {
1015 + @Continuable(ContinuableAccess.HIDDEN)
1016 + public Object subSave(Continuation cont, int a, int b, int c, int d, int e) {
1025 + assertEquals(15, i);
1026 + assertEquals(ContinuationTest1Compiled.class, this.getClass());
1027 + assertEquals(Continuation.class, cont.getClass());
1031 + private int cnt = 0;
1034 + @Continuable(ContinuableAccess.HIDDEN)
1035 + public void testRec() {
1036 + Integer i = 100000;
1037 + Continuation cont = new Continuation();
1038 + assertEquals(10102, interpreted.subSave(cont, 1, 2, 3, 4, 5));
1039 + assertEquals(ContinuationTest1Compiled.class, this.getClass());
1041 + cont.resume(null);
1042 + assertEquals(100000, i);
1046 + @Continuable(ContinuableAccess.HIDDEN)
1047 + public void testSimple() {
1048 + Continuation cont = new Continuation();
1050 + if (cont.save() == Continuation.CAPTURED) {
1052 + cont.resume(null);
1059 + assertActions(new int[] { 1, 2, 3, 4 });
1062 + @Continuable(ContinuableAccess.HIDDEN)
1063 + int intSub(Continuation c, int code1, Integer code2, int depth) {
1068 + lastSaveReturn = c.save();
1069 + assertEquals(intTemp, code1);
1070 + assertEquals(objTemp, code2);
1074 + if ((depth & 3) == 0)
1075 + interpreted.intSub(c, code1, code2, depth - 1);
1077 + intSub(c, code1, code2, depth - 1);
1082 + @Continuable(ContinuableAccess.HIDDEN)
1083 + Integer objSub(Continuation c, int code1, Integer code2, int depth) {
1088 + lastSaveReturn = c.save();
1089 + assertEquals(intTemp, code1);
1090 + assertEquals(objTemp, code2);
1094 + if ((depth & 3) == 0)
1095 + interpreted.objSub(c, code1, code2, depth - 1);
1097 + objSub(c, code1, code2, depth - 1);
1102 + @Continuable(ContinuableAccess.HIDDEN)
1103 + void resumeRec(Continuation c, Object retValue, int depth) {
1108 + if ((depth & 3) == 0)
1109 + interpreted.resumeRec(c, retValue, depth - 1);
1111 + resumeRec(c, retValue, depth - 1);
1115 + @Continuable(ContinuableAccess.HIDDEN)
1116 + public void testParamsReturnInternal(int resumeDepth, int saveDepth) {
1117 + Continuation c = new Continuation();
1119 + action(interpreted.intSub(c, 2, 3, saveDepth));
1120 + if (lastSaveReturn == Continuation.CAPTURED) {
1122 + if (resumeDepth == 0)
1125 + resumeRec(c, null, resumeDepth);
1129 + action(intSub(c, 6, 7, saveDepth));
1130 + if (lastSaveReturn == Continuation.CAPTURED) {
1132 + if (resumeDepth == 0)
1135 + resumeRec(c, null, resumeDepth);
1139 + action(interpreted.objSub(c, 10, 11, saveDepth));
1140 + if (lastSaveReturn == Continuation.CAPTURED) {
1142 + if (resumeDepth == 0)
1145 + resumeRec(c, null, resumeDepth);
1149 + action(objSub(c, 14, 15, saveDepth));
1150 + if (lastSaveReturn == Continuation.CAPTURED) {
1152 + if (resumeDepth == 0)
1155 + resumeRec(c, null, resumeDepth);
1159 + assertActions(new int[] { 1, 2, 3, 101, 4, 3, 101, 5, 6, 7, 102, 8, 7, 102, 9, 10, 11, 201, 12, 11, 201, 13, 14, 15, 202,
1160 + 16, 15, 202, 17 });
1164 + public void testParamsReturn() {
1165 + for (int i2 = 0; i2 < 50; i2++) {
1166 + for (int i = 0; i < 50; i++) {
1167 + // System.out.println("resume: " + i + ", save: " + i2);
1169 + testParamsReturnInternal(i, i2);
1176 + @Continuable(ContinuableAccess.HIDDEN)
1177 + public void testManyParams() {
1178 + Continuation cont = new Continuation();
1179 + if (manyParamsSub(cont, 5, true, false, 1, (short) 2, (byte) 3, (char) 4, (long) 5, 6, (short) 7, (byte) 8, (char) 9,
1180 + (long) 10, (float) 11, (double) 12, (float) 13, (double) 14, 15, 16, 17, 18, 19, 20) == Continuation.CAPTURED)
1181 + cont.resume(null);
1184 + @Continuable(ContinuableAccess.HIDDEN)
1185 + private Object manyParamsSub(Continuation cont, int depth, boolean a, boolean b, int c, short d, byte e, char f, long g,
1186 + Integer h, Short i, Byte j, Character k, Long l, float m, double n, Float o, Double p, Integer q, int r, int s,
1187 + int t, int u, int v) {
1190 + ret = manyParamsSub(cont, depth - 1, a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v);
1192 + ret = cont.save();
1193 + assertEquals(cont.getClass(), Continuation.class);
1194 + assertEquals(a, true);
1195 + assertEquals(b, false);
1196 + assertEquals(c, 1);
1197 + assertEquals(d, (short) 2);
1198 + assertEquals(e, (byte) 3);
1199 + assertEquals(f, (char) 4);
1200 + assertEquals(g, (long) 5);
1201 + assertEquals(h, 6);
1202 + assertEquals(i, (short) 7);
1203 + assertEquals(j, (byte) 8);
1204 + assertEquals(k, (char) 9);
1205 + assertEquals(l, (long) 10);
1206 + assertEquals(m, (float) 11);
1207 + assertEquals(n, (double) 12);
1208 + assertEquals(o, (float) 13);
1209 + assertEquals(p, (double) 14);
1210 + assertEquals(q, 15);
1211 + assertEquals(r, 16);
1212 + assertEquals(s, 17);
1213 + assertEquals(t, 18);
1214 + assertEquals(u, 19);
1215 + assertEquals(v, 20);
1220 diff --git a/test/javax/stack/ContinuationTestTools.java b/test/javax/stack/ContinuationTestTools.java
1221 new file mode 100644
1223 +++ b/test/javax/stack/ContinuationTestTools.java
1225 +package javax.stack;
1227 +import static org.junit.Assert.assertEquals;
1229 +import java.util.ArrayList;
1230 +import java.util.Stack;
1232 +public class ContinuationTestTools {
1233 + private static Stack<ArrayList<Integer>> actions = new Stack<ArrayList<Integer>>();
1235 + protected static Object thisTemp;
1236 + protected static Object objTemp;
1237 + protected static int intTemp;
1238 + protected static Object lastSaveReturn = null;
1240 + protected static ContinuationTest1Compiled compiled;
1241 + protected static ContinuationTest1 interpreted;
1243 + protected static void clearActions() {
1245 + actions.add(new ArrayList<Integer>());
1248 + protected static void pushActions() {
1249 + actions.push(new ArrayList<Integer>());
1252 + protected static void popActions() {
1256 + protected static void action(int code) {
1257 + actions.peek().add(code);
1260 + protected static void assertActions(int[] expectedActions) {
1261 + if (expectedActions.length == actions.peek().size()) {
1262 + for (int i = 0; i < expectedActions.length; i++)
1263 + assertEquals(expectedActions[i], actions.peek().get(i));
1266 + System.out.print("expected: ");
1267 + for (int i = 0; i < expectedActions.length; i++)
1268 + System.out.print(expectedActions[i] + " ");
1269 + System.out.print("\nactual: ");
1270 + for (int i = 0; i < actions.peek().size(); i++)
1271 + System.out.print(actions.peek().get(i) + " ");
1273 + assertEquals(expectedActions.length, actions.peek().size());
1278 diff --git a/test/javax/stack/DelimitedTest.java b/test/javax/stack/DelimitedTest.java
1279 new file mode 100644
1281 +++ b/test/javax/stack/DelimitedTest.java
1283 +package javax.stack;
1285 +import java.io.IOException;
1287 +import org.junit.Test;
1289 +public class DelimitedTest {
1291 + class TestFiber extends Fiber {
1292 + @Continuable(ContinuableAccess.HIDDEN)
1293 + protected Object generate(Object value) {
1294 + int i = (Integer) value;
1296 + i += (Integer) yield(i);
1301 + private static final long COUNT = 5000;
1302 + private static final long COUNT2 = 100;
1305 + @Continuable(ContinuableAccess.HIDDEN)
1306 + public void testRec() throws IOException {
1308 + Continuation cont = new Continuation();
1311 + long time = System.nanoTime();
1312 + for (int i2 = 0; i2 < COUNT2; i2++) {
1313 + TestFiber test = new TestFiber();
1314 + for (int i = 0; i < COUNT; i++) {
1315 + Object ret = test.resume(i);
1316 + int result = (Integer) ret;
1319 + long tps = (long) (COUNT * COUNT2 * 1000000000d / (System.nanoTime() - time));
1320 + System.out.println(tps);
1324 + catch (Throwable e) {
1325 + e.printStackTrace();
1330 \ No newline at end of file