1 /*
   2  * Copyright 2010 Google, Inc.  All Rights Reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.  Sun designates this
   8  * particular file as subject to the "Classpath" exception as provided
   9  * by Sun in the LICENSE file that accompanied this code.
  10  *
  11  * This code is distributed in the hope that it will be useful, but WITHOUT
  12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any
  23  * questions.
  24  */
  25 
  26 package sun.misc;
  27 
  28 /**
  29  * The JVM Continuation class. The API design is still in progress.
  30  *
  31  * @author Hiroshi Yamauchi
  32  */
  33 public class Continuation {
  34 
  35     private static native void registerNatives();
  36     static {
  37         registerNatives();
  38     }
  39 
  40     /**
  41      * The stack frames data
  42      */
  43     protected volatile Object stack;
  44 
  45     /**
  46      * The list of compiled code PCs in the stack. Needed to reclaim
  47      * the compiled code in the code cache.
  48      */
  49     protected volatile long[] pcs;
  50 
  51     /**
  52      * A data field for convenience. This field is set to the second
  53      * <code>data</code> parameter to {@link #enter} upon a {@link
  54      * #save} call.
  55      *
  56      * <p>For example, this field can be used to pass some data from
  57      * a scope entry point (a {@link #enter} call site) to the
  58      * continuation resume point.
  59      */
  60     protected volatile Object data1;
  61 
  62     /**
  63      * A simple data field for convenience. For example, this field
  64      * can be used to pass some data from the continuation save
  65      * point to the continuation resume point.
  66      */
  67     protected volatile Object data2;   // the user-defined data
  68 
  69     public Object data1() { synchronized(this) { return data1; } }
  70     public Object data2() { synchronized(this) { return data2; } }
  71     public void set_data1(Object o) { synchronized(this) { data1 = o; } }
  72     public void set_data2(Object o) { synchronized(this) { data2 = o; } }
  73     public boolean isSaved() { return stack != null; }
  74 
  75     /**
  76      * The continuation may save the compiled stack frames. The
  77      * reference count of the compiled code (nmethod) is incremented
  78      * upon a continuation save and decremented by this finalizer.
  79      */
  80     protected void finalize() throws Throwable {
  81         if (pcs == null || pcs.length == 0) {
  82             return;
  83         }
  84         for (long pc : pcs) {
  85             dec_code_cache_ref_count(pc);
  86         }
  87     }
  88 
  89     /**
  90      * Copies the stack frames in the current scope, and stores them
  91      * in this object.  This method must be called in an enclosing
  92      * scope. Calling this method causes the stack frames in the
  93      * scope to suspend (including the current frame) and the enter
  94      * call at the entry of the current scope to return.
  95      *
  96      * @return the parameter passed to the resume call when the saved stack
  97      *         frames are resumed in the future.
  98      */
  99     public Object save() {
 100         return save_cont(this);
 101     }
 102 
 103     /**
 104      * Reactivates the stack frames saved in this object on the
 105      * current thread.  Overwrites the stack frames in the current
 106      * scope with the saved stack frames.  This method must be
 107      * called in an enclosing scope. Calling this method causes the
 108      * suspended save call to resume from the point where it was
 109      * suspended.
 110      *
 111      * @param rv the value to be returned from the resumed save call site.
 112      */
 113     public void resume(Object rv) {
 114         if (stack == null) {
 115             throw new IllegalArgumentException(
 116                 "Continuation hasn't been saved or tried to resume for a second time.");
 117         }
 118         Object s = stack;
 119         stack = null; // resumable only once
 120         resume_cont(s, rv);
 121     }
 122 
 123     /**
 124      * Marks the beginning of a new 'scope' in preparation for stack
 125      * save/resume.  Executes the given Runnable.
 126      *
 127      * @param data any user defined data to be passed from this call
 128      *             site to the point where {@link #resume} is called
 129      *             for convenience. The {@link #data1} field will be
 130      *             set to this object.
 131      * @return the Continuation object after the scope was saved
 132      *         into a Continuation object or null if it wasn't and
 133      *         simply returned
 134      */
 135     public static Object enter(Runnable r, Object data) {
 136         Object rv = enter0(r, data);
 137         return rv;
 138     }
 139 
 140     /*
 141      * This method currently exists just for convenience for the
 142      * continuation implementation in the JVM. This method along with
 143      * enter() above will never be jitted. This may go away in the
 144      * future.
 145      */
 146     private static Object enter0(Runnable r, Object data) {
 147         Object rv = enter1(r, data);
 148         return rv;
 149     }
 150 
 151     /*
 152      * This method currently exists just for convenience for the
 153      * continuation implementation in the JVM. This may go away in the
 154      * future.
 155      */
 156     private static Object enter1(Runnable r, Object data) {
 157         r.run();
 158         return null; // If saved, this will return the CSE.
 159     }
 160 
 161     private static native Object save_cont(Continuation cont);
 162     private static native void resume_cont(Object stack, Object rv);
 163     private static native void dec_code_cache_ref_count(long pc);
 164 }