/* * Copyright 2010 Google, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation. Sun designates this * particular file as subject to the "Classpath" exception as provided * by Sun in the LICENSE file that accompanied this code. * * This code is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * version 2 for more details (a copy is included in the LICENSE file that * accompanied this code). * * You should have received a copy of the GNU General Public License version * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA * or visit www.oracle.com if you need additional information or have any * questions. */ package sun.misc; /** * The JVM Continuation class. The API design is still in progress. * * @author Hiroshi Yamauchi */ public class Continuation { private static native void registerNatives(); static { registerNatives(); } /** * The stack frames data */ protected volatile Object stack; /** * The list of compiled code PCs in the stack. Needed to reclaim * the compiled code in the code cache. */ protected volatile long[] pcs; /** * A data field for convenience. This field is set to the second * data parameter to {@link #enter} upon a {@link * #save} call. * *

For example, this field can be used to pass some data from * a scope entry point (a {@link #enter} call site) to the * continuation resume point. */ protected volatile Object data1; /** * A simple data field for convenience. For example, this field * can be used to pass some data from the continuation save * point to the continuation resume point. */ protected volatile Object data2; // the user-defined data public Object data1() { synchronized(this) { return data1; } } public Object data2() { synchronized(this) { return data2; } } public void set_data1(Object o) { synchronized(this) { data1 = o; } } public void set_data2(Object o) { synchronized(this) { data2 = o; } } public boolean isSaved() { return stack != null; } /** * The continuation may save the compiled stack frames. The * reference count of the compiled code (nmethod) is incremented * upon a continuation save and decremented by this finalizer. */ protected void finalize() throws Throwable { if (pcs == null || pcs.length == 0) { return; } for (long pc : pcs) { dec_code_cache_ref_count(pc); } } /** * Copies the stack frames in the current scope, and stores them * in this object. This method must be called in an enclosing * scope. Calling this method causes the stack frames in the * scope to suspend (including the current frame) and the enter * call at the entry of the current scope to return. * * @return the parameter passed to the resume call when the saved stack * frames are resumed in the future. */ public Object save() { return save_cont(this); } /** * Reactivates the stack frames saved in this object on the * current thread. Overwrites the stack frames in the current * scope with the saved stack frames. This method must be * called in an enclosing scope. Calling this method causes the * suspended save call to resume from the point where it was * suspended. * * @param rv the value to be returned from the resumed save call site. */ public void resume(Object rv) { if (stack == null) { throw new IllegalArgumentException( "Continuation hasn't been saved or tried to resume for a second time."); } Object s = stack; stack = null; // resumable only once resume_cont(s, rv); } /** * Marks the beginning of a new 'scope' in preparation for stack * save/resume. Executes the given Runnable. * * @param data any user defined data to be passed from this call * site to the point where {@link #resume} is called * for convenience. The {@link #data1} field will be * set to this object. * @return the Continuation object after the scope was saved * into a Continuation object or null if it wasn't and * simply returned */ public static Object enter(Runnable r, Object data) { Object rv = enter0(r, data); return rv; } /* * This method currently exists just for convenience for the * continuation implementation in the JVM. This method along with * enter() above will never be jitted. This may go away in the * future. */ private static Object enter0(Runnable r, Object data) { Object rv = enter1(r, data); return rv; } /* * This method currently exists just for convenience for the * continuation implementation in the JVM. This may go away in the * future. */ private static Object enter1(Runnable r, Object data) { r.run(); return null; // If saved, this will return the CSE. } private static native Object save_cont(Continuation cont); private static native void resume_cont(Object stack, Object rv); private static native void dec_code_cache_ref_count(long pc); }