Merge JDK-8200758-branch
authorherrick
Mon, 17 Jun 2019 15:18:52 -0400
branchJDK-8200758-branch
changeset 57412 02034583f4dc
parent 57411 4a80a72a891d (current diff)
parent 55398 e53ec3b362f4 (diff)
child 57413 45c74e654794
Merge
--- a/src/hotspot/cpu/aarch64/aarch64.ad	Mon Jun 17 14:57:23 2019 -0400
+++ b/src/hotspot/cpu/aarch64/aarch64.ad	Mon Jun 17 15:18:52 2019 -0400
@@ -14255,7 +14255,7 @@
   format %{ "fcmps $src1, 0.0" %}
 
   ins_encode %{
-    __ fcmps(as_FloatRegister($src1$$reg), 0.0D);
+    __ fcmps(as_FloatRegister($src1$$reg), 0.0);
   %}
 
   ins_pipe(pipe_class_compare);
@@ -14284,7 +14284,7 @@
   format %{ "fcmpd $src1, 0.0" %}
 
   ins_encode %{
-    __ fcmpd(as_FloatRegister($src1$$reg), 0.0D);
+    __ fcmpd(as_FloatRegister($src1$$reg), 0.0);
   %}
 
   ins_pipe(pipe_class_compare);
@@ -14360,7 +14360,7 @@
     Label done;
     FloatRegister s1 = as_FloatRegister($src1$$reg);
     Register d = as_Register($dst$$reg);
-    __ fcmps(s1, 0.0D);
+    __ fcmps(s1, 0.0);
     // installs 0 if EQ else -1
     __ csinvw(d, zr, zr, Assembler::EQ);
     // keeps -1 if less or unordered else installs 1
@@ -14387,7 +14387,7 @@
     Label done;
     FloatRegister s1 = as_FloatRegister($src1$$reg);
     Register d = as_Register($dst$$reg);
-    __ fcmpd(s1, 0.0D);
+    __ fcmpd(s1, 0.0);
     // installs 0 if EQ else -1
     __ csinvw(d, zr, zr, Assembler::EQ);
     // keeps -1 if less or unordered else installs 1
--- a/src/hotspot/cpu/aarch64/assembler_aarch64.hpp	Mon Jun 17 14:57:23 2019 -0400
+++ b/src/hotspot/cpu/aarch64/assembler_aarch64.hpp	Mon Jun 17 15:18:52 2019 -0400
@@ -276,7 +276,7 @@
   unsigned get(int msb = 31, int lsb = 0) {
     int nbits = msb - lsb + 1;
     unsigned mask = ((1U << nbits) - 1) << lsb;
-    assert_cond(bits & mask == mask);
+    assert_cond((bits & mask) == mask);
     return (insn & mask) >> lsb;
   }
 
@@ -2644,7 +2644,7 @@
   // RBIT only allows T8B and T16B but encodes them oddly.  Argh...
   void rbit(FloatRegister Vd, SIMD_Arrangement T, FloatRegister Vn) {
     assert((ASSERTION), MSG);
-    _rbit(Vd, SIMD_Arrangement(T & 1 | 0b010), Vn);
+    _rbit(Vd, SIMD_Arrangement((T & 1) | 0b010), Vn);
   }
 #undef ASSERTION
 
--- a/src/hotspot/cpu/aarch64/c1_LIRAssembler_aarch64.cpp	Mon Jun 17 14:57:23 2019 -0400
+++ b/src/hotspot/cpu/aarch64/c1_LIRAssembler_aarch64.cpp	Mon Jun 17 15:18:52 2019 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2000, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2019, Oracle and/or its affiliates. All rights reserved.
  * Copyright (c) 2014, Red Hat Inc. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
@@ -1078,8 +1078,8 @@
       // Assembler::EQ does not permit unordered branches, so we add
       // another branch here.  Likewise, Assembler::NE does not permit
       // ordered branches.
-      if (is_unordered && op->cond() == lir_cond_equal
-          || !is_unordered && op->cond() == lir_cond_notEqual)
+      if ((is_unordered && op->cond() == lir_cond_equal)
+          || (!is_unordered && op->cond() == lir_cond_notEqual))
         __ br(Assembler::VS, *(op->ublock()->label()));
       switch(op->cond()) {
       case lir_cond_equal:        acond = Assembler::EQ; break;
@@ -1789,18 +1789,22 @@
     switch (code) {
     case lir_add: __ fadds (dest->as_float_reg(), left->as_float_reg(), right->as_float_reg()); break;
     case lir_sub: __ fsubs (dest->as_float_reg(), left->as_float_reg(), right->as_float_reg()); break;
+    case lir_mul_strictfp: // fall through
     case lir_mul: __ fmuls (dest->as_float_reg(), left->as_float_reg(), right->as_float_reg()); break;
+    case lir_div_strictfp: // fall through
     case lir_div: __ fdivs (dest->as_float_reg(), left->as_float_reg(), right->as_float_reg()); break;
     default:
       ShouldNotReachHere();
     }
   } else if (left->is_double_fpu()) {
     if (right->is_double_fpu()) {
-      // cpu register - cpu register
+      // fpu register - fpu register
       switch (code) {
       case lir_add: __ faddd (dest->as_double_reg(), left->as_double_reg(), right->as_double_reg()); break;
       case lir_sub: __ fsubd (dest->as_double_reg(), left->as_double_reg(), right->as_double_reg()); break;
+      case lir_mul_strictfp: // fall through
       case lir_mul: __ fmuld (dest->as_double_reg(), left->as_double_reg(), right->as_double_reg()); break;
+      case lir_div_strictfp: // fall through
       case lir_div: __ fdivd (dest->as_double_reg(), left->as_double_reg(), right->as_double_reg()); break;
       default:
         ShouldNotReachHere();
--- a/src/hotspot/cpu/aarch64/c1_LIRGenerator_aarch64.cpp	Mon Jun 17 14:57:23 2019 -0400
+++ b/src/hotspot/cpu/aarch64/c1_LIRGenerator_aarch64.cpp	Mon Jun 17 15:18:52 2019 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2005, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2019, Oracle and/or its affiliates. All rights reserved.
  * Copyright (c) 2014, Red Hat Inc. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
@@ -426,7 +426,7 @@
     tmp = new_register(T_DOUBLE);
   }
 
-  arithmetic_op_fpu(x->op(), reg, left.result(), right.result(), NULL);
+  arithmetic_op_fpu(x->op(), reg, left.result(), right.result(), x->is_strictfp());
 
   set_result(x, round_item(reg));
 }
--- a/src/hotspot/cpu/aarch64/frame_aarch64.cpp	Mon Jun 17 14:57:23 2019 -0400
+++ b/src/hotspot/cpu/aarch64/frame_aarch64.cpp	Mon Jun 17 15:18:52 2019 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2019, Oracle and/or its affiliates. All rights reserved.
  * Copyright (c) 2014, Red Hat Inc. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
@@ -768,11 +768,13 @@
 
 extern "C" void pf(unsigned long sp, unsigned long fp, unsigned long pc,
                    unsigned long bcx, unsigned long thread) {
-  RegisterMap map((JavaThread*)thread, false);
   if (!reg_map) {
-    reg_map = (RegisterMap*)os::malloc(sizeof map, mtNone);
+    reg_map = NEW_C_HEAP_OBJ(RegisterMap, mtNone);
+    ::new (reg_map) RegisterMap((JavaThread*)thread, false);
+  } else {
+    *reg_map = RegisterMap((JavaThread*)thread, false);
   }
-  memcpy(reg_map, &map, sizeof map);
+
   {
     CodeBlob *cb = CodeCache::find_blob((address)pc);
     if (cb && cb->frame_size())
--- a/src/hotspot/cpu/aarch64/interp_masm_aarch64.hpp	Mon Jun 17 14:57:23 2019 -0400
+++ b/src/hotspot/cpu/aarch64/interp_masm_aarch64.hpp	Mon Jun 17 15:18:52 2019 -0400
@@ -38,8 +38,6 @@
  protected:
 
  protected:
-  using MacroAssembler::call_VM_leaf_base;
-
   // Interpreter specific version of call_VM_base
   using MacroAssembler::call_VM_leaf_base;
 
--- a/src/hotspot/cpu/aarch64/macroAssembler_aarch64.cpp	Mon Jun 17 14:57:23 2019 -0400
+++ b/src/hotspot/cpu/aarch64/macroAssembler_aarch64.cpp	Mon Jun 17 15:18:52 2019 -0400
@@ -2681,7 +2681,7 @@
   if ((offset & (size-1)) && offset >= (1<<8)) {
     add(tmp, base, offset & ((1<<12)-1));
     base = tmp;
-    offset &= -1<<12;
+    offset &= -1u<<12;
   }
 
   if (offset >= (1<<12) * size) {
--- a/src/hotspot/cpu/aarch64/macroAssembler_aarch64_log.cpp	Mon Jun 17 14:57:23 2019 -0400
+++ b/src/hotspot/cpu/aarch64/macroAssembler_aarch64_log.cpp	Mon Jun 17 15:18:52 2019 -0400
@@ -286,7 +286,7 @@
     frecpe(vtmp5, vtmp5, S);                   // vtmp5 ~= 1/vtmp5
     lsr(tmp2, rscratch1, 48);
     movz(tmp4, 0x77f0, 48);
-    fmovd(vtmp4, 1.0d);
+    fmovd(vtmp4, 1.0);
     movz(tmp1, INF_OR_NAN_PREFIX, 48);
     bfm(tmp4, rscratch1, 0, 51);               // tmp4 = 0x77F0 << 48 | mantissa(X)
     // vtmp1 = AS_DOUBLE_BITS(0x77F0 << 48 | mantissa(X)) == mx
@@ -358,7 +358,7 @@
       br(GE, DONE);
       cmp(rscratch1, tmp2);
       br(NE, CHECKED_CORNER_CASES);
-      fmovd(v0, 0.0d);
+      fmovd(v0, 0.0);
   }
   bind(DONE);
     ret(lr);
--- a/src/hotspot/cpu/aarch64/macroAssembler_aarch64_trig.cpp	Mon Jun 17 14:57:23 2019 -0400
+++ b/src/hotspot/cpu/aarch64/macroAssembler_aarch64_trig.cpp	Mon Jun 17 15:18:52 2019 -0400
@@ -381,11 +381,11 @@
       }
 
       block_comment("nx calculation with unrolled while(tx[nx-1]==zeroA) nx--;"); {
-        fcmpd(v26, 0.0d);                          // if NE then jx == 2. else it's 1 or 0
+        fcmpd(v26, 0.0);                           // if NE then jx == 2. else it's 1 or 0
         add(iqBase, sp, 480);                      // base of iq[]
         fmuld(v3, v26, v10);
         br(NE, NX_SET);
-        fcmpd(v7, 0.0d);                           // v7 == 0 => jx = 0. Else jx = 1
+        fcmpd(v7, 0.0);                            // v7 == 0 => jx = 0. Else jx = 1
         csetw(jx, NE);
       }
     bind(NX_SET);
@@ -696,7 +696,7 @@
     cmpw(jv, zr);
     addw(tmp4, jx, 4); // tmp4 = m = jx + jk = jx + 4. jx is in {0,1,2} so m is in [4,5,6]
     cselw(jv, jv, zr, GE);
-    fmovd(v26, 0.0d);
+    fmovd(v26, 0.0);
     addw(tmp5, jv, 1);                    // jv+1
     subsw(j, jv, jx);
     add(qBase, sp, 320);                  // base of q[]
@@ -819,8 +819,8 @@
   movw(jz, 4);
   fmovd(v17, i);                               // v17 = twon24
   fmovd(v30, tmp5);                            // 2^q0
-  fmovd(v21, 0.125d);
-  fmovd(v20, 8.0d);
+  fmovd(v21, 0.125);
+  fmovd(v20, 8.0);
   fmovd(v22, tmp4);                            // 2^-q0
 
   block_comment("recompute loop"); {
@@ -877,7 +877,7 @@
           lsr(ih, tmp2, 23);                               // ih = iq[z-1] >> 23
           b(Q0_ZERO_CMP_DONE);
         bind(Q0_ZERO_CMP_LT);
-          fmovd(v4, 0.5d);
+          fmovd(v4, 0.5);
           fcmpd(v18, v4);
           cselw(ih, zr, ih, LT);                           // if (z<0.5) ih = 0
       }
@@ -924,7 +924,7 @@
         br(NE, IH_HANDLED);
 
         block_comment("if(ih==2) {"); {
-          fmovd(v25, 1.0d);
+          fmovd(v25, 1.0);
           fsubd(v18, v25, v18);                            // z = one - z;
           cbzw(rscratch2, IH_HANDLED);
           fsubd(v18, v18, v30);                            // z -= scalbnA(one,q0);
@@ -932,7 +932,7 @@
     }
     bind(IH_HANDLED);
       // check if recomputation is needed
-      fcmpd(v18, 0.0d);
+      fcmpd(v18, 0.0);
       br(NE, RECOMP_CHECK_DONE_NOT_ZERO);
 
       block_comment("if(z==zeroB) {"); {
@@ -994,7 +994,7 @@
     }
     bind(RECOMP_CHECK_DONE);
       // chop off zero terms
-      fcmpd(v18, 0.0d);
+      fcmpd(v18, 0.0);
       br(EQ, Z_IS_ZERO);
 
       block_comment("else block of if(z==0.0) {"); {
@@ -1053,7 +1053,7 @@
           movw(tmp2, zr); // tmp2 will keep jz - i == 0 at start
         bind(COMP_FOR);
           // for(fw=0.0,k=0;k<=jp&&k<=jz-i;k++) fw += PIo2[k]*q[i+k];
-          fmovd(v30, 0.0d);
+          fmovd(v30, 0.0);
           add(tmp5, qBase, i, LSL, 3); // address of q[i+k] for k==0
           movw(tmp3, 4);
           movw(tmp4, zr);              // used as k
@@ -1081,7 +1081,7 @@
         // remember prec == 2
 
         block_comment("for (i=jz;i>=0;i--) fw += fq[i];"); {
-            fmovd(v4, 0.0d);
+            fmovd(v4, 0.0);
             mov(i, jz);
           bind(FW_FOR1);
             ldrd(v1, Address(rscratch2, i, Address::lsl(3)));
@@ -1319,7 +1319,7 @@
     ld1(C1, C2, C3, C4, T1D, Address(rscratch2)); // load C1..C3\4
     block_comment("calculate r = z*(C1+z*(C2+z*(C3+z*(C4+z*(C5+z*C6)))))"); {
       fmaddd(r, z, C6, C5);
-      fmovd(half, 0.5d);
+      fmovd(half, 0.5);
       fmaddd(r, z, r, C4);
       fmuld(y, x, y);
       fmaddd(r, z, r, C3);
@@ -1329,7 +1329,7 @@
       fmaddd(r, z, r, C1);                        // r = C1+z(C2+z(C4+z(C5+z*C6)))
     }
     // need to multiply r by z to have "final" r value
-    fmovd(one, 1.0d);
+    fmovd(one, 1.0);
     cmp(ix, rscratch1);
     br(GT, IX_IS_LARGE);
     block_comment("if(ix < 0x3FD33333) return one - (0.5*z - (z*r - x*y))"); {
@@ -1352,7 +1352,7 @@
       b(QX_SET);
     bind(SET_QX_CONST);
       block_comment("if(ix > 0x3fe90000) qx = 0.28125;"); {
-        fmovd(qx, 0.28125d);
+        fmovd(qx, 0.28125);
       }
     bind(QX_SET);
       fnmsub(C6, x, r, y);    // z*r - xy
@@ -1443,7 +1443,7 @@
   block_comment("kernel_sin/kernel_cos: if(ix<0x3e400000) {<fast return>}"); {
     bind(TINY_X);
       if (isCos) {
-        fmovd(v0, 1.0d);
+        fmovd(v0, 1.0);
       }
       ret(lr);
   }
--- a/src/hotspot/cpu/aarch64/vm_version_aarch64.cpp	Mon Jun 17 14:57:23 2019 -0400
+++ b/src/hotspot/cpu/aarch64/vm_version_aarch64.cpp	Mon Jun 17 15:18:52 2019 -0400
@@ -177,7 +177,7 @@
   if (FILE *f = fopen("/proc/cpuinfo", "r")) {
     char buf[128], *p;
     while (fgets(buf, sizeof (buf), f) != NULL) {
-      if (p = strchr(buf, ':')) {
+      if ((p = strchr(buf, ':')) != NULL) {
         long v = strtol(p+1, NULL, 0);
         if (strncmp(buf, "CPU implementer", sizeof "CPU implementer" - 1) == 0) {
           _cpu = v;
--- a/src/hotspot/os_cpu/linux_aarch64/atomic_linux_aarch64.hpp	Mon Jun 17 14:57:23 2019 -0400
+++ b/src/hotspot/os_cpu/linux_aarch64/atomic_linux_aarch64.hpp	Mon Jun 17 15:18:52 2019 -0400
@@ -40,7 +40,9 @@
 {
   template<typename I, typename D>
   D add_and_fetch(I add_value, D volatile* dest, atomic_memory_order order) const {
-    return __sync_add_and_fetch(dest, add_value);
+    D res = __atomic_add_fetch(dest, add_value, __ATOMIC_RELEASE);
+    FULL_MEM_BARRIER;
+    return res;
   }
 };
 
--- a/src/hotspot/os_cpu/linux_aarch64/copy_linux_aarch64.s	Mon Jun 17 14:57:23 2019 -0400
+++ b/src/hotspot/os_cpu/linux_aarch64/copy_linux_aarch64.s	Mon Jun 17 15:18:52 2019 -0400
@@ -159,7 +159,7 @@
         blo     bwd_copy_drain
 
 bwd_copy_again:
-        prfm    pldl1keep, [s, #-256]
+        prfum   pldl1keep, [s, #-256]
         stp     t0, t1, [d, #-16]
         ldp     t0, t1, [s, #-16]
         stp     t2, t3, [d, #-32]
--- a/src/hotspot/os_cpu/linux_aarch64/os_linux_aarch64.cpp	Mon Jun 17 14:57:23 2019 -0400
+++ b/src/hotspot/os_cpu/linux_aarch64/os_linux_aarch64.cpp	Mon Jun 17 15:18:52 2019 -0400
@@ -83,19 +83,13 @@
 #define REG_SP REG_RSP
 #define REG_PC REG_RIP
 #define REG_FP REG_RBP
-#define SPELL_REG_SP "rsp"
-#define SPELL_REG_FP "rbp"
 #else
 #define REG_FP 29
 #define REG_LR 30
-
-#define SPELL_REG_SP "sp"
-#define SPELL_REG_FP "x29"
 #endif
 
-address os::current_stack_pointer() {
-  register void *esp __asm__ (SPELL_REG_SP);
-  return (address) esp;
+NOINLINE address os::current_stack_pointer() {
+  return (address)__builtin_frame_address(0);
 }
 
 char* os::non_memory_address_word() {
@@ -230,23 +224,8 @@
 #endif
 }
 
-intptr_t* _get_previous_fp() {
-  register intptr_t **fp __asm__ (SPELL_REG_FP);
-
-  // fp is for this frame (_get_previous_fp). We want the fp for the
-  // caller of os::current_frame*(), so go up two frames. However, for
-  // optimized builds, _get_previous_fp() will be inlined, so only go
-  // up 1 frame in that case.
-  #ifdef _NMT_NOINLINE_
-    return **(intptr_t***)fp;
-  #else
-    return *fp;
-  #endif
-}
-
-
-frame os::current_frame() {
-  intptr_t* fp = _get_previous_fp();
+NOINLINE frame os::current_frame() {
+  intptr_t *fp = *(intptr_t **)__builtin_frame_address(0);
   frame myframe((intptr_t*)os::current_stack_pointer(),
                 (intptr_t*)fp,
                 CAST_FROM_FN_PTR(address, os::current_frame));
@@ -259,12 +238,6 @@
 }
 
 // Utility functions
-
-// From IA32 System Programming Guide
-enum {
-  trap_page_fault = 0xE
-};
-
 #ifdef BUILTIN_SIM
 extern "C" void Fetch32PFI () ;
 extern "C" void Fetch32Resume () ;
@@ -667,42 +640,42 @@
     return 0;
   }
 
-  void _Copy_conjoint_jshorts_atomic(jshort* from, jshort* to, size_t count) {
+  void _Copy_conjoint_jshorts_atomic(const jshort* from, jshort* to, size_t count) {
     if (from > to) {
-      jshort *end = from + count;
+      const jshort *end = from + count;
       while (from < end)
         *(to++) = *(from++);
     }
     else if (from < to) {
-      jshort *end = from;
+      const jshort *end = from;
       from += count - 1;
       to   += count - 1;
       while (from >= end)
         *(to--) = *(from--);
     }
   }
-  void _Copy_conjoint_jints_atomic(jint* from, jint* to, size_t count) {
+  void _Copy_conjoint_jints_atomic(const jint* from, jint* to, size_t count) {
     if (from > to) {
-      jint *end = from + count;
+      const jint *end = from + count;
       while (from < end)
         *(to++) = *(from++);
     }
     else if (from < to) {
-      jint *end = from;
+      const jint *end = from;
       from += count - 1;
       to   += count - 1;
       while (from >= end)
         *(to--) = *(from--);
     }
   }
-  void _Copy_conjoint_jlongs_atomic(jlong* from, jlong* to, size_t count) {
+  void _Copy_conjoint_jlongs_atomic(const jlong* from, jlong* to, size_t count) {
     if (from > to) {
-      jlong *end = from + count;
+      const jlong *end = from + count;
       while (from < end)
         os::atomic_copy64(from++, to++);
     }
     else if (from < to) {
-      jlong *end = from;
+      const jlong *end = from;
       from += count - 1;
       to   += count - 1;
       while (from >= end)
@@ -710,22 +683,22 @@
     }
   }
 
-  void _Copy_arrayof_conjoint_bytes(HeapWord* from,
+  void _Copy_arrayof_conjoint_bytes(const HeapWord* from,
                                     HeapWord* to,
                                     size_t    count) {
     memmove(to, from, count);
   }
-  void _Copy_arrayof_conjoint_jshorts(HeapWord* from,
+  void _Copy_arrayof_conjoint_jshorts(const HeapWord* from,
                                       HeapWord* to,
                                       size_t    count) {
     memmove(to, from, count * 2);
   }
-  void _Copy_arrayof_conjoint_jints(HeapWord* from,
+  void _Copy_arrayof_conjoint_jints(const HeapWord* from,
                                     HeapWord* to,
                                     size_t    count) {
     memmove(to, from, count * 4);
   }
-  void _Copy_arrayof_conjoint_jlongs(HeapWord* from,
+  void _Copy_arrayof_conjoint_jlongs(const HeapWord* from,
                                      HeapWord* to,
                                      size_t    count) {
     memmove(to, from, count * 8);
--- a/src/jdk.jshell/share/classes/jdk/jshell/Corraller.java	Mon Jun 17 14:57:23 2019 -0400
+++ b/src/jdk.jshell/share/classes/jdk/jshell/Corraller.java	Mon Jun 17 15:18:52 2019 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2016, 2019, Oracle and/or its affiliates. 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
@@ -25,132 +25,226 @@
 
 package jdk.jshell;
 
-import java.io.IOException;
-import java.io.StringWriter;
 import com.sun.source.tree.ClassTree;
 import com.sun.source.tree.MethodTree;
 import com.sun.source.tree.Tree;
-import com.sun.tools.javac.code.Flags;
+import com.sun.source.tree.Tree.Kind;
 import com.sun.tools.javac.tree.JCTree;
 import com.sun.tools.javac.tree.JCTree.JCBlock;
 import com.sun.tools.javac.tree.JCTree.JCClassDecl;
-import com.sun.tools.javac.tree.JCTree.JCExpression;
 import com.sun.tools.javac.tree.JCTree.JCMethodDecl;
-import com.sun.tools.javac.tree.JCTree.JCNewClass;
-import com.sun.tools.javac.tree.JCTree.JCStatement;
 import com.sun.tools.javac.tree.JCTree.JCVariableDecl;
-import com.sun.tools.javac.tree.Pretty;
-import com.sun.tools.javac.tree.TreeMaker;
-import com.sun.tools.javac.util.Context;
+import com.sun.tools.javac.tree.JCTree.Visitor;
 import com.sun.tools.javac.util.List;
 import com.sun.tools.javac.util.ListBuffer;
-import com.sun.tools.javac.util.Names;
+import static com.sun.tools.javac.code.Flags.FINAL;
+import static com.sun.tools.javac.code.Flags.PUBLIC;
 import static com.sun.tools.javac.code.Flags.STATIC;
 import static com.sun.tools.javac.code.Flags.INTERFACE;
 import static com.sun.tools.javac.code.Flags.ENUM;
-import static com.sun.tools.javac.code.Flags.PUBLIC;
-import com.sun.tools.javac.util.Name;
-import jdk.jshell.spi.SPIResolutionException;
+import jdk.jshell.Wrap.CompoundWrap;
+import jdk.jshell.Wrap.Range;
+import jdk.jshell.Wrap.RangeWrap;
 
 /**
  * Produce a corralled version of the Wrap for a snippet.
- * Incoming tree is mutated.
- *
- * @author Robert Field
  */
-class Corraller extends Pretty {
+class Corraller extends Visitor {
+
+    /** Visitor result field: a Wrap
+     */
+    protected Wrap result;
+
+    private final TreeDissector dis;
+    private final String resolutionExceptionBlock;
+    private final String source;
+
+    public Corraller(TreeDissector dis, int keyIndex, String source) {
+        this.dis = dis;
+        this.resolutionExceptionBlock = "\n      { throw new jdk.jshell.spi.SPIResolutionException(" + keyIndex + "); }";
+        this.source = source;
+    }
+
+    public Wrap corralType(ClassTree tree) {
+        return corralToWrap(tree);
+    }
+
+    public Wrap corralMethod(MethodTree tree) {
+        return corralToWrap(tree);
+    }
 
-    private final StringWriter out;
-    private final int keyIndex;
-    private final TreeMaker make;
-    private final Names names;
-    private JCBlock resolutionExceptionBlock;
+    private Wrap corralToWrap(Tree tree) {
+        try {
+            JCTree jct = (JCTree) tree;
+            Wrap w = new CompoundWrap(
+                    "    public static\n    ",
+                    corral(jct));
+            debugWrap("corralToWrap SUCCESS source: %s -- wrap:\n %s\n", tree, w.wrapped());
+            return w;
+        } catch (Exception ex) {
+            debugWrap("corralToWrap FAIL: %s - %s\n", tree, ex);
+            //ex.printStackTrace(System.err);
+            return null;
+        }
+    }
 
-    public Corraller(int keyIndex, Context context) {
-        this(new StringWriter(), keyIndex, context);
+    // Corral a single node.
+//    @SuppressWarnings("unchecked")
+    private <T extends JCTree> Wrap corral(T tree) {
+        if (tree == null) {
+            return null;
+        } else {
+            tree.accept(this);
+            Wrap tmpResult = this.result;
+            this.result = null;
+            return tmpResult;
+        }
+    }
+
+    private String defaultConstructor(JCClassDecl tree) {
+        return "  public " + tree.name.toString() + "() " +
+                resolutionExceptionBlock;
     }
 
-    private Corraller(StringWriter out, int keyIndex, Context context) {
-        super(out, false);
-        this.out = out;
-        this.keyIndex = keyIndex;
-        this.make = TreeMaker.instance(context);
-        this.names = Names.instance(context);
-    }
+    /* ***************************************************************************
+     * Visitor methods
+     ****************************************************************************/
 
-    public Wrap corralType(ClassTree ct) {
-        ((JCClassDecl) ct).mods.flags |= Flags.STATIC | Flags.PUBLIC;
-        return corral(ct);
+    @Override
+    public void visitClassDef(JCClassDecl tree) {
+        boolean isEnum = (tree.mods.flags & ENUM) != 0;
+        boolean isInterface = (tree.mods.flags & INTERFACE ) != 0;
+        int classBegin = dis.getStartPosition(tree);
+        int classEnd = dis.getEndPosition(tree);
+        //debugWrap("visitClassDef: %d-%d = %s\n", classBegin, classEnd, source.substring(classBegin, classEnd));
+        ListBuffer<Object> wrappedDefs = new ListBuffer<>();
+        int bodyBegin = -1;
+        if (tree.defs != null && !tree.defs.isEmpty()) {
+            if (isEnum) {
+                // copy the enum constants verbatim
+                int enumBegin = dis.getStartPosition(tree.defs.head);
+                JCTree t = null; // null to shut-up compiler, always set because non-empty
+                List<? extends JCTree> l = tree.defs;
+                for (; l.nonEmpty(); l = l.tail) {
+                    t = l.head;
+                    if (t.getKind() == Kind.VARIABLE) {
+                        if ((((JCVariableDecl)t).mods.flags & (PUBLIC | STATIC | FINAL)) != (PUBLIC | STATIC | FINAL)) {
+                            // non-enum constant, process normally
+                            break;
+                        }
+                    } else {
+                        // non-variable, process normally
+                        break;
+                    }
+                }
+                int constEnd = l.nonEmpty()                  // end of constants
+                        ? dis.getStartPosition(l.head) - 1   // is one before next defs, if there is one
+                        : dis.getEndPosition(t);             // and otherwise end of the last constant
+                wrappedDefs.append(new RangeWrap(source, new Range(enumBegin, constEnd)));
+                // handle any other defs
+                for (; l.nonEmpty(); l = l.tail) {
+                    wrappedDefs.append("\n");
+                    t = l.head;
+                    wrappedDefs.append(corral(t));
+                }
+            } else {
+                // non-enum
+                boolean constructorSeen = false;
+                for (List<? extends JCTree> l = tree.defs; l.nonEmpty(); l = l.tail) {
+                    wrappedDefs.append("\n   ");
+                    JCTree t = l.head;
+                    switch (t.getKind()) {
+                        case METHOD:
+                            constructorSeen = constructorSeen || ((MethodTree)t).getName() == tree.name.table.names.init;
+                            break;
+                        case BLOCK:
+                            // throw exception in instance initializer too -- inline because String not Wrap
+                            wrappedDefs.append((((JCBlock)t).flags & STATIC) != 0
+                                    ? new RangeWrap(source, dis.treeToRange(t))
+                                    : resolutionExceptionBlock);
+                            continue; // already appended, skip append below
+                    }
+                    wrappedDefs.append(corral(t));
+                }
+                if (!constructorSeen && !isInterface && !isEnum) {
+                    // Generate a default constructor, since
+                    // this is a regular class and there are no constructors
+                    if (wrappedDefs.length() > 0) {
+                        wrappedDefs.append("\n ");
+                    }
+                    wrappedDefs.append(defaultConstructor(tree));
+                }
+            }
+            bodyBegin = dis.getStartPosition(tree.defs.head);
+        }
+        Object defs = wrappedDefs.length() == 1
+            ? wrappedDefs.first()
+            : new CompoundWrap(wrappedDefs.toArray());
+        if (bodyBegin < 0) {
+            int brace = source.indexOf('{', classBegin);
+            if (brace < 0 || brace >= classEnd) {
+                throw new IllegalArgumentException("No brace found: " + source.substring(classBegin, classEnd));
+            }
+            bodyBegin = brace + 1;
+        }
+        // body includes openning brace
+        result = new CompoundWrap(
+                new RangeWrap(source, new Range(classBegin, bodyBegin)),
+                defs,
+                "\n}"
+        );
     }
 
-    public Wrap corralMethod(MethodTree mt) {
-        ((JCMethodDecl) mt).mods.flags |= Flags.STATIC | Flags.PUBLIC;
-        return corral(mt);
+    // Corral the body
+    @Override
+    public void visitMethodDef(JCMethodDecl tree) {
+        int methodBegin = dis.getStartPosition(tree);
+        int methodEnd = dis.getEndPosition(tree);
+        //debugWrap("+visitMethodDef: %d-%d = %s\n", methodBegin, methodEnd,
+        //        source.substring(methodBegin, methodEnd));
+        int bodyBegin = dis.getStartPosition(tree.getBody());
+        if (bodyBegin < 0) {
+            bodyBegin = source.indexOf('{', methodBegin);
+            if (bodyBegin > methodEnd) {
+                bodyBegin = -1;
+            }
+        }
+        if (bodyBegin > 0) {
+            //debugWrap("-visitMethodDef BEGIN: %d = '%s'\n", bodyBegin,
+            //        source.substring(methodBegin, bodyBegin));
+            Range noBodyRange = new Range(methodBegin, bodyBegin);
+            result = new CompoundWrap(
+                    new RangeWrap(source, noBodyRange),
+                    resolutionExceptionBlock);
+        } else {
+            Range range = new Range(methodBegin, methodEnd);
+            result = new RangeWrap(source, range);
+        }
     }
 
-    private Wrap corral(Tree tree) {
-        try {
-            printStat((JCTree) tree);
-        } catch (IOException e) {
-            throw new AssertionError(e);
+    // Remove initializer, if present
+    @Override
+    public void visitVarDef(JCVariableDecl tree) {
+        int begin = dis.getStartPosition(tree);
+        int end = dis.getEndPosition(tree);
+        if (tree.init == null) {
+            result = new RangeWrap(source, new Range(begin, end));
+        } else {
+            int sinit = dis.getStartPosition(tree.init);
+            int eq = source.lastIndexOf('=', sinit);
+            if (eq < begin) {
+                throw new IllegalArgumentException("Equals not found before init: " + source + " @" + sinit);
+            }
+            result = new CompoundWrap(new RangeWrap(source, new Range(begin, eq - 1)), ";");
         }
-        return Wrap.simpleWrap(out.toString());
     }
 
     @Override
-    public void visitBlock(JCBlock tree) {
-        // Top-level executable blocks (usually method bodies) are corralled
-        super.visitBlock((tree.flags & STATIC) != 0
-                ? tree
-                : resolutionExceptionBlock());
-    }
-
-    @Override
-    public void visitVarDef(JCVariableDecl tree) {
-        // No field inits in corralled classes
-        tree.init = null;
-        super.visitVarDef(tree);
+    public void visitTree(JCTree tree) {
+        throw new IllegalArgumentException("Unexpected tree: " + tree);
     }
 
-    @Override
-    public void visitClassDef(JCClassDecl tree) {
-        if ((tree.mods.flags & (INTERFACE | ENUM)) == 0 &&
-                !tree.getMembers().stream()
-                .anyMatch(t -> t.getKind() == Tree.Kind.METHOD &&
-                ((MethodTree) t).getName() == tree.name.table.names.init)) {
-            // Generate a default constructor, since
-            // this is a regular class and there are no constructors
-            ListBuffer<JCTree> ndefs = new ListBuffer<>();
-            ndefs.addAll(tree.defs);
-            ndefs.add(make.MethodDef(make.Modifiers(PUBLIC),
-                    tree.name.table.names.init,
-                    null, List.nil(), List.nil(), List.nil(),
-                    resolutionExceptionBlock(), null));
-            tree.defs = ndefs.toList();
-        }
-        super.visitClassDef(tree);
-    }
-
-    // Build a compiler tree for an exception throwing block, e.g.:
-    // {
-    //     throw new jdk.jshell.spi.SPIResolutionException(9);
-    // }
-    private JCBlock resolutionExceptionBlock() {
-        if (resolutionExceptionBlock == null) {
-            JCExpression expClass = null;
-            // Split the exception class name at dots
-            for (String id : SPIResolutionException.class.getName().split("\\.")) {
-                Name nm = names.fromString(id);
-                if (expClass == null) {
-                    expClass = make.Ident(nm);
-                } else {
-                    expClass = make.Select(expClass, nm);
-                }
-            }
-            JCNewClass exp = make.NewClass(null,
-                    null, expClass, List.of(make.Literal(keyIndex)), null);
-            resolutionExceptionBlock = make.Block(0L, List.of(make.Throw(exp)));
-        }
-        return resolutionExceptionBlock;
+    void debugWrap(String format, Object... args) {
+        //state.debug(this, InternalDebugControl.DBG_WRAP, format, args);
     }
 }
--- a/src/jdk.jshell/share/classes/jdk/jshell/Eval.java	Mon Jun 17 14:57:23 2019 -0400
+++ b/src/jdk.jshell/share/classes/jdk/jshell/Eval.java	Mon Jun 17 15:18:52 2019 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 2019, Oracle and/or its affiliates. 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
@@ -44,7 +44,6 @@
 import com.sun.source.tree.NewClassTree;
 import com.sun.source.tree.Tree;
 import com.sun.source.tree.VariableTree;
-import com.sun.source.util.TreeScanner;
 import com.sun.tools.javac.tree.JCTree;
 import com.sun.tools.javac.tree.Pretty;
 import java.io.IOException;
@@ -622,7 +621,6 @@
                         name = "$" + ++varNumber;
                     }
                 }
-                TreeDissector dis = TreeDissector.createByFirstClass(pt);
                 ExpressionInfo varEI =
                         ExpressionToTypeInfo.localVariableTypeForInitializer(compileSource, state, true);
                 String declareTypeName;
@@ -634,6 +632,7 @@
                     fullTypeName = varEI.fullTypeName;
                     displayTypeName = varEI.displayTypeName;
 
+                    TreeDissector dis = TreeDissector.createByFirstClass(pt);
                     Pair<Wrap, Wrap> anonymous2Member =
                             anonymous2Member(varEI, compileSource, new Range(0, compileSource.length()), dis, expr.getExpression());
                     guts = Wrap.tempVarWrap(anonymous2Member.second.wrapped(), declareTypeName, name, anonymous2Member.first);
@@ -680,8 +679,8 @@
         String name = klassTree.getSimpleName().toString();
         DiagList modDiag = modifierDiagnostics(klassTree.getModifiers(), dis, false);
         TypeDeclKey key = state.keyMap.keyForClass(name);
-        // Corralling mutates.  Must be last use of pt, unitTree, klassTree
-        Wrap corralled = new Corraller(key.index(), pt.getContext()).corralType(klassTree);
+        // Corralling
+        Wrap corralled = new Corraller(dis, key.index(), compileSource).corralType(klassTree);
 
         Wrap guts = Wrap.classMemberWrap(compileSource);
         Snippet snip = new TypeDeclSnippet(key, userSource, guts,
@@ -752,8 +751,8 @@
         Tree returnType = mt.getReturnType();
         DiagList modDiag = modifierDiagnostics(mt.getModifiers(), dis, true);
         MethodKey key = state.keyMap.keyForMethod(name, parameterTypes);
-        // Corralling mutates.  Must be last use of pt, unitTree, mt
-        Wrap corralled = new Corraller(key.index(), pt.getContext()).corralMethod(mt);
+        // Corralling
+        Wrap corralled = new Corraller(dis, key.index(), compileSource).corralMethod(mt);
 
         if (modDiag.hasErrors()) {
             return compileFailResult(modDiag, userSource, Kind.METHOD);
--- a/src/jdk.jshell/share/classes/jdk/jshell/GeneralWrap.java	Mon Jun 17 14:57:23 2019 -0400
+++ b/src/jdk.jshell/share/classes/jdk/jshell/GeneralWrap.java	Mon Jun 17 15:18:52 2019 -0400
@@ -28,7 +28,10 @@
 /**
  * Common interface for all wrappings of snippet source to Java source.
  *
- * @author Robert Field
+ * Snippet index is index into the source of the snippet.  Note: If the snippet is a sub-range of
+ * the source, the index is not the index in the snippet.
+ *
+ * Wrap index is index into the wrapped snippet.
  */
 interface GeneralWrap {
 
--- a/src/jdk.jshell/share/classes/jdk/jshell/SourceCodeAnalysisImpl.java	Mon Jun 17 14:57:23 2019 -0400
+++ b/src/jdk.jshell/share/classes/jdk/jshell/SourceCodeAnalysisImpl.java	Mon Jun 17 15:18:52 2019 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 2019, Oracle and/or its affiliates. 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
@@ -301,7 +301,7 @@
             SourcePositions sp = at.trees().getSourcePositions();
             CompilationUnitTree topLevel = at.firstCuTree();
             List<Suggestion> result = new ArrayList<>();
-            TreePath tp = pathFor(topLevel, sp, code.snippetIndexToWrapIndex(cursor));
+            TreePath tp = pathFor(topLevel, sp, code, cursor);
             if (tp != null) {
                 Scope scope = at.trees().getScope(tp);
                 Predicate<Element> accessibility = createAccessibilityFilter(at, tp);
@@ -563,7 +563,10 @@
         }
     }
 
-    private TreePath pathFor(CompilationUnitTree topLevel, SourcePositions sp, int pos) {
+    private TreePath pathFor(CompilationUnitTree topLevel, SourcePositions sp, GeneralWrap wrap, int snippetEndPos) {
+        int wrapEndPos = snippetEndPos == 0
+                ? wrap.snippetIndexToWrapIndex(snippetEndPos)
+                : wrap.snippetIndexToWrapIndex(snippetEndPos - 1) + 1;
         TreePath[] deepest = new TreePath[1];
 
         new TreePathScanner<Void, Void>() {
@@ -576,7 +579,7 @@
                 long end = sp.getEndPosition(topLevel, tree);
                 long prevEnd = deepest[0] != null ? sp.getEndPosition(topLevel, deepest[0].getLeaf()) : -1;
 
-                if (start <= pos && pos <= end &&
+                if (start <= wrapEndPos && wrapEndPos <= end &&
                     (start != end || prevEnd != end || deepest[0] == null ||
                      deepest[0].getParentPath().getLeaf() != getCurrentPath().getLeaf())) {
                     deepest[0] = new TreePath(getCurrentPath(), tree);
@@ -1176,7 +1179,7 @@
         return proc.taskFactory.analyze(codeWrap, List.of(keepParameterNames), at -> {
             SourcePositions sp = at.trees().getSourcePositions();
             CompilationUnitTree topLevel = at.firstCuTree();
-            TreePath tp = pathFor(topLevel, sp, codeWrap.snippetIndexToWrapIndex(cursor));
+            TreePath tp = pathFor(topLevel, sp, codeWrap, cursor);
 
             if (tp == null)
                 return Collections.emptyList();
@@ -1526,7 +1529,7 @@
         return proc.taskFactory.analyze(codeWrap, at -> {
             SourcePositions sp = at.trees().getSourcePositions();
             CompilationUnitTree topLevel = at.firstCuTree();
-            TreePath tp = pathFor(topLevel, sp, codeWrap.snippetIndexToWrapIndex(codeFin.length()));
+            TreePath tp = pathFor(topLevel, sp, codeWrap, codeFin.length());
             if (tp.getLeaf().getKind() != Kind.IDENTIFIER) {
                 return new QualifiedNames(Collections.emptyList(), -1, true, false);
             }
--- a/src/jdk.jshell/share/classes/jdk/jshell/Wrap.java	Mon Jun 17 14:57:23 2019 -0400
+++ b/src/jdk.jshell/share/classes/jdk/jshell/Wrap.java	Mon Jun 17 15:18:52 2019 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2019, Oracle and/or its affiliates. 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
@@ -34,8 +34,6 @@
 /**
  * Wrapping of source into Java methods, fields, etc.  All but outer layer
  * wrapping with imports and class.
- *
- * @author Robert Field
  */
 abstract class Wrap implements GeneralWrap {
 
@@ -184,7 +182,7 @@
 
     public static final class Range {
         final int begin;
-        final int end;
+        final int end; // exclusive
 
         Range(int begin, int end) {
             this.begin = begin;
@@ -216,7 +214,7 @@
 
         @Override
         public String toString() {
-            return "Range[" + begin + "," + end + "]";
+            return "Range[" + begin + "," + end + ")";
         }
     }
 
@@ -280,8 +278,12 @@
                     before += s.length();
                 } else if (o instanceof Wrap) {
                     Wrap w = (Wrap) o;
-                    if (sni >= w.firstSnippetIndex() && sni <= w.lastSnippetIndex()) {
-                        return w.snippetIndexToWrapIndex(sni) + before;
+                    if (sni >= w.firstSnippetIndex() && sni < w.lastSnippetIndex()) {
+                        int wwi = w.snippetIndexToWrapIndex(sni);
+                        debugWrap("\nCommoundWrap.snippetIndexToWrapIndex: SnippetIndex(%d) -> WrapIndex(%d + %d = %d)"
+                                        + "\n   === %s",
+                                sni, wwi, before, wwi + before, wrapped());
+                        return wwi + before;
                     }
                     before += w.wrapped().length();
                 }
@@ -300,8 +302,8 @@
                     w = (Wrap) o;
                     int len = w.wrapped().length();
                     if ((wi - before) <= len) {
-                        //System.err.printf("Defer to wrap %s - wi: %d. before; %d   -- %s  >>> %s\n",
-                        //        w, wi, before, w.debugPos(wi - before), w.wrapped());
+                        debugWrap("CommoundWrap.wrapIndexToWrap: Defer to wrap %s - wi: %d. before; %d   >>> %s\n",
+                                w, wi, before, w.wrapped());
                         return w;
                     }
                     before += len;
@@ -321,9 +323,10 @@
                     Wrap w = (Wrap) o;
                     int len = w.wrapped().length();
                     if ((wi - before) <= len) {
-                        //System.err.printf("Defer to wrap %s - wi: %d. before; %d   -- %s  >>> %s\n",
-                        //        w, wi, before, w.debugPos(wi - before), w.wrapped());
-                        return w.wrapIndexToSnippetIndex(wi - before);
+                        int si = w.wrapIndexToSnippetIndex(wi - before);
+                        debugWrap("\nCommoundWrap.wrapIndexToSnippetIndex: WrapIndex(%d) -> SnippetIndex(%d)\n",
+                                wi, si);
+                        return si;
                     }
                     before += len;
                 }
@@ -369,7 +372,7 @@
                 } else if (o instanceof Wrap) {
                     w = (Wrap) o;
                     int lns = countLines(w.wrapped());
-                    if ((wline - before) < lns) {
+                    if ((wline - before) <= lns) {
                         return w;
                     }
                     before += lns;
@@ -388,7 +391,7 @@
                 } else if (o instanceof Wrap) {
                     Wrap w = (Wrap) o;
                     int lns = countLines(w.wrapped());
-                    if ((wline - before) < lns) {
+                    if ((wline - before) <= lns) {
                         return w.wrapLineToSnippetLine(wline - before);
                     }
                     before += lns;
@@ -409,16 +412,21 @@
 
         @Override
         public String toString() {
-            return "CompoundWrap(" + Arrays.stream(os).map(Object::toString).collect(joining(",")) + ")";
+            return "CompoundWrap(" + Arrays.stream(os)
+                    .map(o -> (o instanceof String)
+                            ? "\"" + o + "\""
+                            : o.toString())
+                    .collect(joining(","))
+                    + ")";
         }
     }
 
-    private static class RangeWrap extends Wrap {
+    static class RangeWrap extends Wrap {
 
         final Range range;
-        final String wrapped;
-        final int firstSnline;
-        final int lastSnline;
+        final String wrapped;   // The snippet portion of the source
+        final int firstSnline;  // Line count to start of snippet portion
+        final int lastSnline;   // Line count to end of snippet portion
 
         RangeWrap(String snippetSource, Range usedWithinSnippet) {
             this.range = usedWithinSnippet;
@@ -436,24 +444,39 @@
         @Override
         public int snippetIndexToWrapIndex(int sni) {
             if (sni < range.begin) {
+                debugWrap("\nRangeWrap.snippetIndexToWrapIndex: ERR before SnippetIndex(%d) -> WrapIndex(%d + %d = %d)\n",
+                        sni, 0);
                 return 0;
             }
             if (sni > range.end) {
+                debugWrap("\nRangeWrap.snippetIndexToWrapIndex: ERR after SnippetIndex(%d) -> WrapIndex(%d + %d = %d)\n",
+                        sni, range.length());
                 return range.length();
             }
-            return sni - range.begin;
+            int wi = sni - range.begin;
+            debugWrap("\nRangeWrap.snippetIndexToWrapIndex: SnippetIndex(%d) -> WrapIndex(%d + %d = %d)"
+                            + "\n   === %s",
+                    sni, sni, range.begin, sni - range.begin, wrapped());
+            return wi;
         }
 
         @Override
         public int wrapIndexToSnippetIndex(int wi) {
             if (wi < 0) {
+                debugWrap("\nRangeWrap.wrapIndexToSnippetIndex: ERR before WrapIndex(%d) -> SnippetIndex(%d)\n",
+                        wi, 0);
                 return 0; // bad index
             }
             int max = range.length();
             if (wi > max) {
-                wi = max;
+                debugWrap("\nRangeWrap.wrapIndexToSnippetIndex: ERR after WrapIndex(%d) -> SnippetIndex(%d)\n",
+                        wi, max + range.begin);
+                return max + range.begin;
             }
-            return wi + range.begin;
+            int sni = wi + range.begin;
+            debugWrap("\nRangeWrap.wrapIndexToSnippetIndex: WrapIndex(%d) -> SnippetIndex(%d)\n",
+                    wi, sni);
+            return sni;
         }
 
         @Override
@@ -535,4 +558,9 @@
             super("    public static ", wtype, brackets + " ", wname, semi(wname));
         }
     }
+
+    void debugWrap(String format, Object... args) {
+        //System.err.printf(format, args);
+        //state.debug(this, InternalDebugControl.DBG_WRAP, format, args);
+    }
 }
--- a/test/langtools/ProblemList.txt	Mon Jun 17 14:57:23 2019 -0400
+++ b/test/langtools/ProblemList.txt	Mon Jun 17 15:18:52 2019 -0400
@@ -37,7 +37,6 @@
 
 jdk/jshell/UserJdiUserRemoteTest.java                                           8173079    linux-all
 jdk/jshell/UserInputTest.java                                                   8169536    generic-all
-jdk/jshell/ExceptionsTest.java                                                  8200701    windows-all
 
 ###########################################################################
 #
--- a/test/langtools/jdk/jshell/ClassesTest.java	Mon Jun 17 14:57:23 2019 -0400
+++ b/test/langtools/jdk/jshell/ClassesTest.java	Mon Jun 17 15:18:52 2019 -0400
@@ -344,7 +344,7 @@
                    "  public T get() {return null;}\n" +
                    "}",
                    added(VALID),
-                   ste(aClass, Status.RECOVERABLE_DEFINED, Status.VALID, true, null));
+                   ste(aClass, Status.RECOVERABLE_DEFINED, Status.VALID, false, null));
         assertEval("new A()");
     }
 
--- a/test/langtools/jdk/jshell/ExceptionsTest.java	Mon Jun 17 14:57:23 2019 -0400
+++ b/test/langtools/jdk/jshell/ExceptionsTest.java	Mon Jun 17 15:18:52 2019 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2019, Oracle and/or its affiliates. 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
@@ -24,7 +24,7 @@
 /*
  * @test
  * @summary Tests for exceptions
- * @bug 8198801
+ * @bug 8198801 8212167
  * @build KullaTesting TestingInputStream
  * @run testng ExceptionsTest
  */
@@ -207,6 +207,49 @@
                         newStackTraceElement("", "", cr2.snippet(), 1)));
     }
 
+    // test 8212167
+    public void throwLineFormat1() {
+        SnippetEvent se = assertEvalException(
+                "if (true) { \n" +
+                        "   int x = 10; \n" +
+                        "   int y = 10 / 0;}"
+        );
+        assertExceptionMatch(se,
+                new ExceptionInfo(ArithmeticException.class, "/ by zero",
+                        newStackTraceElement("", "", se.snippet(), 3)));
+    }
+
+    public void throwLineFormat3() {
+        Snippet sp = methodKey(assertEval(
+                "int p() \n" +
+                        "  { return 4/0; }"));
+        Snippet sm = methodKey(assertEval(
+                "int m(int x)\n" +
+                        "       \n" +
+                        "       {\n" +
+                        "          return p() + x; \n" +
+                        "       }"));
+        Snippet sn = methodKey(assertEval(
+                "int n(int x) {\n" +
+                        "         try {\n" +
+                        "           return m(x);\n" +
+                        "         }\n" +
+                        "         catch (Throwable ex) {\n" +
+                        "           throw new IllegalArgumentException( \"GOT:\", ex);\n" +
+                        "         }\n" +
+                        "       }"));
+        SnippetEvent se = assertEvalException("n(33);");
+        assertExceptionMatch(se,
+                new ExceptionInfo(IllegalArgumentException.class, null,
+                        new ExceptionInfo(ArithmeticException.class, "/ by zero",
+                                newStackTraceElement("", "p", sp, 2),
+                                newStackTraceElement("", "m", sm, 4),
+                                newStackTraceElement("", "n", sn, 3),
+                                newStackTraceElement("", "", se.snippet(), 1)),
+                        newStackTraceElement("", "n", sn, 6),
+                        newStackTraceElement("", "", se.snippet(), 1)));
+    }
+
     @Test(enabled = false) // TODO 8129427
     public void outOfMemory() {
         assertEval("import java.util.*;");
@@ -333,7 +376,8 @@
                     }
                     assertEquals(actualElement.getFileName(), expectedElement.getFileName(), message + " : file names");
                     assertEquals(actualElement.getLineNumber(), expectedElement.getLineNumber(), message + " : line numbers"
-                        + " -- actual: " + actual + ", expected: " + expected);
+                        + " -- actual: " + actualElement.getLineNumber() + ", expected: " + expectedElement.getLineNumber() +
+                            " -- in: " + actualElement.getClassName());
                 }
             }
         }
--- a/test/langtools/jdk/jshell/KullaTesting.java	Mon Jun 17 14:57:23 2019 -0400
+++ b/test/langtools/jdk/jshell/KullaTesting.java	Mon Jun 17 15:18:52 2019 -0400
@@ -911,7 +911,10 @@
 
     public void assertCompletionIncludesExcludes(String code, Boolean isSmart, Set<String> expected, Set<String> notExpected) {
         List<String> completions = computeCompletions(code, isSmart);
-        assertTrue(completions.containsAll(expected), String.valueOf(completions));
+        assertTrue(completions.containsAll(expected), "Expected completions: "
+                + String.valueOf(expected)
+                + ", got: "
+                + String.valueOf(completions));
         assertTrue(Collections.disjoint(completions, notExpected), String.valueOf(completions));
     }
 
--- a/test/langtools/jdk/jshell/WrapperTest.java	Mon Jun 17 14:57:23 2019 -0400
+++ b/test/langtools/jdk/jshell/WrapperTest.java	Mon Jun 17 15:18:52 2019 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2016, 2019, Oracle and/or its affiliates. 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
@@ -23,7 +23,7 @@
 
 /*
  * @test
- * @bug 8159111
+ * @bug 8159111 8159740
  * @summary test wrappers and dependencies
  * @modules jdk.jshell/jdk.jshell
  * @build KullaTesting
@@ -62,15 +62,126 @@
         assertPosition(swg, src, 15, 6);
     }
 
-    @Test(enabled = false) // TODO 8159740
+    // test 8159740
     public void testMethodCorralled() {
         String src = "void glib() { f(); }";
+        //            _123456789_123456789
         Snippet g = methodKey(assertEval(src, added(RECOVERABLE_DEFINED)));
         SnippetWrapper swg = getState().sourceCodeAnalysis().wrapper(g);
-        assertWrapperHas(swg, src, Kind.METHOD, "void", "glib");
+        assertWrapperHas(swg, src, Kind.METHOD, "SPIResolutionException",
+                "void", "glib");
+        assertPosition(swg, src, 0, 4);
         assertPosition(swg, src, 5, 4);
     }
 
+    // test 8159740
+    public void testClassCorralled0() {
+        String src = "class AAA { float mmm(double d1234) { return (float) (f0 * d1234); } }";
+        //            _123456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789
+        Snippet a = classKey(assertEval(src, added(RECOVERABLE_DEFINED)));
+        SnippetWrapper swa = getState().sourceCodeAnalysis().wrapper(a);
+        assertWrapperHas(swa, src, Kind.TYPE_DECL, "SPIResolutionException",
+                "class", "AAA", "float", "mmm", "double", "d1234");
+        assertPosition(swa, src, 0, 5);
+        assertPosition(swa, src, 6, 3);
+        assertPosition(swa, src, 12, 5);
+        assertPosition(swa, src, 18, 3);
+        assertPosition(swa, src, 22, 6);
+        assertPosition(swa, src, 29, 5);
+    }
+
+    // test 8159740
+    public void testClassCorralled() {
+        String src = "class AAA { int xxx = x0 + 4; float mmm(float ffff) { return f0 * ffff; } }";
+        //            _123456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789
+        Snippet a = classKey(assertEval(src, added(RECOVERABLE_DEFINED)));
+        SnippetWrapper swa = getState().sourceCodeAnalysis().wrapper(a);
+        assertWrapperHas(swa, src, Kind.TYPE_DECL, "SPIResolutionException",
+                "class", "AAA", "int", "xxx", "float", "mmm", "ffff");
+        assertPosition(swa, src, 0, 5);
+        assertPosition(swa, src, 6, 3);
+        assertPosition(swa, src, 12, 3);
+        assertPosition(swa, src, 16, 3);
+        assertPosition(swa, src, 30, 5);
+        assertPosition(swa, src, 36, 3);
+        assertPosition(swa, src, 40, 5);
+        assertPosition(swa, src, 46, 4);
+    }
+
+    // test 8159740
+    public void testClassWithConstructorCorralled() {
+        String src = "public class AAA { AAA(String b) {} int xxx = x0 + 4; float mmm(float ffff) { return f0 * ffff; } }";
+        //            _123456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789
+        Snippet a = classKey(assertEval(src, added(RECOVERABLE_DEFINED)));
+        SnippetWrapper swa = getState().sourceCodeAnalysis().wrapper(a);
+        assertWrapperHas(swa, src, Kind.TYPE_DECL, "SPIResolutionException",
+                "class", "AAA", "String", "int", "xxx", "float", "mmm", "ffff");
+        assertPosition(swa, src, 7, 5);
+        assertPosition(swa, src, 13, 3);
+        assertPosition(swa, src, 19, 3);
+        assertPosition(swa, src, 23, 5);
+        assertPosition(swa, src, 30, 1);
+        assertPosition(swa, src, 36, 3);
+        assertPosition(swa, src, 40, 3);
+        assertPosition(swa, src, 54, 5);
+        assertPosition(swa, src, 60, 3);
+        assertPosition(swa, src, 64, 5);
+        assertPosition(swa, src, 70, 4);
+    }
+
+    // test 8159740
+    public void testInterfaceCorralled() {
+        String src = "interface AAA { default float mmm(double d1234) { return (float) (f0 * d1234); } }";
+        //            _123456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789
+        Snippet a = classKey(assertEval(src, added(RECOVERABLE_DEFINED)));
+        SnippetWrapper swa = getState().sourceCodeAnalysis().wrapper(a);
+        assertWrapperHas(swa, src, Kind.TYPE_DECL, "SPIResolutionException",
+                "interface", "AAA", "float", "mmm", "double", "d1234");
+        assertPosition(swa, src, 0, 9);
+        assertPosition(swa, src, 10, 3);
+        assertPosition(swa, src, 16, 7);
+        assertPosition(swa, src, 24, 5);
+        assertPosition(swa, src, 30, 3);
+        assertPosition(swa, src, 34, 6);
+        assertPosition(swa, src, 41, 5);
+    }
+
+    // test 8159740
+    public void testEnumCorralled() {
+        String src =
+                "public enum Planet {\n" +
+                "    MERCURY (3.303e+23, 2.4397e6),\n" +
+                "    VENUS   (4.869e+24, 6.0518e6),\n" +
+                "    EARTH   (5.976e+24, 6.37814e6),\n" +
+                "    MARS    (6.421e+23, 3.3972e6),\n" +
+                "    JUPITER (1.9e+27,   7.1492e7),\n" +
+                "    SATURN  (5.688e+26, 6.0268e7),\n" +
+                "    URANUS  (8.686e+25, 2.5559e7),\n" +
+                "    NEPTUNE (1.024e+26, 2.4746e7);\n" +
+                "\n" +
+                "    private final double mass;   // in kilograms\n" +
+                "    private final double radius; // in meters\n" +
+                "    Planet(double mass, double radius) {\n" +
+                "        this.mass = mass;\n" +
+                "        this.radius = radius;\n" +
+                "    }\n" +
+                "    private double mass() { return mass; }\n" +
+                "    private double radius() { return radius; }\n" +
+                "\n" +
+                "    double surfaceGravity() {\n" +
+                "        return GRAVITATIONAL_CONSTANT * mass / (radius * radius);\n" +
+                "    }\n" +
+                "    double surfaceWeight(double otherMass) {\n" +
+                "        return otherMass * surfaceGravity();\n" +
+                "    }\n" +
+                "}\n";
+        Snippet a = classKey(assertEval(src, added(RECOVERABLE_DEFINED)));
+        SnippetWrapper swa = getState().sourceCodeAnalysis().wrapper(a);
+        assertWrapperHas(swa, src, Kind.TYPE_DECL, "SPIResolutionException",
+                "enum", "Planet", "double", "mass", "EARTH", "NEPTUNE", "MERCURY",
+                "radius", "surfaceGravity", "surfaceWeight");
+    }
+
     public void testMethodBad() {
         String src = "void flob() { ?????; }";
         List<SnippetWrapper> swl = getState().sourceCodeAnalysis().wrappers(src);
@@ -182,23 +293,36 @@
     private void assertWrapperHas(SnippetWrapper sw, String source, Kind kind, String... has) {
         assertEquals(sw.source(), source);
         assertEquals(sw.kind(), kind);
+        String s = sw.wrapped();
         if (kind == Kind.IMPORT) {
-            assertTrue(sw.wrapped().contains("import"));
+            assertHas(s, "import");
         } else {
             String cn = sw.fullClassName();
             int idx = cn.lastIndexOf(".");
-            assertTrue(sw.wrapped().contains(cn.substring(idx+1)));
-            assertTrue(sw.wrapped().contains("class"));
+            assertHas(s, cn.substring(idx+1));
+            assertHas(s, "class");
         }
-        for (String s : has) {
-            assertTrue(sw.wrapped().contains(s));
+        for (String hx : has) {
+            assertHas(s, hx);
         }
     }
 
+    private void assertHas(String s, String has) {
+        assertTrue(s.contains(has), "Expected to find '" + has + "' in: '" + s + "'");
+    }
+
     private void assertPosition(SnippetWrapper sw, String source, int start, int length) {
+        //System.err.printf("\n#assertPosition:\n#  debug-source: %s\n#  SnippetWrapper --\n#    source: %s\n#    wrapped: %s\n",
+        //        source, sw.source(), sw.wrapped());
+        //System.err.printf("#  start: %d    length: %d\n", start, length);
         int wpg = sw.sourceToWrappedPosition(start);
-        assertEquals(sw.wrapped().substring(wpg, wpg+length),
-                source.substring(start, start+length),
+        //System.err.printf("#  wrappedPos: %d\n", wpg);
+        String wrappedPart = sw.wrapped().substring(wpg, wpg+length);
+        String sourcePart = source.substring(start, start+length);
+        //System.err.printf("#  wrapped @ wrappedPos: %s\n", wrappedPart);
+        //System.err.printf("#  source @ start: %s\n", sourcePart);
+
+        assertEquals(wrappedPart, sourcePart,
                 "position " + wpg + " in " + sw.wrapped());
         assertEquals(sw.wrappedToSourcePosition(wpg), start);
     }