changeset 53264:c92e170e24df fibers

Merge
author alanb
date Fri, 04 Jan 2019 17:54:48 +0000
parents d6017ec2f4a9 54f157532ee3
children 19f887f76d49
files
diffstat 32 files changed, 557 insertions(+), 133 deletions(-) [+]
line wrap: on
line diff
--- a/make/hotspot/symbols/symbols-unix	Fri Jan 04 17:53:42 2019 +0000
+++ b/make/hotspot/symbols/symbols-unix	Fri Jan 04 17:54:48 2019 +0000
@@ -174,6 +174,7 @@
 JVM_SetClassSigners
 JVM_SetNativeThreadName
 JVM_SetPrimitiveArrayElement
+JVM_SetStackWalkContinuation
 JVM_SetThreadPriority
 JVM_Sleep
 JVM_StartThread
--- a/src/hotspot/share/classfile/javaClasses.cpp	Fri Jan 04 17:53:42 2019 +0000
+++ b/src/hotspot/share/classfile/javaClasses.cpp	Fri Jan 04 17:54:48 2019 +0000
@@ -2036,6 +2036,7 @@
   typeArrayOop    _bcis;
   objArrayOop     _mirrors;
   typeArrayOop    _names; // needed to insulate method name against redefinition
+  objArrayOop     _conts;
   int             _index;
   NoSafepointVerifier _nsv;
 
@@ -2044,6 +2045,7 @@
     trace_bcis_offset    = java_lang_Throwable::trace_bcis_offset,
     trace_mirrors_offset = java_lang_Throwable::trace_mirrors_offset,
     trace_names_offset   = java_lang_Throwable::trace_names_offset,
+    trace_conts_offset   = java_lang_Throwable::trace_conts_offset,
     trace_next_offset    = java_lang_Throwable::trace_next_offset,
     trace_size           = java_lang_Throwable::trace_size,
     trace_chunk_size     = java_lang_Throwable::trace_chunk_size
@@ -2070,11 +2072,16 @@
     assert(names != NULL, "names array should be initialized in backtrace");
     return names;
   }
+  static objArrayOop get_conts(objArrayHandle chunk) {
+    objArrayOop conts = objArrayOop(chunk->obj_at(trace_conts_offset));
+    assert(conts != NULL, "conts array should be initialized in backtrace");
+    return conts;
+  }
 
  public:
 
   // constructor for new backtrace
-  BacktraceBuilder(TRAPS): _head(NULL), _methods(NULL), _bcis(NULL), _mirrors(NULL), _names(NULL) {
+  BacktraceBuilder(TRAPS): _head(NULL), _methods(NULL), _bcis(NULL), _mirrors(NULL), _names(NULL), _conts(NULL) {
     expand(CHECK);
     _backtrace = Handle(THREAD, _head);
     _index = 0;
@@ -2085,9 +2092,11 @@
     _bcis = get_bcis(backtrace);
     _mirrors = get_mirrors(backtrace);
     _names = get_names(backtrace);
+    _conts = get_conts(backtrace);
     assert(_methods->length() == _bcis->length() &&
            _methods->length() == _mirrors->length() &&
-           _mirrors->length() == _names->length(),
+           _mirrors->length() == _names->length() && 
+           _names->length() == _conts->length(),
            "method and source information arrays should match");
 
     // head is the preallocated backtrace
@@ -2115,6 +2124,9 @@
     typeArrayOop names = oopFactory::new_symbolArray(trace_chunk_size, CHECK);
     typeArrayHandle new_names(THREAD, names);
 
+    objArrayOop conts = oopFactory::new_objectArray(trace_chunk_size, CHECK);
+    objArrayHandle new_conts(THREAD, conts);
+
     if (!old_head.is_null()) {
       old_head->obj_at_put(trace_next_offset, new_head());
     }
@@ -2122,12 +2134,14 @@
     new_head->obj_at_put(trace_bcis_offset, new_bcis());
     new_head->obj_at_put(trace_mirrors_offset, new_mirrors());
     new_head->obj_at_put(trace_names_offset, new_names());
+    new_head->obj_at_put(trace_conts_offset, new_conts());
 
     _head    = new_head();
     _methods = new_methods();
     _bcis = new_bcis();
     _mirrors = new_mirrors();
     _names  = new_names();
+    _conts  = new_conts();
     _index = 0;
   }
 
@@ -2135,7 +2149,7 @@
     return _backtrace();
   }
 
-  inline void push(Method* method, int bci, TRAPS) {
+  inline void push(Method* method, int bci, oop contScopeName, TRAPS) {
     // Smear the -1 bci to 0 since the array only holds unsigned
     // shorts.  The later line number lookup would just smear the -1
     // to a 0 even if it could be recorded.
@@ -2159,6 +2173,9 @@
     // from being unloaded while we still have this stack trace.
     assert(method->method_holder()->java_mirror() != NULL, "never push null for mirror");
     _mirrors->obj_at_put(_index, method->method_holder()->java_mirror());
+
+    _conts->obj_at_put(_index, contScopeName);
+
     _index++;
   }
 
@@ -2170,8 +2187,9 @@
   int _version;
   Symbol* _name;
   Handle _mirror;
-  BacktraceElement(Handle mirror, int mid, int version, int bci, Symbol* name) :
-                   _method_id(mid), _bci(bci), _version(version), _name(name), _mirror(mirror) {}
+  Handle _cont; // the continuation scope name (String)
+  BacktraceElement(Handle mirror, int mid, int version, int bci, Symbol* name, Handle cont) :
+                   _method_id(mid), _bci(bci), _version(version), _name(name), _mirror(mirror), _cont(cont) {}
 };
 
 class BacktraceIterator : public StackObj {
@@ -2181,6 +2199,7 @@
   typeArrayHandle _methods;
   typeArrayHandle _bcis;
   typeArrayHandle _names;
+  objArrayHandle  _conts;
 
   void init(objArrayHandle result, Thread* thread) {
     // Get method id, bci, version and mirror from chunk
@@ -2190,6 +2209,7 @@
       _bcis = typeArrayHandle(thread, BacktraceBuilder::get_bcis(_result));
       _mirrors = objArrayHandle(thread, BacktraceBuilder::get_mirrors(_result));
       _names = typeArrayHandle(thread, BacktraceBuilder::get_names(_result));
+      _conts = objArrayHandle(thread, BacktraceBuilder::get_conts(_result));
       _index = 0;
     }
   }
@@ -2204,7 +2224,8 @@
                         _methods->ushort_at(_index),
                         Backtrace::version_at(_bcis->int_at(_index)),
                         Backtrace::bci_at(_bcis->int_at(_index)),
-                        _names->symbol_at(_index));
+                        _names->symbol_at(_index),
+                        Handle(thread, _conts->obj_at(_index)));
     _index++;
 
     if (_index >= java_lang_Throwable::trace_chunk_size) {
@@ -2387,7 +2408,7 @@
   // with bci 0
   if (!thread->has_last_Java_frame()) {
     if (max_depth >= 1 && method() != NULL) {
-      bt.push(method(), 0, CHECK);
+      bt.push(method(), 0, NULL, CHECK);
       log_info(stacktrace)("%s, %d", throwable->klass()->external_name(), 1);
       set_depth(throwable(), 1);
       set_backtrace(throwable(), bt.backtrace());
@@ -2412,10 +2433,12 @@
   bool skip_fillInStackTrace_check = false;
   bool skip_throwableInit_check = false;
   bool skip_hidden = !ShowHiddenFrames;
-
-  for (frame fr = thread->last_frame(); max_depth == 0 || max_depth != total_count;) {
+  bool is_last = false;
+  oop cont = thread->last_continuation();
+  for (frame fr = thread->last_frame(); (max_depth == 0 || max_depth != total_count) && !is_last;) {
     Method* method = NULL;
     int bci = 0;
+    oop contScopeName = cont != NULL ? java_lang_ContinuationScope::name(java_lang_Continuation::scope(cont)) : NULL;
 
     // Compiled java method case.
     if (decode_offset != 0) {
@@ -2425,7 +2448,12 @@
       bci = stream.read_bci();
     } else {
       if (fr.is_first_frame()) break;
-      if (Continuation::is_scope_bottom(contScope(), fr, &map)) break;
+      if (Continuation::is_scope_bottom(contScope(), fr, &map)) 
+        is_last = true;
+
+      if (cont != NULL && Continuation::is_continuation_entry_frame(fr, &map)) {
+        cont = java_lang_Continuation::parent(cont);
+      }
       address pc = fr.pc();
       if (fr.is_interpreted_frame()) {
         address bcp;
@@ -2495,7 +2523,8 @@
     if (method->is_hidden()) {
       if (skip_hidden)  continue;
     }
-    bt.push(method, bci, CHECK);
+
+    bt.push(method, bci, contScopeName, CHECK);
     total_count++;
   }
 
@@ -2559,7 +2588,7 @@
   // fill in as much stack trace as possible
   int chunk_count = 0;
   for (;!st.at_end(); st.next()) {
-    bt.push(st.method(), st.bci(), CHECK);
+    bt.push(st.method(), st.bci(), NULL, CHECK);
     chunk_count++;
 
     // Bail-out for deep stacks
@@ -2606,11 +2635,13 @@
                                          method,
                                          bte._version,
                                          bte._bci,
-                                         bte._name, CHECK);
+                                         bte._name, 
+                                         bte._cont,
+                                         CHECK);
   }
 }
 
-oop java_lang_StackTraceElement::create(const methodHandle& method, int bci, TRAPS) {
+oop java_lang_StackTraceElement::create(const methodHandle& method, int bci, Handle contScope, TRAPS) {
   // Allocate java.lang.StackTraceElement instance
   InstanceKlass* k = SystemDictionary::StackTraceElement_klass();
   assert(k != NULL, "must be loaded in 1.4+");
@@ -2621,13 +2652,13 @@
   Handle element = k->allocate_instance_handle(CHECK_0);
 
   int version = method->constants()->version();
-  fill_in(element, method->method_holder(), method, version, bci, method->name(), CHECK_0);
+  fill_in(element, method->method_holder(), method, version, bci, method->name(), contScope, CHECK_0);
   return element();
 }
 
 void java_lang_StackTraceElement::fill_in(Handle element,
                                           InstanceKlass* holder, const methodHandle& method,
-                                          int version, int bci, Symbol* name, TRAPS) {
+                                          int version, int bci, Symbol* name, Handle contScopeName, TRAPS) {
   assert(element->is_a(SystemDictionary::StackTraceElement_klass()), "sanity check");
 
   // Fill in class name
@@ -2677,6 +2708,9 @@
     int line_number = Backtrace::get_line_number(method, bci);
     java_lang_StackTraceElement::set_lineNumber(element(), line_number);
   }
+
+  // Fill in continuation scope
+  java_lang_StackTraceElement::set_contScopeName(element(), contScopeName());
 }
 
 Method* java_lang_StackFrameInfo::get_method(Handle stackFrame, InstanceKlass* holder, TRAPS) {
@@ -2687,7 +2721,7 @@
   return method;
 }
 
-void java_lang_StackFrameInfo::set_method_and_bci(Handle stackFrame, const methodHandle& method, int bci, TRAPS) {
+void java_lang_StackFrameInfo::set_method_and_bci(Handle stackFrame, const methodHandle& method, int bci, oop cont, TRAPS) {
   // set Method* or mid/cpref
   Handle mname(Thread::current(), stackFrame->obj_field(_memberName_offset));
   InstanceKlass* ik = method->method_holder();
@@ -2699,6 +2733,9 @@
   int version = method->constants()->version();
   assert((jushort)version == version, "version should be short");
   java_lang_StackFrameInfo::set_version(stackFrame(), (short)version);
+
+  oop contScopeName = cont != NULL ? java_lang_ContinuationScope::name(java_lang_Continuation::scope(cont)): NULL;
+  java_lang_StackFrameInfo::set_contScopeName(stackFrame(), contScopeName);
 }
 
 void java_lang_StackFrameInfo::to_stack_trace_element(Handle stackFrame, Handle stack_trace_element, TRAPS) {
@@ -2707,16 +2744,18 @@
   Klass* clazz = java_lang_Class::as_Klass(java_lang_invoke_MemberName::clazz(mname()));
   InstanceKlass* holder = InstanceKlass::cast(clazz);
   Method* method = java_lang_StackFrameInfo::get_method(stackFrame, holder, CHECK);
+  Handle contScopeName(THREAD, stackFrame->obj_field(java_lang_StackFrameInfo::_contScopeName_offset));
 
   short version = stackFrame->short_field(_version_offset);
   short bci = stackFrame->short_field(_bci_offset);
   Symbol* name = method->name();
-  java_lang_StackTraceElement::fill_in(stack_trace_element, holder, method, version, bci, name, CHECK);
+  java_lang_StackTraceElement::fill_in(stack_trace_element, holder, method, version, bci, name, contScopeName, CHECK);
 }
 
 #define STACKFRAMEINFO_FIELDS_DO(macro) \
-  macro(_memberName_offset,     k, "memberName",  object_signature, false); \
-  macro(_bci_offset,            k, "bci",         short_signature,  false)
+  macro(_memberName_offset,     k, "memberName",    object_signature, false); \
+  macro(_bci_offset,            k, "bci",           short_signature,  false); \
+  macro(_contScopeName_offset,  k, "contScopeName", string_signature, false)
 
 void java_lang_StackFrameInfo::compute_offsets() {
   InstanceKlass* k = SystemDictionary::StackFrameInfo_klass();
@@ -4089,6 +4128,7 @@
 int java_lang_ref_Reference::discovered_offset;
 int java_lang_ref_SoftReference::timestamp_offset;
 int java_lang_ref_SoftReference::static_clock_offset;
+int java_lang_ContinuationScope::_name_offset;
 int java_lang_Continuation::_scope_offset;
 int java_lang_Continuation::_target_offset;
 int java_lang_Continuation::_stack_offset;
@@ -4120,9 +4160,11 @@
 int java_lang_StackTraceElement::classLoaderName_offset;
 int java_lang_StackTraceElement::declaringClass_offset;
 int java_lang_StackTraceElement::declaringClassObject_offset;
+int java_lang_StackTraceElement::contScope_offset;
 int java_lang_StackFrameInfo::_memberName_offset;
 int java_lang_StackFrameInfo::_bci_offset;
 int java_lang_StackFrameInfo::_version_offset;
+int java_lang_StackFrameInfo::_contScopeName_offset;
 int java_lang_LiveStackFrameInfo::_monitors_offset;
 int java_lang_LiveStackFrameInfo::_locals_offset;
 int java_lang_LiveStackFrameInfo::_operands_offset;
@@ -4146,7 +4188,8 @@
   macro(declaringClass_offset,  k, "declaringClass",  string_signature, false); \
   macro(methodName_offset,      k, "methodName",      string_signature, false); \
   macro(fileName_offset,        k, "fileName",        string_signature, false); \
-  macro(lineNumber_offset,      k, "lineNumber",      int_signature,    false)
+  macro(lineNumber_offset,      k, "lineNumber",      int_signature,    false); \
+  macro(contScope_offset,       k, "contScopeName",   string_signature, false)
 
 // Support for java_lang_StackTraceElement
 void java_lang_StackTraceElement::compute_offsets() {
@@ -4192,6 +4235,10 @@
   element->obj_field_put(declaringClassObject_offset, value);
 }
 
+void java_lang_StackTraceElement::set_contScopeName(oop element, oop value) {
+  element->obj_field_put(contScope_offset, value);
+}
+
 void java_lang_StackFrameInfo::set_version(oop element, short value) {
   element->short_field_put(_version_offset, value);
 }
@@ -4200,6 +4247,10 @@
   element->int_field_put(_bci_offset, value);
 }
 
+void java_lang_StackFrameInfo::set_contScopeName(oop element, oop value) {
+  element->obj_field_put(_contScopeName_offset, value);
+}
+
 void java_lang_LiveStackFrameInfo::set_monitors(oop element, oop value) {
   element->obj_field_put(_monitors_offset, value);
 }
@@ -4255,6 +4306,22 @@
   o->bool_field_put(deflt_offset, val);
 }
 
+// Support for java.lang.ContinuationScope
+
+#define CONTINUATIONSCOPE_FIELDS_DO(macro) \
+  macro(_name_offset, k, vmSymbols::name_name(), string_signature, false);
+
+void java_lang_ContinuationScope::compute_offsets() {
+  InstanceKlass* k = SystemDictionary::ContinuationScope_klass();
+  CONTINUATIONSCOPE_FIELDS_DO(FIELD_COMPUTE_OFFSET);
+}
+
+#if INCLUDE_CDS
+void java_lang_ContinuationScope::serialize_offsets(SerializeClosure* f) {
+  CONTINUATIONSCOPE_FIELDS_DO(FIELD_SERIALIZE_OFFSET);
+}
+#endif
+
 // Support for java.lang.Continuation
 
 #define CONTINUATION_FIELDS_DO(macro) \
--- a/src/hotspot/share/classfile/javaClasses.hpp	Fri Jan 04 17:53:42 2019 +0000
+++ b/src/hotspot/share/classfile/javaClasses.hpp	Fri Jan 04 17:54:48 2019 +0000
@@ -82,6 +82,7 @@
   f(java_lang_StackTraceElement) \
   f(java_lang_StackFrameInfo) \
   f(java_lang_LiveStackFrameInfo) \
+  f(java_lang_ContinuationScope) \
   f(java_lang_Continuation) \
   f(java_util_concurrent_locks_AbstractOwnableSynchronizer) \
   //end
@@ -538,8 +539,9 @@
     trace_bcis_offset    = 1,
     trace_mirrors_offset = 2,
     trace_names_offset   = 3,
-    trace_next_offset    = 4,
-    trace_size           = 5,
+    trace_conts_offset   = 4,
+    trace_next_offset    = 5,
+    trace_size           = 6,
     trace_chunk_size     = 32
   };
 
@@ -965,6 +967,19 @@
   static void serialize_offsets(SerializeClosure* f) NOT_CDS_RETURN;
 };
 
+// Interface to java.lang.ContinuationScope objects
+class java_lang_ContinuationScope: AllStatic {
+  friend class JavaClasses;
+ private:
+  static int _name_offset;
+
+  static void compute_offsets();
+ public:
+  static void serialize_offsets(SerializeClosure* f) NOT_CDS_RETURN;
+
+  static inline oop name(oop ref);
+};
+  
 // Interface to java.lang.Continuation objects
 class java_lang_Continuation: AllStatic {
   friend class JavaClasses;
@@ -1440,6 +1455,7 @@
   static int methodName_offset;
   static int fileName_offset;
   static int lineNumber_offset;
+  static int contScope_offset;
 
   // Setters
   static void set_classLoaderName(oop element, oop value);
@@ -1450,13 +1466,14 @@
   static void set_fileName(oop element, oop value);
   static void set_lineNumber(oop element, int value);
   static void set_declaringClassObject(oop element, oop value);
+  static void set_contScopeName(oop element, oop value);
 
  public:
   // Create an instance of StackTraceElement
-  static oop create(const methodHandle& method, int bci, TRAPS);
+  static oop create(const methodHandle& method, int bci, Handle contScope, TRAPS);
 
   static void fill_in(Handle element, InstanceKlass* holder, const methodHandle& method,
-                      int version, int bci, Symbol* name, TRAPS);
+                      int version, int bci, Symbol* name, Handle contScopeName, TRAPS);
 
   static void compute_offsets();
   static void serialize_offsets(SerializeClosure* f) NOT_CDS_RETURN;
@@ -1492,15 +1509,17 @@
   static int _memberName_offset;
   static int _bci_offset;
   static int _version_offset;
+  static int _contScopeName_offset;
 
   static Method* get_method(Handle stackFrame, InstanceKlass* holder, TRAPS);
 
 public:
   // Setters
-  static void set_method_and_bci(Handle stackFrame, const methodHandle& method, int bci, TRAPS);
+  static void set_method_and_bci(Handle stackFrame, const methodHandle& method, int bci, oop cont, TRAPS);
   static void set_bci(oop info, int value);
 
   static void set_version(oop info, short value);
+  static void set_contScopeName(oop info, oop value);
 
   static void compute_offsets();
   static void serialize_offsets(SerializeClosure* f) NOT_CDS_RETURN;
--- a/src/hotspot/share/classfile/javaClasses.inline.hpp	Fri Jan 04 17:53:42 2019 +0000
+++ b/src/hotspot/share/classfile/javaClasses.inline.hpp	Fri Jan 04 17:54:48 2019 +0000
@@ -135,6 +135,10 @@
   return InstanceKlass::cast(ref->klass())->reference_type() == REF_PHANTOM;
 }
 
+inline oop java_lang_ContinuationScope::name(oop ref) {
+  return ref->obj_field(_name_offset);
+}
+
 inline oop java_lang_Continuation::scope(oop ref) {
   return ref->obj_field(_scope_offset);
 }
--- a/src/hotspot/share/include/jvm.h	Fri Jan 04 17:53:42 2019 +0000
+++ b/src/hotspot/share/include/jvm.h	Fri Jan 04 17:54:48 2019 +0000
@@ -211,6 +211,9 @@
                   jint frame_count, jint start_index, 
                   jobjectArray frames);
 
+JNIEXPORT void JNICALL
+JVM_SetStackWalkContinuation(JNIEnv *env, jobject stackStream, jlong anchor, jobjectArray frames, jobject cont);
+
 /*
  * java.lang.Thread
  */
--- a/src/hotspot/share/jvmci/jvmciCompilerToVM.cpp	Fri Jan 04 17:53:42 2019 +0000
+++ b/src/hotspot/share/jvmci/jvmciCompilerToVM.cpp	Fri Jan 04 17:54:48 2019 +0000
@@ -843,7 +843,7 @@
   HandleMark hm;
 
   methodHandle method = CompilerToVM::asMethod(jvmci_method);
-  oop element = java_lang_StackTraceElement::create(method, bci, CHECK_NULL);
+  oop element = java_lang_StackTraceElement::create(method, bci, Handle(), CHECK_NULL);
   return JNIHandles::make_local(THREAD, element);
 C2V_END
 
--- a/src/hotspot/share/prims/jvm.cpp	Fri Jan 04 17:53:42 2019 +0000
+++ b/src/hotspot/share/prims/jvm.cpp	Fri Jan 04 17:54:48 2019 +0000
@@ -601,7 +601,6 @@
                                   jint frame_count, jint start_index, 
                                   jobjectArray frames))
   JVMWrapper("JVM_MoreStackWalk");
-  JavaThread* jt = (JavaThread*) THREAD;
 
   // frames array is a Class<?>[] array when only getting caller reference,
   // and a StackFrameInfo[] array (or derivative) otherwise. It should never
@@ -619,6 +618,17 @@
                                   start_index, frames_array_h, THREAD);
 JVM_END
 
+JVM_ENTRY(void, JVM_SetStackWalkContinuation(JNIEnv *env, jobject stackStream, jlong anchor, jobjectArray frames, jobject cont))
+    JVMWrapper("JVM_SetStackWalkContinuation");
+
+    objArrayOop fa = objArrayOop(JNIHandles::resolve_non_null(frames));
+    objArrayHandle frames_array_h(THREAD, fa);
+    Handle stackStream_h(THREAD, JNIHandles::resolve_non_null(stackStream));
+    Handle cont_h(THREAD, JNIHandles::resolve_non_null(cont));
+
+    StackWalk::setContinuation(stackStream_h, anchor, frames_array_h, cont_h, THREAD);
+JVM_END
+
 // java.lang.Object ///////////////////////////////////////////////
 
 
--- a/src/hotspot/share/prims/stackwalk.cpp	Fri Jan 04 17:53:42 2019 +0000
+++ b/src/hotspot/share/prims/stackwalk.cpp	Fri Jan 04 17:54:48 2019 +0000
@@ -59,6 +59,14 @@
   return ok;
 }
 
+void BaseFrameStream::set_continuation(Handle cont) {
+  // ensure that the lifetime of the handle is that of the entire walk
+  // This actually also sets a copy of the handle in the RegisterMap,
+  // but that's OK, because we want them to be the same, anyway.
+  // (although we don't rely on this sharing, and set the other copy again)
+  *(_continuation.raw_value()) = cont(); 
+}
+
 // static inline Handle continuation_of(Handle cont_or_scope) {
 //   return (cont_or_scope.not_null() && cont_or_scope()->is_a(SystemDictionary::Continuation_klass()))
 //             ? cont_or_scope
@@ -76,18 +84,50 @@
   : BaseFrameStream(thread, cont), 
    _vfst(cont.is_null()
       ? vframeStream(thread, cont_scope)
-      : vframeStream(cont, cont_scope)) {
+      : vframeStream(cont)) {
   _need_method_info = StackWalk::need_method_info(mode);
 }
 
 LiveFrameStream::LiveFrameStream(JavaThread* thread, RegisterMap* rm, Handle cont_scope, Handle cont)
-   : BaseFrameStream(thread, cont), _cont_scope(cont_scope) {
+   : BaseFrameStream(thread, cont), _cont_scope(cont_scope),
+    _cont(cont.not_null() ? cont : Handle(thread, thread->last_continuation())) {
      
-    _jvf = cont.is_null() ? thread->last_java_vframe(rm)
-                          : Continuation::last_java_vframe(cont(), rm);
+    _map = rm;
+    if (cont.is_null()) {
+      _jvf  = thread->last_java_vframe(rm);
+      // _cont = Handle(thread, thread->last_continuation());
+    } else {
+      _jvf  = Continuation::last_java_vframe(cont, rm);
+      // _cont = cont;
+    }
 }
 
-void JavaFrameStream::next() { _vfst.next();}
+void JavaFrameStream::set_continuation(Handle cont) {
+  BaseFrameStream::set_continuation(cont);
+
+  _vfst = vframeStream(continuation()); // we must not use the handle argument (lifetime; see BaseFrameStream::set_continuation)
+}
+
+void LiveFrameStream::set_continuation(Handle cont) {
+  BaseFrameStream::set_continuation(cont);
+
+  _jvf = Continuation::last_java_vframe(continuation(), _map); // we must not use the handle argument (lifetime; see BaseFrameStream::set_continuation)
+  _cont = cont;
+}
+
+void JavaFrameStream::next() { _vfst.next(); }
+
+void LiveFrameStream::next() { 
+  if (_cont.not_null() && Continuation::is_continuation_entry_frame(_jvf->fr(), _jvf->register_map())) {
+    *(_cont.raw_value()) = java_lang_Continuation::parent(_cont());
+  }
+  
+  if (Continuation::is_scope_bottom(_cont_scope(), _jvf->fr(), _jvf->register_map())) {
+    _jvf = NULL;
+  } else {
+    _jvf = _jvf->java_sender();
+  }
+}
 
 // Returns the BaseFrameStream for the current stack being traversed.
 //
@@ -309,7 +349,7 @@
 
 // Fill StackFrameInfo with bci and initialize memberName
 void BaseFrameStream::fill_stackframe(Handle stackFrame, const methodHandle& method, TRAPS) {
-  java_lang_StackFrameInfo::set_method_and_bci(stackFrame, method, bci(), THREAD);
+  java_lang_StackFrameInfo::set_method_and_bci(stackFrame, method, bci(), cont(), THREAD);
 }
 
 // Fill LiveStackFrameInfo with locals, monitors, and expressions
@@ -396,7 +436,6 @@
     Klass* abstractStackWalker_klass = SystemDictionary::AbstractStackWalker_klass();
     while (!stream.at_end()) {
       InstanceKlass* ik = stream.method()->method_holder();
-      // XXXXXX skip stackWalker frames XXXXXXX
       if (ik != stackWalker_klass &&
             ik != abstractStackWalker_klass && ik->super() != abstractStackWalker_klass)  {
         break;
@@ -520,3 +559,18 @@
   }
   return end_index;
 }
+
+void StackWalk::setContinuation(Handle stackStream, jlong magic, objArrayHandle frames_array, Handle cont, TRAPS) {
+  JavaThread* jt = (JavaThread*)THREAD;
+
+  if (frames_array.is_null()) {
+    THROW_MSG(vmSymbols::java_lang_NullPointerException(), "frames_array is NULL");
+  }
+
+  BaseFrameStream* existing_stream = BaseFrameStream::from_current(jt, magic, frames_array);
+  if (existing_stream == NULL) {
+    THROW_MSG(vmSymbols::java_lang_InternalError(), "doStackWalk: corrupted buffers");
+  }
+
+  existing_stream->set_continuation(cont);
+}
--- a/src/hotspot/share/prims/stackwalk.hpp	Fri Jan 04 17:53:42 2019 +0000
+++ b/src/hotspot/share/prims/stackwalk.hpp	Fri Jan 04 17:54:48 2019 +0000
@@ -57,9 +57,13 @@
 
   virtual Method* method()=0;
   virtual int     bci()=0;
+  virtual oop     cont()=0; // returns the current continuation (even when walking a thread)
 
   virtual void    fill_frame(int index, objArrayHandle  frames_array,
                              const methodHandle& method, TRAPS)=0;
+  
+  Handle continuation() { return _continuation; }
+  virtual void set_continuation(Handle cont);
 
   void setup_magic_on_entry(objArrayHandle frames_array);
   bool check_magic(objArrayHandle frames_array);
@@ -89,9 +93,12 @@
 
   Method* method() { return _vfst.method(); }
   int bci()        { return _vfst.bci(); }
+  oop cont()       { return _vfst.continuation(); }
 
   void fill_frame(int index, objArrayHandle  frames_array,
                   const methodHandle& method, TRAPS);
+
+  void set_continuation(Handle cont);
 };
 
 class LiveFrameStream : public BaseFrameStream {
@@ -101,8 +108,11 @@
     MODE_COMPILED    = 0x02
   };
 
+  Handle                _cont_scope;  // the delimitation of this walk
+
+  RegisterMap*          _map;
   javaVFrame*           _jvf;
-  Handle                _cont_scope;
+  Handle                _cont; // the current continuation
 
   void fill_live_stackframe(Handle stackFrame, const methodHandle& method, TRAPS);
   static oop create_primitive_slot_instance(StackValueCollection* values,
@@ -113,14 +123,17 @@
 public:
   LiveFrameStream(JavaThread* thread, RegisterMap* rm, Handle cont_scope, Handle cont);
 
-  void next()      { _jvf = _jvf->java_sender(); }
-  bool at_end()    { return _jvf == NULL || Continuation::is_scope_bottom(_cont_scope(), _jvf->fr(), _jvf->register_map()); }
+  void next();
+  bool at_end()    { return _jvf == NULL; }
 
   Method* method() { return _jvf->method(); }
   int bci()        { return _jvf->bci(); }
+  oop cont()       { return _jvf->continuation(); }
 
   void fill_frame(int index, objArrayHandle  frames_array,
                   const methodHandle& method, TRAPS);
+
+  void set_continuation(Handle cont);
 };
 
 class StackWalk : public AllStatic {
@@ -158,5 +171,8 @@
   static jint fetchNextBatch(Handle stackStream, jlong mode, jlong magic,
                              int frame_count, int start_index,
                              objArrayHandle frames_array, TRAPS);
+
+  static void setContinuation(Handle stackStream, jlong magic, objArrayHandle frames_array, 
+                              Handle cont, TRAPS);
 };
 #endif // SHARE_VM_PRIMS_STACKWALK_HPP
--- a/src/hotspot/share/runtime/continuation.cpp	Fri Jan 04 17:53:42 2019 +0000
+++ b/src/hotspot/share/runtime/continuation.cpp	Fri Jan 04 17:54:48 2019 +0000
@@ -161,7 +161,7 @@
 }
 
 static oop get_continuation(JavaThread* thread) {
-  return java_lang_Thread::continuation(thread->threadObj());
+  return thread->last_continuation();
 }
 
 static long java_tid(JavaThread* thread) {
@@ -2340,12 +2340,13 @@
 
 typedef int (*DoYieldStub)(int scopes);
 
+// called in a safepoint
 int Continuation::try_force_yield(JavaThread* thread, oop cont) {
-
+  // this is the only place where we traverse the continuatuion hierarchy in native code, as it needs to be done in a safepoint
+  oop scope = NULL;
   oop innermost = get_continuation(thread);
-  oop scope = NULL;
   for (oop c = innermost; c != NULL; c = java_lang_Continuation::parent(c)) {
-    if (c == cont) {
+    if (oopDesc::equals(c, cont)) {
       scope = java_lang_Continuation::scope(c);
       break;
     }
@@ -2356,10 +2357,16 @@
   if (thread->_cont_yield) {
     return -2; // during yield
   }
-  if (innermost != cont) {
+  if (!oopDesc::equals(innermost, cont)) { // we have nested continuations
+    // make sure none of the continuations in the hierarchy are pinned
+    // for (oop c = innermost; c != NULL && !oopDesc::equals(c, cont); c = java_lang_Continuation::parent(c)) {
+    //   if ()
+    //     return PINNED;
+    // }
+
     java_lang_Continuation::set_yieldInfo(cont, scope);
   }
-  
+
 // #ifdef ASSERT
 //   tty->print_cr("FREEZING:");
 //   frame lf = thread->last_frame();
@@ -3090,19 +3097,22 @@
 
   // tty->print_cr("continuation_top_frame");
   
-  map->set_cont(map->thread(), contOop);
+  if (!oopDesc::equals(map->cont(), contOop))
+    map->set_cont(map->thread(), contOop);
+
   return hf.to_frame(cont);
 }
 
 static frame continuation_parent_frame(ContMirror& cont, RegisterMap* map) {
   assert (map->thread() != NULL || cont.entryPC() == NULL, "");
-  if (map->thread() == NULL) { // When a continuation is mounted, its entry frame is always on the v-stack
-    oop parentOop = java_lang_Continuation::parent(cont.mirror());
-    if (parentOop != NULL) {
-      // tty->print_cr("continuation_parent_frame: parent");
-      return continuation_top_frame(parentOop, map);
-    }
-  }
+
+  // if (map->thread() == NULL) { // When a continuation is mounted, its entry frame is always on the v-stack
+  //   oop parentOop = java_lang_Continuation::parent(cont.mirror());
+  //   if (parentOop != NULL) {
+  //     // tty->print_cr("continuation_parent_frame: parent");
+  //     return continuation_top_frame(parentOop, map);
+  //   }
+  // }
   
   map->set_cont(map->thread(), NULL);
   if (cont.entryPC() == NULL) { // When we're walking an unmounted continuation and reached the end
@@ -3118,18 +3128,19 @@
   return sender;
 }
 
-frame Continuation::last_frame(oop continutation, RegisterMap *map) {
+frame Continuation::last_frame(Handle continuation, RegisterMap *map) {
   assert(map != NULL, "a map must be given");
-  return continuation_top_frame(continutation, map);
+  map->set_cont(continuation);
+  return continuation_top_frame(continuation(), map);
 }
 
-bool Continuation::has_last_Java_frame(oop continutation) {
-  return (java_lang_Continuation::sp(continutation) >= 0);
+bool Continuation::has_last_Java_frame(Handle continuation) {
+  return java_lang_Continuation::pc(continuation()) != NULL;
 }
 
-javaVFrame* Continuation::last_java_vframe(oop continutation, RegisterMap *map) {
+javaVFrame* Continuation::last_java_vframe(Handle continuation, RegisterMap *map) {
   assert(map != NULL, "a map must be given");
-  frame f = last_frame(continutation, map);
+  frame f = last_frame(continuation, map);
   for (vframe* vf = vframe::new_vframe(&f, map, NULL); vf; vf = vf->sender()) {
     if (vf->is_java_frame()) return javaVFrame::cast(vf);
   }
--- a/src/hotspot/share/runtime/continuation.hpp	Fri Jan 04 17:53:42 2019 +0000
+++ b/src/hotspot/share/runtime/continuation.hpp	Fri Jan 04 17:54:48 2019 +0000
@@ -69,9 +69,9 @@
   static frame sender_for_interpreter_frame(const frame& callee, RegisterMap* map);
   static frame sender_for_compiled_frame(const frame& callee, RegisterMap* map);
 
-  static bool has_last_Java_frame(oop continutation);
-  static frame last_frame(oop continutation, RegisterMap *map);
-  static javaVFrame* last_java_vframe(oop continutation, RegisterMap *map);
+  static bool has_last_Java_frame(Handle continuation);
+  static frame last_frame(Handle continuation, RegisterMap *map);
+  static javaVFrame* last_java_vframe(Handle continuation, RegisterMap *map);
 
   // access frame data
   static address usp_offset_to_location(const frame& fr, const RegisterMap* map, const int usp_offset_in_bytes);
--- a/src/hotspot/share/runtime/frame.cpp	Fri Jan 04 17:53:42 2019 +0000
+++ b/src/hotspot/share/runtime/frame.cpp	Fri Jan 04 17:54:48 2019 +0000
@@ -77,6 +77,7 @@
   _walk_cont     = map->_walk_cont;
 
   _cont = map->_cont;
+
   pd_initialize_from(map);
   if (update_map()) {
     for(int i = 0; i < location_valid_size; i++) {
@@ -98,7 +99,7 @@
 
 void RegisterMap::set_cont(Thread* thread, oop cont) {
   // tty->print_cr("set_cont: %d", cont != NULL);
-  _cont = cont != NULL ? Handle(thread != NULL ? thread : Thread::current(), cont) : Handle();
+  set_cont(cont != NULL ? Handle(thread != NULL ? thread : Thread::current(), cont) : Handle());
 }
 
 void RegisterMap::clear() {
@@ -111,6 +112,7 @@
   } else {
     pd_initialize();
   }
+  _cont = Handle();
 }
 
 #ifndef PRODUCT
--- a/src/hotspot/share/runtime/registerMap.hpp	Fri Jan 04 17:53:42 2019 +0000
+++ b/src/hotspot/share/runtime/registerMap.hpp	Fri Jan 04 17:54:48 2019 +0000
@@ -134,6 +134,7 @@
   JavaThread *thread() const { return _thread; }
   oop  cont()          const { return _cont(); }
   void set_cont(Thread* thread, oop cont);
+  void set_cont(Handle cont) {  _cont = cont; }
   bool update_map()    const { return _update_map; }
   bool walk_cont()     const { return _walk_cont; }
   bool validate_oops() const { return _validate_oops; }
--- a/src/hotspot/share/runtime/thread.cpp	Fri Jan 04 17:53:42 2019 +0000
+++ b/src/hotspot/share/runtime/thread.cpp	Fri Jan 04 17:54:48 2019 +0000
@@ -3313,6 +3313,9 @@
   return NULL;
 }
 
+oop JavaThread::last_continuation() {
+  return java_lang_Thread::continuation(threadObj());
+}
 
 Klass* JavaThread::security_get_caller_class(int depth) {
   vframeStream vfst(this);
--- a/src/hotspot/share/runtime/thread.hpp	Fri Jan 04 17:53:42 2019 +0000
+++ b/src/hotspot/share/runtime/thread.hpp	Fri Jan 04 17:54:48 2019 +0000
@@ -1857,6 +1857,8 @@
   }
   javaVFrame* last_java_vframe(RegisterMap* reg_map);
 
+  oop last_continuation();
+  
   // Returns method at 'depth' java or native frames down the stack
   // Used for security checks
   Klass* security_get_caller_class(int depth);
--- a/src/hotspot/share/runtime/vframe.cpp	Fri Jan 04 17:53:42 2019 +0000
+++ b/src/hotspot/share/runtime/vframe.cpp	Fri Jan 04 17:54:48 2019 +0000
@@ -499,23 +499,29 @@
   }
 
   _frame = _thread->last_frame();
+  oop cont = _thread->last_continuation();
   while (!fill_from_frame()) {
+    if (cont != (oop)NULL && Continuation::is_continuation_entry_frame(_frame, &_reg_map)) {
+      cont = java_lang_Continuation::parent(cont);
+    }
     _frame = _frame.sender(&_reg_map);
   }
+  _cont = Handle(thread, cont);
 }
 
-vframeStream::vframeStream(Handle continuation, Handle continuation_scope) 
+vframeStream::vframeStream(Handle continuation) 
  : vframeStreamCommon(RegisterMap(NULL, false, true)) {
 
   _stop_at_java_call_stub = false;
-  _continuation_scope = continuation_scope;
+  _continuation_scope = Handle();
   
-  if (!Continuation::has_last_Java_frame(continuation())) {
+  if (!Continuation::has_last_Java_frame(continuation)) {
     _mode = at_end_mode;
     return;
   }
 
-  _frame = Continuation::last_frame(continuation(), &_reg_map);
+  _frame = Continuation::last_frame(continuation, &_reg_map);
+  _cont = continuation;
   while (!fill_from_frame()) {
     _frame = _frame.sender(&_reg_map);
   }
--- a/src/hotspot/share/runtime/vframe.hpp	Fri Jan 04 17:53:42 2019 +0000
+++ b/src/hotspot/share/runtime/vframe.hpp	Fri Jan 04 17:54:48 2019 +0000
@@ -74,6 +74,7 @@
   frame*             frame_pointer() { return &_fr;       }
   const RegisterMap* register_map() const { return &_reg_map; }
   JavaThread*        thread()       const { return _thread;   }
+  oop                continuation() const { return _reg_map.cont(); }
 
   // Returns the sender vframe
   virtual vframe* sender() const;
@@ -292,6 +293,7 @@
   // Cached information
   Method* _method;
   int       _bci;
+  Handle   _cont; // the current frame's continuation
 
   // Should VM activations be ignored or not
   bool _stop_at_java_call_stub;
@@ -319,6 +321,7 @@
   int bci() const { return _bci; }
   inline intptr_t* frame_id() const;
   address frame_pc() const { return _frame.pc(); }
+  oop continuation() const { return _cont(); }
 
   CodeBlob*          cb()         const { return _frame.cb();  }
   CompiledMethod*   nm()         const {
@@ -357,7 +360,7 @@
   // top_frame may not be at safepoint, start with sender
   vframeStream(JavaThread* thread, frame top_frame, bool stop_at_java_call_stub = false);
 
-  vframeStream(Handle continuation, Handle continuation_scope);
+  vframeStream(Handle continuation);
 };
 
 #endif // SHARE_VM_RUNTIME_VFRAME_HPP
--- a/src/hotspot/share/runtime/vframe.inline.hpp	Fri Jan 04 17:53:42 2019 +0000
+++ b/src/hotspot/share/runtime/vframe.inline.hpp	Fri Jan 04 17:54:48 2019 +0000
@@ -48,6 +48,14 @@
 
   // handle general case
   do {
+    if (_cont.not_null() && Continuation::is_continuation_entry_frame(_frame, &_reg_map)) {
+      *(_cont.raw_value()) = java_lang_Continuation::parent(_cont());
+    }
+    if (Continuation::is_scope_bottom(_continuation_scope(), _frame, &_reg_map)) {
+      _mode = at_end_mode;
+      break;
+    }
+
     _prev_frame = _frame;
     _frame = _frame.sender(&_reg_map);
   } while (!fill_from_frame());
@@ -63,10 +71,15 @@
   }
 
   _frame = _thread->last_frame();
+  oop cont = _thread->last_continuation();
   while (!fill_from_frame()) {
+    if (cont != (oop)NULL && Continuation::is_continuation_entry_frame(_frame, &_reg_map)) {
+      cont = java_lang_Continuation::parent(cont);
+    }
     _prev_frame = _frame;
     _frame = _frame.sender(&_reg_map);
   }
+  _cont = Handle(thread, cont);
 }
 
 inline bool vframeStreamCommon::fill_in_compiled_inlined_sender() {
@@ -141,10 +154,6 @@
   // Interpreted frame
   if (_frame.is_interpreted_frame()) {
     fill_from_interpreter_frame();
-
-    if (Continuation::is_scope_bottom(_continuation_scope(), _frame, &_reg_map))
-      _mode = at_end_mode;
-
     return true;
   }
 
@@ -207,9 +216,6 @@
       }
       fill_from_compiled_frame(decode_offset);
 
-      if (Continuation::is_scope_bottom(_continuation_scope(), _frame, &_reg_map))
-        _mode = at_end_mode;
-
       _vframe_id = 0;
     }
     return true;
--- a/src/hotspot/share/services/threadService.cpp	Fri Jan 04 17:53:42 2019 +0000
+++ b/src/hotspot/share/services/threadService.cpp	Fri Jan 04 17:54:48 2019 +0000
@@ -537,6 +537,7 @@
   _bci = jvf->bci();
   _class_holder = _method->method_holder()->klass_holder();
   _locked_monitors = NULL;
+  _cont_scope_name = jvf->continuation() != NULL ? java_lang_ContinuationScope::name(java_lang_Continuation::scope(jvf->continuation())) : NULL;
   if (with_lock_info) {
     ResourceMark rm;
     GrowableArray<MonitorInfo*>* list = jvf->locked_monitors();
@@ -560,6 +561,7 @@
     }
   }
   f->do_oop(&_class_holder);
+  f->do_oop(&_cont_scope_name);
 }
 
 void StackFrameInfo::metadata_do(void f(Metadata*)) {
@@ -681,7 +683,8 @@
   for (int j = 0; j < _depth; j++) {
     StackFrameInfo* frame = _frames->at(j);
     methodHandle mh(THREAD, frame->method());
-    oop element = java_lang_StackTraceElement::create(mh, frame->bci(), CHECK_NH);
+    Handle contScopeNameH(THREAD, frame->cont_scope_name());
+    oop element = java_lang_StackTraceElement::create(mh, frame->bci(), contScopeNameH, CHECK_NH);
     backtrace->obj_at_put(j, element);
   }
   return backtrace;
--- a/src/hotspot/share/services/threadService.hpp	Fri Jan 04 17:53:42 2019 +0000
+++ b/src/hotspot/share/services/threadService.hpp	Fri Jan 04 17:54:48 2019 +0000
@@ -287,6 +287,7 @@
  private:
   Method*             _method;
   int                 _bci;
+  oop                 _cont_scope_name;
   GrowableArray<oop>* _locked_monitors; // list of object monitors locked by this frame
   // We need to save the mirrors in the backtrace to keep the class
   // from being unloaded while we still have this stack trace.
@@ -300,8 +301,9 @@
       delete _locked_monitors;
     }
   };
-  Method*   method() const       { return _method; }
-  int       bci()    const       { return _bci; }
+  Method*   method() const          { return _method; }
+  int       bci()    const          { return _bci; }
+  oop       cont_scope_name() const { return _cont_scope_name; }
   void      oops_do(OopClosure* f);
   void      metadata_do(void f(Metadata*));
 
--- a/src/java.base/share/classes/java/lang/Continuation.java	Fri Jan 04 17:53:42 2019 +0000
+++ b/src/java.base/share/classes/java/lang/Continuation.java	Fri Jan 04 17:54:48 2019 +0000
@@ -38,6 +38,7 @@
 import java.util.Set;
 import java.util.concurrent.ConcurrentHashMap;
 import java.util.concurrent.atomic.AtomicBoolean;
+import java.util.function.Supplier;
 
 /**
  * TBD
@@ -69,7 +70,11 @@
 
         final Pinned pinned;
         private PreemptStatus(Pinned reason) { this.pinned = reason; }
-        Pinned pinned() { return pinned; }
+        /** 
+         * TBD
+         * @return TBD
+         **/
+        public Pinned pinned() { return pinned; }
     }
 
     private static Thread currentCarrierThread() {
@@ -87,8 +92,13 @@
         }
     }
 
+    private Runnable target;
+
+    /* While the native JVM code is aware that every continuation has a scope, it is, for the most part,
+     * oblivious to the continuation hierarchy. The only time this hierarchy is traversed in native code
+     * is when a hierarchy of continuations is mounted on the native stack.
+     */
     private final ContinuationScope scope;
-    private Runnable target;
     private Continuation parent; // null for native stack
     private Continuation child; // non-null when we're yielded in a child continuation
 
@@ -151,6 +161,14 @@
         return super.toString() + " scope: " + scope;
     }
 
+    ContinuationScope getScope() {
+        return scope;
+    }
+
+    Continuation getParent() {
+        return parent;
+    }
+
     /**
      * TBD
      * @param scope TBD
@@ -220,6 +238,22 @@
         return stackWalker().walk(s -> s.map(StackWalker.StackFrame::toStackTraceElement).toArray(StackTraceElement[]::new));
     }
 
+    /// Support for StackWalker
+    static <R> R wrapWalk(Continuation inner, ContinuationScope scope, Supplier<R> walk) {
+        try {
+            for (Continuation c = inner; c != null && c.scope != scope; c = c.parent)
+                c.mount();
+
+            // if (!inner.isStarted())
+            //     throw new IllegalStateException("Continuation not started");
+                
+            return walk.get();
+        } finally {
+            for (Continuation c = inner; c != null && c.scope != scope; c = c.parent)
+                c.unmount();
+        }
+    }
+
     private Continuation innermost() {
         Continuation c = this;
         while (c.child != null)
@@ -227,12 +261,12 @@
         return c;
     }
 
-    void mount() {
+    private void mount() {
         if (!compareAndSetMounted(false, true))
             throw new IllegalStateException("Mounted!!!!");
     }
 
-    void unmount() {
+    private void unmount() {
         setMounted(false);
     }
     
@@ -307,7 +341,7 @@
         // This method runs in the "entry frame".
         // A yield jumps to this method's caller as if returning from this method.
         try {
-            if (stack == null || sp >= stack.length) { // is this the first run? (at this point we know !done)
+            if (!isStarted()) { // is this the first run? (at this point we know !done)
                 if (TRACE)
                     System.out.println("ENTERING " + id());
                 this.entrySP = getSP();
@@ -329,6 +363,10 @@
         target.run();
     }
 
+    private boolean isStarted() {
+        return stack != null && sp < stack.length;
+    }
+
     /**
      * TBD
      * 
@@ -776,8 +814,12 @@
 
     /**
      * TBD
+     * Subclasses may throw an {@link UnsupportedOperationException}, but this does not prevent
+     * the continuation from being preempted on a parent scope.
+     * 
      * @param thread TBD
      * @return TBD
+     * @throws UnsupportedOperationException if this continuation does not support preemption
      */
     public PreemptStatus tryPreempt(Thread thread) {
         return preemptStatus(tryForceYield0(thread));
--- a/src/java.base/share/classes/java/lang/ContinuationScope.java	Fri Jan 04 17:53:42 2019 +0000
+++ b/src/java.base/share/classes/java/lang/ContinuationScope.java	Fri Jan 04 17:54:48 2019 +0000
@@ -45,11 +45,29 @@
      * A constructor providing no name is available to subclasses.
      */
     protected ContinuationScope() {
-        this.name = null;
+        this.name = getClass().getName();
+    }
+
+    /**
+     * Returns this scope's name.
+     * @return this scope's name
+     */
+    public final String getName() {
+        return name;
     }
 
     @Override
-    public String toString() {
-        return name != null ? name : getClass().getName();
+    public final String toString() {
+        return name;
+    }
+
+    @Override
+    public final int hashCode() {
+        return super.hashCode();
+    }
+
+    @Override
+    public final boolean equals(Object obj) {
+        return super.equals(obj);
     }
 }
--- a/src/java.base/share/classes/java/lang/LiveStackFrameInfo.java	Fri Jan 04 17:53:42 2019 +0000
+++ b/src/java.base/share/classes/java/lang/LiveStackFrameInfo.java	Fri Jan 04 17:54:48 2019 +0000
@@ -42,6 +42,15 @@
     private int mode = 0;
 
     @Override
+    protected void clear() {
+        super.clear();
+        monitors = EMPTY_ARRAY;
+        locals = EMPTY_ARRAY;
+        operands = EMPTY_ARRAY;
+        mode = 0;
+    }
+
+    @Override
     public Object[] getMonitors() {
         return monitors;
     }
--- a/src/java.base/share/classes/java/lang/StackFrameInfo.java	Fri Jan 04 17:53:42 2019 +0000
+++ b/src/java.base/share/classes/java/lang/StackFrameInfo.java	Fri Jan 04 17:54:48 2019 +0000
@@ -29,6 +29,7 @@
 
 import java.lang.StackWalker.StackFrame;
 import java.lang.invoke.MethodType;
+import java.lang.reflect.Method;
 
 class StackFrameInfo implements StackFrame {
     private final byte RETAIN_CLASS_REF = 0x01;
@@ -37,8 +38,10 @@
         SharedSecrets.getJavaLangInvokeAccess();
 
     private final byte flags;
-    private final Object memberName;
-    private final short bci;
+    private Object memberName;
+    private short bci;
+    private String contScopeName;
+
     private volatile StackTraceElement ste;
 
     /*
@@ -57,6 +60,21 @@
         return JLIA.getDeclaringClass(memberName);
     }
 
+    void setMemberName(Method method) {
+        this.memberName = JLIA.newMemberName(method);
+    }
+
+    void setBCI(short bci) {
+        this.bci = bci;
+    }
+
+    void setContinuationScopeName(String contScopeName) {
+        this.contScopeName = contScopeName;
+    }
+    
+    protected void clear() {
+    }
+
     // ----- implementation of StackFrame methods
 
     @Override
@@ -116,6 +134,11 @@
     }
 
     @Override
+    public java.lang.String getContinuationScopeName() {
+        return contScopeName;
+    }
+
+    @Override
     public String toString() {
         return toStackTraceElement().toString();
     }
--- a/src/java.base/share/classes/java/lang/StackStreamFactory.java	Fri Jan 04 17:53:42 2019 +0000
+++ b/src/java.base/share/classes/java/lang/StackStreamFactory.java	Fri Jan 04 17:54:48 2019 +0000
@@ -32,6 +32,8 @@
 import java.lang.annotation.Native;
 import java.lang.reflect.Method;
 import java.lang.reflect.Constructor;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
 import java.util.HashSet;
 import java.util.NoSuchElementException;
 import java.util.Objects;
@@ -127,7 +129,7 @@
         protected FrameBuffer<? extends T> frameBuffer;
         protected long anchor;
         protected final ContinuationScope contScope;
-        protected final Continuation continuation;
+        protected Continuation continuation;
 
         // buffers to fill in stack frame information
         protected AbstractStackWalker(StackWalker walker, int mode) {
@@ -240,8 +242,12 @@
          */
         final R walk() {
             checkState(NEW);
-            Continuation cont = walker.getContinuation();
-            if (cont != null) cont.mount();
+            return continuation != null
+                ? Continuation.wrapWalk(continuation, contScope, this::walkHelper)
+                : walkHelper();
+        }
+
+        private final R walkHelper() {
             try {
                 // VM will need to stablize the stack before walking.  It will invoke
                 // the AbstractStackWalker::doStackWalk method once it fetches the first batch.
@@ -249,7 +255,6 @@
                 return beginStackWalk();
             } finally {
                 close();  // done traversal; close the stream
-                if (cont != null) cont.unmount();
             }
         }
 
@@ -307,6 +312,12 @@
             }
 
             this.anchor = anchor;  // set anchor for this bulk stack frame traversal
+
+            int numFrames = bufEndIndex - bufStartIndex;        
+            if (numFrames > 0 && numFrames < batchSize && continuation != null) {
+                makeContinuationEnterFrame(bufEndIndex);
+                bufEndIndex++;
+            }
             frameBuffer.setBatch(depth, bufStartIndex, bufEndIndex);
 
             // traverse all frames and perform the action on the stack frames, if specified
@@ -318,7 +329,8 @@
          */
         private int getNextBatch() {
             int nextBatchSize = Math.min(maxDepth - depth, getNextBatchSize());
-            if (!frameBuffer.isActive() || nextBatchSize <= 0) {
+
+            if (!frameBuffer.isActive() || nextBatchSize <= 0 || (frameBuffer.isAtBottom() && !hasMoreContinuations())) {
                 if (isDebug) {
                     System.out.format("  more stack walk done%n");
                 }
@@ -326,7 +338,24 @@
                 return 0;
             }
 
-            return fetchStackFrames(nextBatchSize);
+            if (frameBuffer.isAtBottom() && hasMoreContinuations()) {
+                setContinuation(continuation.getParent());
+            }
+
+            int numFrames = fetchStackFrames(nextBatchSize);
+            if (numFrames == 0 && !hasMoreContinuations()) {
+                frameBuffer.freeze(); // done stack walking
+            }
+            return numFrames;
+        }
+
+        private boolean hasMoreContinuations() {
+            return continuation != null && continuation.getScope() != contScope && continuation.getParent() != null;
+        }
+
+        private void setContinuation(Continuation cont) {
+            this.continuation = cont;
+            setContinuation(anchor, frameBuffer.frames(), cont);
         }
 
         /*
@@ -398,16 +427,27 @@
                 System.out.format("  more stack walk requesting %d got %d to %d frames%n",
                                   batchSize, frameBuffer.startIndex(), endIndex);
             }
+
             int numFrames = endIndex - startIndex;
-            if (numFrames == 0) {
-                frameBuffer.freeze(); // done stack walking
-            } else {
+
+            if (numFrames < batchSize && continuation != null) {
+                makeContinuationEnterFrame(endIndex);
+                endIndex++;
+                numFrames++;
+            }
+
+            if (numFrames > 0) {
                 frameBuffer.setBatch(depth, startIndex, endIndex);
             }
             return numFrames;
         }
 
         /**
+         * Create a synthetic frame for {@code Continuation.enter}.
+         */
+        protected abstract void makeContinuationEnterFrame(int index);
+
+        /**
          * Begins stack walking.  This method anchors this frame and invokes
          * AbstractStackWalker::doStackWalk after fetching the first batch of stack frames.
          *
@@ -441,6 +481,8 @@
         private native int fetchStackFrames(long mode, long anchor,
                                             int batchSize, int startIndex,
                                             T[] frames);
+
+        private native void setContinuation(long anchor, T[] frames, Continuation cont);
     }
 
     /*
@@ -510,6 +552,23 @@
             }
         }
 
+        @Override
+        protected final void makeContinuationEnterFrame(int index) {
+            PrivilegedAction<Method> pa = () -> {
+                try {
+                    return Continuation.class.getDeclaredMethod("enter");
+                } catch(NoSuchMethodException | SecurityException e) {
+                    throw new AssertionError(e);
+                }
+            };
+            Method enter = AccessController.doPrivileged(pa);
+            StackFrameInfo sfi = frameBuffer.frames()[index];
+            sfi.clear();
+            sfi.setMemberName(enter);
+            sfi.setBCI((short)-1);
+            sfi.setContinuationScopeName(continuation.getScope().getName());
+        }
+
         final Function<? super Stream<StackFrame>, ? extends T> function;  // callback
 
         StackFrameTraverser(StackWalker walker,
@@ -716,6 +775,11 @@
         protected int getNextBatchSize() {
             return MIN_BATCH_SIZE;
         }
+
+        @Override
+        protected final void makeContinuationEnterFrame(int index) {
+            throw new InternalError("should not reach here");
+        }
     }
 
     static final class LiveStackInfoTraverser<T> extends StackFrameTraverser<T> {
@@ -892,7 +956,15 @@
          * it is done for traversal.  All stack frames have been traversed.
          */
         final boolean isActive() {
-            return origin > 0 && (fence == 0 || origin < fence || fence == currentBatchSize);
+            return origin > 0; //  && (fence == 0 || origin < fence || fence == currentBatchSize);
+        }
+
+        /*
+         * Tests if this frame buffer is at the end of the stack
+         * and all frames have been traversed.
+         */
+        final boolean isAtBottom() {
+            return origin > 0 && origin >= fence && fence < currentBatchSize;
         }
 
         /**
--- a/src/java.base/share/classes/java/lang/StackTraceElement.java	Fri Jan 04 17:53:42 2019 +0000
+++ b/src/java.base/share/classes/java/lang/StackTraceElement.java	Fri Jan 04 17:54:48 2019 +0000
@@ -66,6 +66,7 @@
     private String declaringClass;
     private String methodName;
     private String fileName;
+    private String contScopeName;
     private int    lineNumber;
     private byte   format = 0; // Default to show all
 
@@ -353,11 +354,21 @@
         }
         s = s.isEmpty() ? declaringClass : s + "/" + declaringClass;
 
-        return s + "." + methodName + "(" +
+        s = s + "." + methodName + "(" +
              (isNativeMethod() ? "Native Method)" :
               (fileName != null && lineNumber >= 0 ?
                fileName + ":" + lineNumber + ")" :
                 (fileName != null ?  ""+fileName+")" : "Unknown Source)")));
+
+        if (contScopeName != null && isContinuationEntry()) {
+            s = s + " " + contScopeName;
+        }
+
+        return s;
+    }
+
+    private boolean isContinuationEntry() {
+        return declaringClass.equals(Continuation.class.getName()) && methodName.equals("enter");
     }
 
     /**
@@ -398,7 +409,8 @@
             e.declaringClass.equals(declaringClass) &&
             e.lineNumber == lineNumber &&
             Objects.equals(methodName, e.methodName) &&
-            Objects.equals(fileName, e.fileName);
+            Objects.equals(fileName, e.fileName) &&
+            Objects.equals(contScopeName, e.contScopeName);
     }
 
     /**
@@ -410,6 +422,7 @@
         result = 31*result + Objects.hashCode(moduleName);
         result = 31*result + Objects.hashCode(moduleVersion);
         result = 31*result + Objects.hashCode(fileName);
+        result = 31*result + Objects.hashCode(contScopeName);
         result = 31*result + lineNumber;
         return result;
     }
--- a/src/java.base/share/classes/java/lang/StackWalker.java	Fri Jan 04 17:53:42 2019 +0000
+++ b/src/java.base/share/classes/java/lang/StackWalker.java	Fri Jan 04 17:54:48 2019 +0000
@@ -225,6 +225,16 @@
         public boolean isNativeMethod();
 
         /**
+         * Returns the name of the {@link ContinuationScope} of the continuation 
+         * (if any) in which this frame exists.
+         * 
+         * @return the name of the {@link ContinuationScope} of the continuation 
+         *         in which this frame exists or {@code null} if this frame is 
+         *         not in a continuation.
+         */
+        public String getContinuationScopeName();
+
+        /**
          * Gets a {@code StackTraceElement} for this stack frame.
          *
          * @return {@code StackTraceElement} for this stack frame.
@@ -677,6 +687,9 @@
             throw new UnsupportedOperationException("This stack walker " +
                     "does not have RETAIN_CLASS_REFERENCE access");
         }
+        if (continuation != null) {
+            throw new UnsupportedOperationException("This stack walker walks a continuation");
+        }
 
         return StackStreamFactory.makeCallerFinder(this).findCaller();
     }
--- a/src/java.base/share/classes/java/lang/invoke/MethodHandleImpl.java	Fri Jan 04 17:53:42 2019 +0000
+++ b/src/java.base/share/classes/java/lang/invoke/MethodHandleImpl.java	Fri Jan 04 17:54:48 2019 +0000
@@ -40,6 +40,7 @@
 import sun.invoke.util.Wrapper;
 
 import java.lang.reflect.Array;
+import java.lang.reflect.Method;
 import java.util.Arrays;
 import java.util.Collections;
 import java.util.HashMap;
@@ -1732,6 +1733,11 @@
             }
 
             @Override
+            public Object newMemberName(Method method) {
+                return new MemberName(method);
+            }
+
+            @Override
             public String getName(Object mname) {
                 MemberName memberName = (MemberName)mname;
                 return memberName.getName();
--- a/src/java.base/share/classes/jdk/internal/access/JavaLangInvokeAccess.java	Fri Jan 04 17:53:42 2019 +0000
+++ b/src/java.base/share/classes/jdk/internal/access/JavaLangInvokeAccess.java	Fri Jan 04 17:54:48 2019 +0000
@@ -26,6 +26,7 @@
 package jdk.internal.access;
 
 import java.lang.invoke.MethodType;
+import java.lang.reflect.Method;
 import java.util.Map;
 
 public interface JavaLangInvokeAccess {
@@ -35,6 +36,11 @@
     Object newMemberName();
 
     /**
+     * Create a new MemberName instance. Used by {@code StackFrameInfo}.
+     */
+    Object newMemberName(Method method);
+
+    /**
      * Returns the name for the given MemberName. Used by {@code StackFrameInfo}.
      */
     String getName(Object mname);
--- a/src/java.base/share/native/libjava/StackStreamFactory.c	Fri Jan 04 17:53:42 2019 +0000
+++ b/src/java.base/share/native/libjava/StackStreamFactory.c	Fri Jan 04 17:54:48 2019 +0000
@@ -75,3 +75,14 @@
     return JVM_MoreStackWalk(env, stackstream, mode, anchor, batchSize, 
                              startIndex, frames);
 }
+
+/*
+ * Class:     java_lang_StackStreamFactory_AbstractStackWalker
+ * Method:    setContinuation
+ * Signature: (J[Ljava/lang/Object;Ljava/lang/Continuation;)V
+ */
+JNIEXPORT void JNICALL Java_java_lang_StackStreamFactory_00024AbstractStackWalker_setContinuation
+  (JNIEnv *env, jobject stackstream, jlong anchor, jobjectArray frames, jobject cont)
+{
+  JVM_SetStackWalkContinuation(env, stackstream, anchor, frames, cont);
+}
--- a/test/jdk/java/lang/Continuation/Basic.java	Fri Jan 04 17:53:42 2019 +0000
+++ b/test/jdk/java/lang/Continuation/Basic.java	Fri Jan 04 17:54:48 2019 +0000
@@ -98,7 +98,7 @@
         walker = StackWalker.getInstance(FOO);
         frames = walker.walk(fs -> fs.map(StackWalker.StackFrame::getMethodName).collect(Collectors.toList()));
 
-        assertEquals(frames, Arrays.asList("bar", "foo", "lambda$test1$0", "enter0"));
+        assertEquals(frames, Arrays.asList("bar", "foo", "lambda$test1$0", "enter0", "enter"));
 
         long r = b+1;
         return "" + r;
--- a/test/jdk/java/lang/Continuation/Scoped.java	Fri Jan 04 17:53:42 2019 +0000
+++ b/test/jdk/java/lang/Continuation/Scoped.java	Fri Jan 04 17:54:48 2019 +0000
@@ -45,10 +45,10 @@
 
 @Test
 public class Scoped {
-        static final ContinuationScope A = new ContinuationScope() {};
-        static final ContinuationScope B = new ContinuationScope() {};
-        static final ContinuationScope C = new ContinuationScope() {};
-        static final ContinuationScope K = new ContinuationScope() {};
+    static final ContinuationScope A = new ContinuationScope("A") {};
+    static final ContinuationScope B = new ContinuationScope("B") {};
+    static final ContinuationScope C = new ContinuationScope("C") {};
+    static final ContinuationScope K = new ContinuationScope("K") {};
 
     public void test1() {
                 final AtomicInteger res = new AtomicInteger(0);
@@ -62,35 +62,38 @@
                         res.set((int)r);        
                 });
 
+                List<String> frames;
+                frames = cont.stackWalker().walk(fs -> fs.map(StackWalker.StackFrame::getMethodName).collect(Collectors.toList()));
+                // System.out.println("No scope (before start): " + frames);
+                assertEquals(frames, List.of());
+
                 while (!cont.isDone()) {
                         cont.run();
                         System.gc();
 
-                        List<String> frames;
-
                         frames = cont.stackWalker().walk(fs -> fs.map(StackWalker.StackFrame::getMethodName).collect(Collectors.toList()));
-                        System.out.println("No scope: " + frames);
-                        // assertEquals(frames, Arrays.asList("yield0", "yield", "bar", "foo", "lambda$test1$0", "enter0"));
+                        // System.out.println("No scope: " + frames);
+                        assertEquals(frames, cont.isDone() ? List.of() : Arrays.asList("yield0", "yield", "lambda$bar$14", "enter0", "enter", "run", "bar", "lambda$foo$8", "enter0", "enter", "run", "foo", "lambda$test1$0", "enter0", "enter"));
 
                         frames = cont.stackWalker(EnumSet.noneOf(StackWalker.Option.class), A).walk(fs -> fs.map(StackWalker.StackFrame::getMethodName).collect(Collectors.toList()));
-                        System.out.println("A: " + frames);
-                        // assertEquals(frames, Arrays.asList("yield0", "yield", "bar", "foo", "lambda$test1$0", "enter0"));
+                        // System.out.println("A: " + frames);
+                        assertEquals(frames, cont.isDone() ? List.of() : Arrays.asList("yield0", "yield", "lambda$bar$14", "enter0", "enter", "run", "bar", "lambda$foo$8", "enter0", "enter", "run", "foo", "lambda$test1$0", "enter0", "enter"));
 
                         frames = cont.stackWalker(EnumSet.noneOf(StackWalker.Option.class), B).walk(fs -> fs.map(StackWalker.StackFrame::getMethodName).collect(Collectors.toList()));
-                        System.out.println("B: " + frames);
-                        // assertEquals(frames, Arrays.asList("yield0", "yield", "bar", "foo", "lambda$test1$0", "enter0"));
+                        // System.out.println("B: " + frames);
+                        assertEquals(frames, cont.isDone() ? List.of() : Arrays.asList("yield0", "yield", "lambda$bar$14", "enter0", "enter", "run", "bar", "lambda$foo$8", "enter0", "enter"));
 
                         frames = cont.stackWalker(EnumSet.noneOf(StackWalker.Option.class), C).walk(fs -> fs.map(StackWalker.StackFrame::getMethodName).collect(Collectors.toList()));
-                        System.out.println("C: " + frames);
-                        // assertEquals(frames, Arrays.asList("yield0", "yield"));
+                        // System.out.println("C: " + frames);
+                        assertEquals(frames, cont.isDone() ? List.of() : Arrays.asList("yield0", "yield", "lambda$bar$14", "enter0", "enter"));
 
                         frames = cont.stackWalker(EnumSet.noneOf(StackWalker.Option.class), K).walk(fs -> fs.map(StackWalker.StackFrame::getMethodName).collect(Collectors.toList()));
-                        System.out.println("K: " + frames);
-                        // assertEquals(frames, Arrays.asList("yield0", "yield"));
+                        // System.out.println("K: " + frames);
+                        assertEquals(frames, cont.isDone() ? List.of() : Arrays.asList("yield0", "yield", "lambda$bar$14", "enter0", "enter", "run", "bar", "lambda$foo$8", "enter0", "enter", "run", "foo", "lambda$test1$0", "enter0", "enter"));
 
                         frames = cont.stackWalker(EnumSet.noneOf(StackWalker.Option.class), null).walk(fs -> fs.map(StackWalker.StackFrame::getMethodName).collect(Collectors.toList()));
-                        System.out.println("null: " + frames);
-                        // assertEquals(frames, Arrays.asList("yield0", "yield"));
+                        // System.out.println("null: " + frames);
+                        assertEquals(frames, cont.isDone() ? List.of() : Arrays.asList("yield0", "yield", "lambda$bar$14", "enter0", "enter", "run", "bar", "lambda$foo$8", "enter0", "enter", "run", "foo", "lambda$test1$0", "enter0", "enter"));
                 }
                 assertEquals(res.get(), 2);
         }
@@ -113,30 +116,25 @@
                 Continuation cont = new Continuation(C, ()-> {
                         Continuation.yield(A);
 
-                        StackWalker walker = StackWalker.getInstance();
-                        List<String> frames = walker.walk(fs -> fs.map(StackWalker.StackFrame::getMethodName).collect(Collectors.toList()));
+                        List<String> frames = StackWalker.getInstance().walk(fs -> fs.map(StackWalker.StackFrame::getMethodName).collect(Collectors.toList()));
                 
-                        assertEquals(frames.subList(0, 15), Arrays.asList("lambda$bar$6", "enter0", "enter", "run", "bar", "lambda$foo$1", "enter0", "enter", "run", "foo", "lambda$test1$0", "enter0", "enter", "run", "test1"));
+                        assertEquals(frames.subList(0, 15), Arrays.asList("lambda$bar$14", "enter0", "enter", "run", "bar", "lambda$foo$8", "enter0", "enter", "run", "foo", "lambda$test1$0", "enter0", "enter", "run", "test1"));
                 
-                        walker = StackWalker.getInstance(C);
-                        frames = walker.walk(fs -> fs.map(StackWalker.StackFrame::getMethodName).collect(Collectors.toList()));
+                        frames = StackWalker.getInstance(C).walk(fs -> fs.map(StackWalker.StackFrame::getMethodName).collect(Collectors.toList()));
                 
-                        assertEquals(frames, Arrays.asList("lambda$bar$6", "enter0"));
+                        assertEquals(frames, Arrays.asList("lambda$bar$14", "enter0", "enter"));
 
-                        walker = StackWalker.getInstance(B);
-                        frames = walker.walk(fs -> fs.map(StackWalker.StackFrame::getMethodName).collect(Collectors.toList()));
+                        frames = StackWalker.getInstance(B).walk(fs -> fs.map(StackWalker.StackFrame::getMethodName).collect(Collectors.toList()));
                 
-                        assertEquals(frames, Arrays.asList("lambda$bar$6", "enter0", "enter", "run", "bar", "lambda$foo$1", "enter0"));
+                        assertEquals(frames, Arrays.asList("lambda$bar$14", "enter0", "enter", "run", "bar", "lambda$foo$8", "enter0", "enter"));
 
-                        walker = StackWalker.getInstance(A);
-                        frames = walker.walk(fs -> fs.map(StackWalker.StackFrame::getMethodName).collect(Collectors.toList()));
+                        frames = StackWalker.getInstance(A).walk(fs -> fs.map(StackWalker.StackFrame::getMethodName).collect(Collectors.toList()));
                 
-                        assertEquals(frames, Arrays.asList("lambda$bar$6", "enter0", "enter", "run", "bar", "lambda$foo$1", "enter0", "enter", "run", "foo", "lambda$test1$0", "enter0"));
+                        assertEquals(frames, Arrays.asList("lambda$bar$14", "enter0", "enter", "run", "bar", "lambda$foo$8", "enter0", "enter", "run", "foo", "lambda$test1$0", "enter0", "enter"));
 
-                        walker = StackWalker.getInstance(K);
-                        frames = walker.walk(fs -> fs.map(StackWalker.StackFrame::getMethodName).collect(Collectors.toList()));
+                        frames = StackWalker.getInstance(K).walk(fs -> fs.map(StackWalker.StackFrame::getMethodName).collect(Collectors.toList()));
                 
-                        assertEquals(frames, Arrays.asList("lambda$bar$6", "enter0", "enter", "run", "bar", "lambda$foo$1", "enter0", "enter", "run", "foo", "lambda$test1$0", "enter0"));
+                        assertEquals(frames.subList(0, 15), Arrays.asList("lambda$bar$14", "enter0", "enter", "run", "bar", "lambda$foo$8", "enter0", "enter", "run", "foo", "lambda$test1$0", "enter0", "enter", "run", "test1"));
 
                         long r = b+1;
                 });