changeset 24353:d63e731a896c jdk8u152-b03

Merge
author asaha
date Thu, 13 Apr 2017 08:28:56 -0700
parents e7db67a9ddfd 857e77fd668d
children cf85f331361b
files
diffstat 22 files changed, 551 insertions(+), 228 deletions(-) [+]
line wrap: on
line diff
--- a/src/cpu/sparc/vm/vm_version_sparc.cpp	Mon Mar 27 11:31:27 2017 -0700
+++ b/src/cpu/sparc/vm/vm_version_sparc.cpp	Thu Apr 13 08:28:56 2017 -0700
@@ -236,7 +236,7 @@
   assert((OptoLoopAlignment % relocInfo::addr_unit()) == 0, "alignment is not a multiple of NOP size");
 
   char buf[512];
-  jio_snprintf(buf, sizeof(buf), "%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s",
+  jio_snprintf(buf, sizeof(buf), "%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s",
                (has_v9() ? ", v9" : (has_v8() ? ", v8" : "")),
                (has_hardware_popc() ? ", popc" : ""),
                (has_vis1() ? ", vis1" : ""),
@@ -249,6 +249,7 @@
                (has_sha256() ? ", sha256" : ""),
                (has_sha512() ? ", sha512" : ""),
                (is_ultra3() ? ", ultra3" : ""),
+               (has_sparc5_instr() ? ", sparc5" : ""),
                (is_sun4v() ? ", sun4v" : ""),
                (is_niagara_plus() ? ", niagara_plus" : (is_niagara() ? ", niagara" : "")),
                (is_sparc64() ? ", sparc64" : ""),
@@ -364,6 +365,7 @@
 
 #ifndef PRODUCT
   if (PrintMiscellaneous && Verbose) {
+    tty->print_cr("L1 data cache line size: %u", L1_data_cache_line_size());
     tty->print_cr("L2 data cache line size: %u", L2_data_cache_line_size());
     tty->print("Allocation");
     if (AllocatePrefetchStyle <= 0) {
@@ -447,9 +449,10 @@
 
 unsigned int VM_Version::calc_parallel_worker_threads() {
   unsigned int result;
-  if (is_M_series()) {
-    // for now, use same gc thread calculation for M-series as for niagara-plus
-    // in future, we may want to tweak parameters for nof_parallel_worker_thread
+  if (is_M_series() || is_S_series()) {
+    // for now, use same gc thread calculation for M-series and S-series as for
+    // niagara-plus. In future, we may want to tweak parameters for
+    // nof_parallel_worker_thread
     result = nof_parallel_worker_threads(5, 16, 8);
   } else if (is_niagara_plus()) {
     result = nof_parallel_worker_threads(5, 16, 8);
@@ -458,3 +461,37 @@
   }
   return result;
 }
+
+
+int VM_Version::parse_features(const char* implementation) {
+  int features = unknown_m;
+  // Convert to UPPER case before compare.
+  char* impl = os::strdup(implementation);
+
+  for (int i = 0; impl[i] != 0; i++)
+    impl[i] = (char)toupper((uint)impl[i]);
+
+  if (strstr(impl, "SPARC64") != NULL) {
+    features |= sparc64_family_m;
+  } else if (strstr(impl, "SPARC-M") != NULL) {
+    // M-series SPARC is based on T-series.
+    features |= (M_family_m | T_family_m);
+  } else if (strstr(impl, "SPARC-S") != NULL) {
+    // S-series SPARC is based on T-series.
+    features |= (S_family_m | T_family_m);
+  } else if (strstr(impl, "SPARC-T") != NULL) {
+    features |= T_family_m;
+    if (strstr(impl, "SPARC-T1") != NULL) {
+      features |= T1_model_m;
+    }
+  } else if (strstr(impl, "SUN4V-CPU") != NULL) {
+    // Generic or migration class LDOM
+    features |= T_family_m;
+  } else {
+#ifndef PRODUCT
+    warning("Failed to parse CPU implementation = '%s'", impl);
+#endif
+  }
+  os::free((void*)impl);
+  return features;
+}
--- a/src/cpu/sparc/vm/vm_version_sparc.hpp	Mon Mar 27 11:31:27 2017 -0700
+++ b/src/cpu/sparc/vm/vm_version_sparc.hpp	Thu Apr 13 08:28:56 2017 -0700
@@ -47,13 +47,14 @@
     cbcond_instructions  = 13,
     sparc64_family       = 14,
     M_family             = 15,
-    T_family             = 16,
-    T1_model             = 17,
-    sparc5_instructions  = 18,
-    aes_instructions     = 19,
-    sha1_instruction     = 20,
-    sha256_instruction   = 21,
-    sha512_instruction   = 22
+    S_family             = 16,
+    T_family             = 17,
+    T1_model             = 18,
+    sparc5_instructions  = 19,
+    aes_instructions     = 20,
+    sha1_instruction     = 21,
+    sha256_instruction   = 22,
+    sha512_instruction   = 23
   };
 
   enum Feature_Flag_Set {
@@ -76,6 +77,7 @@
     cbcond_instructions_m   = 1 << cbcond_instructions,
     sparc64_family_m        = 1 << sparc64_family,
     M_family_m              = 1 << M_family,
+    S_family_m              = 1 << S_family,
     T_family_m              = 1 << T_family,
     T1_model_m              = 1 << T1_model,
     sparc5_instructions_m   = 1 << sparc5_instructions,
@@ -105,6 +107,7 @@
 
   // Returns true if the platform is in the niagara line (T series)
   static bool is_M_family(int features) { return (features & M_family_m) != 0; }
+  static bool is_S_family(int features) { return (features & S_family_m) != 0; }
   static bool is_T_family(int features) { return (features & T_family_m) != 0; }
   static bool is_niagara() { return is_T_family(_features); }
 #ifdef ASSERT
@@ -119,7 +122,7 @@
   static bool is_T1_model(int features) { return is_T_family(features) && ((features & T1_model_m) != 0); }
 
   static int maximum_niagara1_processor_count() { return 32; }
-
+  static int parse_features(const char* implementation);
 public:
   // Initialization
   static void initialize();
@@ -152,6 +155,7 @@
   static bool is_niagara_plus()         { return is_T_family(_features) && !is_T1_model(_features); }
 
   static bool is_M_series()             { return is_M_family(_features); }
+  static bool is_S_series()             { return is_S_family(_features); }
   static bool is_T4()                   { return is_T_family(_features) && has_cbcond(); }
   static bool is_T7()                   { return is_T_family(_features) && has_sparc5_instr(); }
 
--- a/src/cpu/x86/vm/vm_version_x86.cpp	Mon Mar 27 11:31:27 2017 -0700
+++ b/src/cpu/x86/vm/vm_version_x86.cpp	Thu Apr 13 08:28:56 2017 -0700
@@ -406,6 +406,8 @@
   _stepping = 0;
   _cpuFeatures = 0;
   _logical_processors_per_package = 1;
+  // i486 internal cache is both I&D and has a 16-byte line size
+  _L1_data_cache_line_size = 16;
 
   if (!Use486InstrsOnly) {
     // Get raw processor info
@@ -424,6 +426,7 @@
       // Logical processors are only available on P4s and above,
       // and only if hyperthreading is available.
       _logical_processors_per_package = logical_processor_count();
+      _L1_data_cache_line_size = L1_line_size();
     }
   }
 
@@ -1034,6 +1037,7 @@
   if (PrintMiscellaneous && Verbose) {
     tty->print_cr("Logical CPUs per core: %u",
                   logical_processors_per_package());
+    tty->print_cr("L1 data cache line size: %u", L1_data_cache_line_size());
     tty->print("UseSSE=%d", (int) UseSSE);
     if (UseAVX > 0) {
       tty->print("  UseAVX=%d", (int) UseAVX);
--- a/src/cpu/x86/vm/vm_version_x86.hpp	Mon Mar 27 11:31:27 2017 -0700
+++ b/src/cpu/x86/vm/vm_version_x86.hpp	Thu Apr 13 08:28:56 2017 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2014, 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
@@ -595,7 +595,7 @@
     return (result == 0 ? 1 : result);
   }
 
-  static intx prefetch_data_size()  {
+  static intx L1_line_size()  {
     intx result = 0;
     if (is_intel()) {
       result = (_cpuid_info.dcp_cpuid4_ebx.bits.L1_line_size + 1);
@@ -607,6 +607,10 @@
     return result;
   }
 
+  static intx prefetch_data_size()  {
+    return L1_line_size();
+  }
+
   //
   // Feature identification
   //
--- a/src/os_cpu/solaris_sparc/vm/vm_version_solaris_sparc.cpp	Mon Mar 27 11:31:27 2017 -0700
+++ b/src/os_cpu/solaris_sparc/vm/vm_version_solaris_sparc.cpp	Thu Apr 13 08:28:56 2017 -0700
@@ -262,6 +262,7 @@
 
 // We need to keep these here as long as we have to build on Solaris
 // versions before 10.
+
 #ifndef SI_ARCHITECTURE_32
 #define SI_ARCHITECTURE_32      516     /* basic 32-bit SI_ARCHITECTURE */
 #endif
@@ -270,231 +271,233 @@
 #define SI_ARCHITECTURE_64      517     /* basic 64-bit SI_ARCHITECTURE */
 #endif
 
-static void do_sysinfo(int si, const char* string, int* features, int mask) {
-  char   tmp;
-  size_t bufsize = sysinfo(si, &tmp, 1);
+#ifndef SI_CPUBRAND
+#define SI_CPUBRAND             523     /* return cpu brand string */
+#endif
 
-  // All SI defines used below must be supported.
-  guarantee(bufsize != -1, "must be supported");
+class Sysinfo {
+  char* _string;
+public:
+  Sysinfo(int si) : _string(NULL) {
+    char   tmp;
+    size_t bufsize = sysinfo(si, &tmp, 1);
 
-  char* buf = (char*) malloc(bufsize);
+    if (bufsize != -1) {
+      char* buf = (char*) os::malloc(bufsize, mtInternal);
+      if (buf != NULL) {
+        if (sysinfo(si, buf, bufsize) == bufsize) {
+          _string = buf;
+        } else {
+          os::free(buf);
+        }
+      }
+     }
+   }
 
-  if (buf == NULL)
-    return;
-
-  if (sysinfo(si, buf, bufsize) == bufsize) {
-    // Compare the string.
-    if (strcmp(buf, string) == 0) {
-      *features |= mask;
+  ~Sysinfo() {
+    if (_string != NULL) {
+      os::free(_string);
     }
   }
 
-  free(buf);
-}
+  const char* value() const {
+    return _string;
+  }
+
+  bool valid() const {
+    return _string != NULL;
+  }
+
+  bool match(const char* s) const {
+    return valid() ? strcmp(_string, s) == 0 : false;
+  }
+
+  bool match_substring(const char* s) const {
+    return valid() ? strstr(_string, s) != NULL : false;
+  }
+};
+
+class Sysconf {
+  int _value;
+public:
+  Sysconf(int sc) : _value(-1) {
+    _value = sysconf(sc);
+  }
+  bool valid() const {
+    return _value != -1;
+  }
+  int value() const {
+    return _value;
+  }
+};
+
+
+#ifndef _SC_DCACHE_LINESZ
+#define _SC_DCACHE_LINESZ       508     /* Data cache line size */
+#endif
+
+#ifndef _SC_L2CACHE_LINESZ
+#define _SC_L2CACHE_LINESZ      527     /* Size of L2 cache line */
+#endif
+
 
 int VM_Version::platform_features(int features) {
-  // getisax(2), SI_ARCHITECTURE_32, and SI_ARCHITECTURE_64 are
-  // supported on Solaris 10 and later.
-  if (os::Solaris::supports_getisax()) {
+  assert(os::Solaris::supports_getisax(), "getisax() must be available");
 
-    // Check 32-bit architecture.
-    do_sysinfo(SI_ARCHITECTURE_32, "sparc", &features, v8_instructions_m);
+  // Check 32-bit architecture.
+  if (Sysinfo(SI_ARCHITECTURE_32).match("sparc")) {
+    features |= v8_instructions_m;
+  }
 
-    // Check 64-bit architecture.
-    do_sysinfo(SI_ARCHITECTURE_64, "sparcv9", &features, generic_v9_m);
+  // Check 64-bit architecture.
+  if (Sysinfo(SI_ARCHITECTURE_64).match("sparcv9")) {
+    features |= generic_v9_m;
+  }
 
-    // Extract valid instruction set extensions.
-    uint_t avs[2];
-    uint_t avn = os::Solaris::getisax(avs, 2);
-    assert(avn <= 2, "should return two or less av's");
-    uint_t av = avs[0];
+  // Extract valid instruction set extensions.
+  uint_t avs[2];
+  uint_t avn = os::Solaris::getisax(avs, 2);
+  assert(avn <= 2, "should return two or less av's");
+  uint_t av = avs[0];
 
 #ifndef PRODUCT
-    if (PrintMiscellaneous && Verbose) {
-      tty->print("getisax(2) returned: " PTR32_FORMAT, av);
-      if (avn > 1) {
-        tty->print(", " PTR32_FORMAT, avs[1]);
-      }
-      tty->cr();
+  if (PrintMiscellaneous && Verbose) {
+    tty->print("getisax(2) returned: " PTR32_FORMAT, av);
+    if (avn > 1) {
+      tty->print(", " PTR32_FORMAT, avs[1]);
     }
+    tty->cr();
+  }
 #endif
 
-    if (av & AV_SPARC_MUL32)  features |= hardware_mul32_m;
-    if (av & AV_SPARC_DIV32)  features |= hardware_div32_m;
-    if (av & AV_SPARC_FSMULD) features |= hardware_fsmuld_m;
-    if (av & AV_SPARC_V8PLUS) features |= v9_instructions_m;
-    if (av & AV_SPARC_POPC)   features |= hardware_popc_m;
-    if (av & AV_SPARC_VIS)    features |= vis1_instructions_m;
-    if (av & AV_SPARC_VIS2)   features |= vis2_instructions_m;
-    if (avn > 1) {
-      uint_t av2 = avs[1];
+  if (av & AV_SPARC_MUL32)  features |= hardware_mul32_m;
+  if (av & AV_SPARC_DIV32)  features |= hardware_div32_m;
+  if (av & AV_SPARC_FSMULD) features |= hardware_fsmuld_m;
+  if (av & AV_SPARC_V8PLUS) features |= v9_instructions_m;
+  if (av & AV_SPARC_POPC)   features |= hardware_popc_m;
+  if (av & AV_SPARC_VIS)    features |= vis1_instructions_m;
+  if (av & AV_SPARC_VIS2)   features |= vis2_instructions_m;
+  if (avn > 1) {
+    uint_t av2 = avs[1];
 #ifndef AV2_SPARC_SPARC5
 #define AV2_SPARC_SPARC5 0x00000008 /* The 29 new fp and sub instructions */
 #endif
-      if (av2 & AV2_SPARC_SPARC5)       features |= sparc5_instructions_m;
-    }
+    if (av2 & AV2_SPARC_SPARC5)       features |= sparc5_instructions_m;
+  }
 
-    // Next values are not defined before Solaris 10
-    // but Solaris 8 is used for jdk6 update builds.
+  // We only build on Solaris 10 and up, but some of the values below
+  // are not defined on all versions of Solaris 10, so we define them,
+  // if necessary.
 #ifndef AV_SPARC_ASI_BLK_INIT
 #define AV_SPARC_ASI_BLK_INIT 0x0080  /* ASI_BLK_INIT_xxx ASI */
 #endif
-    if (av & AV_SPARC_ASI_BLK_INIT) features |= blk_init_instructions_m;
+  if (av & AV_SPARC_ASI_BLK_INIT) features |= blk_init_instructions_m;
 
 #ifndef AV_SPARC_FMAF
 #define AV_SPARC_FMAF 0x0100        /* Fused Multiply-Add */
 #endif
-    if (av & AV_SPARC_FMAF)         features |= fmaf_instructions_m;
+  if (av & AV_SPARC_FMAF)         features |= fmaf_instructions_m;
 
 #ifndef AV_SPARC_FMAU
-#define    AV_SPARC_FMAU    0x0200  /* Unfused Multiply-Add */
+#define AV_SPARC_FMAU    0x0200  /* Unfused Multiply-Add */
 #endif
-    if (av & AV_SPARC_FMAU)         features |= fmau_instructions_m;
+  if (av & AV_SPARC_FMAU)         features |= fmau_instructions_m;
 
 #ifndef AV_SPARC_VIS3
-#define    AV_SPARC_VIS3    0x0400  /* VIS3 instruction set extensions */
+#define AV_SPARC_VIS3    0x0400  /* VIS3 instruction set extensions */
 #endif
-    if (av & AV_SPARC_VIS3)         features |= vis3_instructions_m;
+  if (av & AV_SPARC_VIS3)         features |= vis3_instructions_m;
 
 #ifndef AV_SPARC_CBCOND
 #define AV_SPARC_CBCOND 0x10000000  /* compare and branch instrs supported */
 #endif
-    if (av & AV_SPARC_CBCOND)       features |= cbcond_instructions_m;
+  if (av & AV_SPARC_CBCOND)       features |= cbcond_instructions_m;
 
 #ifndef AV_SPARC_AES
 #define AV_SPARC_AES 0x00020000  /* aes instrs supported */
 #endif
-    if (av & AV_SPARC_AES)       features |= aes_instructions_m;
+  if (av & AV_SPARC_AES)       features |= aes_instructions_m;
 
 #ifndef AV_SPARC_SHA1
 #define AV_SPARC_SHA1   0x00400000  /* sha1 instruction supported */
 #endif
-    if (av & AV_SPARC_SHA1)         features |= sha1_instruction_m;
+  if (av & AV_SPARC_SHA1)         features |= sha1_instruction_m;
 
 #ifndef AV_SPARC_SHA256
 #define AV_SPARC_SHA256 0x00800000  /* sha256 instruction supported */
 #endif
-    if (av & AV_SPARC_SHA256)       features |= sha256_instruction_m;
+  if (av & AV_SPARC_SHA256)       features |= sha256_instruction_m;
 
 #ifndef AV_SPARC_SHA512
 #define AV_SPARC_SHA512 0x01000000  /* sha512 instruction supported */
 #endif
-    if (av & AV_SPARC_SHA512)       features |= sha512_instruction_m;
+  if (av & AV_SPARC_SHA512)       features |= sha512_instruction_m;
 
+  // Determine the machine type.
+  if (Sysinfo(SI_MACHINE).match("sun4v")) {
+    features |= sun4v_m;
+  }
+
+  // If SI_CPUBRAND works, that means Solaris 12 API to get the cache line sizes
+  // is available to us as well
+  Sysinfo cpu_info(SI_CPUBRAND);
+  bool use_solaris_12_api = cpu_info.valid();
+  const char* impl;
+  int impl_m = 0;
+  if (use_solaris_12_api) {
+    impl = cpu_info.value();
+#ifndef PRODUCT
+  if (PrintMiscellaneous && Verbose) {
+    tty->print_cr("Parsing CPU implementation from %s", impl);
+  }
+#endif
+    impl_m = parse_features(impl);
   } else {
-    // getisax(2) failed, use the old legacy code.
+    // Otherwise use kstat to determine the machine type.
+    kstat_ctl_t* kc = kstat_open();
+    if (kc != NULL) {
+      kstat_t* ksp = kstat_lookup(kc, (char*)"cpu_info", -1, NULL);
+      if (ksp != NULL) {
+        if (kstat_read(kc, ksp, NULL) != -1 && ksp->ks_data != NULL) {
+          kstat_named_t* knm = (kstat_named_t *)ksp->ks_data;
+          for (int i = 0; i < ksp->ks_ndata; i++) {
+            if (strcmp((const char*)&(knm[i].name), "implementation") == 0) {
+              impl = KSTAT_NAMED_STR_PTR(&knm[i]);
 #ifndef PRODUCT
-    if (PrintMiscellaneous && Verbose)
-      tty->print_cr("getisax(2) is not supported.");
+              if (PrintMiscellaneous && Verbose) {
+                tty->print_cr("Parsing CPU implementation from %s", impl);
+              }
 #endif
-
-    char   tmp;
-    size_t bufsize = sysinfo(SI_ISALIST, &tmp, 1);
-    char*  buf     = (char*) malloc(bufsize);
-
-    if (buf != NULL) {
-      if (sysinfo(SI_ISALIST, buf, bufsize) == bufsize) {
-        // Figure out what kind of sparc we have
-        char *sparc_string = strstr(buf, "sparc");
-        if (sparc_string != NULL) {              features |= v8_instructions_m;
-          if (sparc_string[5] == 'v') {
-            if (sparc_string[6] == '8') {
-              if (sparc_string[7] == '-') {      features |= hardware_mul32_m;
-                                                 features |= hardware_div32_m;
-              } else if (sparc_string[7] == 'p') features |= generic_v9_m;
-              else                               features |= generic_v8_m;
-            } else if (sparc_string[6] == '9')   features |= generic_v9_m;
+              impl_m = parse_features(impl);
+              break;
+            }
           }
         }
-
-        // Check for visualization instructions
-        char *vis = strstr(buf, "vis");
-        if (vis != NULL) {                       features |= vis1_instructions_m;
-          if (vis[3] == '2')                     features |= vis2_instructions_m;
-        }
       }
-      free(buf);
+      kstat_close(kc);
     }
   }
+  assert(impl_m != 0, err_msg("Unknown CPU implementation %s", impl));
+  features |= impl_m;
 
-  // Determine the machine type.
-  do_sysinfo(SI_MACHINE, "sun4v", &features, sun4v_m);
+  bool is_sun4v = (features & sun4v_m) != 0;
+  if (use_solaris_12_api && is_sun4v) {
+    // If Solaris 12 API is supported and it's sun4v use sysconf() to get the cache line sizes
+    Sysconf l1_dcache_line_size(_SC_DCACHE_LINESZ);
+    if (l1_dcache_line_size.valid()) {
+      _L1_data_cache_line_size =  l1_dcache_line_size.value();
+    }
 
-  {
-    // Using kstat to determine the machine type.
-    kstat_ctl_t* kc = kstat_open();
-    kstat_t* ksp = kstat_lookup(kc, (char*)"cpu_info", -1, NULL);
-    const char* implementation = "UNKNOWN";
-    if (ksp != NULL) {
-      if (kstat_read(kc, ksp, NULL) != -1 && ksp->ks_data != NULL) {
-        kstat_named_t* knm = (kstat_named_t *)ksp->ks_data;
-        for (int i = 0; i < ksp->ks_ndata; i++) {
-          if (strcmp((const char*)&(knm[i].name),"implementation") == 0) {
-#ifndef KSTAT_DATA_STRING
-#define KSTAT_DATA_STRING   9
-#endif
-            if (knm[i].data_type == KSTAT_DATA_CHAR) {
-              // VM is running on Solaris 8 which does not have value.str.
-              implementation = &(knm[i].value.c[0]);
-            } else if (knm[i].data_type == KSTAT_DATA_STRING) {
-              // VM is running on Solaris 10.
-#ifndef KSTAT_NAMED_STR_PTR
-              // Solaris 8 was used to build VM, define the structure it misses.
-              struct str_t {
-                union {
-                  char *ptr;     /* NULL-term string */
-                  char __pad[8]; /* 64-bit padding */
-                } addr;
-                uint32_t len;    /* # bytes for strlen + '\0' */
-              };
-#define KSTAT_NAMED_STR_PTR(knptr) (( (str_t*)&((knptr)->value) )->addr.ptr)
-#endif
-              implementation = KSTAT_NAMED_STR_PTR(&knm[i]);
-            }
-#ifndef PRODUCT
-            if (PrintMiscellaneous && Verbose) {
-              tty->print_cr("cpu_info.implementation: %s", implementation);
-            }
-#endif
-            // Convert to UPPER case before compare.
-            char* impl = strdup(implementation);
-
-            for (int i = 0; impl[i] != 0; i++)
-              impl[i] = (char)toupper((uint)impl[i]);
-            if (strstr(impl, "SPARC64") != NULL) {
-              features |= sparc64_family_m;
-            } else if (strstr(impl, "SPARC-M") != NULL) {
-              // M-series SPARC is based on T-series.
-              features |= (M_family_m | T_family_m);
-            } else if (strstr(impl, "SPARC-T") != NULL) {
-              features |= T_family_m;
-              if (strstr(impl, "SPARC-T1") != NULL) {
-                features |= T1_model_m;
-              }
-            } else {
-              if (strstr(impl, "SPARC") == NULL) {
-#ifndef PRODUCT
-                // kstat on Solaris 8 virtual machines (branded zones)
-                // returns "(unsupported)" implementation.
-                warning("kstat cpu_info implementation = '%s', should contain SPARC", impl);
-#endif
-                implementation = "SPARC";
-              }
-            }
-            free((void*)impl);
-            break;
-          }
-        } // for(
-      }
+    Sysconf l2_dcache_line_size(_SC_L2CACHE_LINESZ);
+    if (l2_dcache_line_size.valid()) {
+      _L2_data_cache_line_size = l2_dcache_line_size.value();
     }
-    assert(strcmp(implementation, "UNKNOWN") != 0,
-           "unknown cpu info (changed kstat interface?)");
-    kstat_close(kc);
+  } else {
+    // Otherwise figure out the cache line sizes using PICL
+    bool is_fujitsu = (features & sparc64_family_m) != 0;
+    PICL picl(is_fujitsu, is_sun4v);
+    _L1_data_cache_line_size = picl.L1_data_cache_line_size();
+    _L2_data_cache_line_size = picl.L2_data_cache_line_size();
   }
-
-  // Figure out cache line sizes using PICL
-  PICL picl((features & sparc64_family_m) != 0, (features & sun4v_m) != 0);
-  _L2_data_cache_line_size = picl.L2_data_cache_line_size();
-
   return features;
 }
--- a/src/share/vm/c1/c1_LIR.cpp	Mon Mar 27 11:31:27 2017 -0700
+++ b/src/share/vm/c1/c1_LIR.cpp	Thu Apr 13 08:28:56 2017 -0700
@@ -1516,6 +1516,17 @@
   append(c);
 }
 
+void LIR_List::null_check(LIR_Opr opr, CodeEmitInfo* info, bool deoptimize_on_null) {
+  if (deoptimize_on_null) {
+    // Emit an explicit null check and deoptimize if opr is null
+    CodeStub* deopt = new DeoptimizeStub(info);
+    cmp(lir_cond_equal, opr, LIR_OprFact::oopConst(NULL));
+    branch(lir_cond_equal, T_OBJECT, deopt);
+  } else {
+    // Emit an implicit null check
+    append(new LIR_Op1(lir_null_check, opr, info));
+  }
+}
 
 void LIR_List::cas_long(LIR_Opr addr, LIR_Opr cmp_value, LIR_Opr new_value,
                         LIR_Opr t1, LIR_Opr t2, LIR_Opr result) {
--- a/src/share/vm/c1/c1_LIR.hpp	Mon Mar 27 11:31:27 2017 -0700
+++ b/src/share/vm/c1/c1_LIR.hpp	Thu Apr 13 08:28:56 2017 -0700
@@ -2153,7 +2153,7 @@
   void   pack64(LIR_Opr src, LIR_Opr dst) { append(new LIR_Op1(lir_pack64,   src, dst, T_LONG, lir_patch_none, NULL)); }
   void unpack64(LIR_Opr src, LIR_Opr dst) { append(new LIR_Op1(lir_unpack64, src, dst, T_LONG, lir_patch_none, NULL)); }
 
-  void null_check(LIR_Opr opr, CodeEmitInfo* info)         { append(new LIR_Op1(lir_null_check, opr, info)); }
+  void null_check(LIR_Opr opr, CodeEmitInfo* info, bool deoptimize_on_null = false);
   void throw_exception(LIR_Opr exceptionPC, LIR_Opr exceptionOop, CodeEmitInfo* info) {
     append(new LIR_Op2(lir_throw, exceptionPC, exceptionOop, LIR_OprFact::illegalOpr, info));
   }
--- a/src/share/vm/c1/c1_LIRGenerator.cpp	Mon Mar 27 11:31:27 2017 -0700
+++ b/src/share/vm/c1/c1_LIRGenerator.cpp	Thu Apr 13 08:28:56 2017 -0700
@@ -1700,8 +1700,10 @@
   if (x->needs_null_check() &&
       (needs_patching ||
        MacroAssembler::needs_explicit_null_check(x->offset()))) {
-    // emit an explicit null check because the offset is too large
-    __ null_check(object.result(), new CodeEmitInfo(info));
+    // Emit an explicit null check because the offset is too large.
+    // If the class is not loaded and the object is NULL, we need to deoptimize to throw a
+    // NoClassDefFoundError in the interpreter instead of an implicit NPE from compiled code.
+    __ null_check(object.result(), new CodeEmitInfo(info), /* deoptimize */ needs_patching);
   }
 
   LIR_Address* address;
@@ -1785,8 +1787,10 @@
       obj = new_register(T_OBJECT);
       __ move(LIR_OprFact::oopConst(NULL), obj);
     }
-    // emit an explicit null check because the offset is too large
-    __ null_check(obj, new CodeEmitInfo(info));
+    // Emit an explicit null check because the offset is too large.
+    // If the class is not loaded and the object is NULL, we need to deoptimize to throw a
+    // NoClassDefFoundError in the interpreter instead of an implicit NPE from compiled code.
+    __ null_check(obj, new CodeEmitInfo(info), /* deoptimize */ needs_patching);
   }
 
   LIR_Opr reg = rlock_result(x, field_type);
--- a/src/share/vm/code/nmethod.cpp	Mon Mar 27 11:31:27 2017 -0700
+++ b/src/share/vm/code/nmethod.cpp	Thu Apr 13 08:28:56 2017 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2017, 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
@@ -254,7 +254,8 @@
 
 
 address ExceptionCache::test_address(address addr) {
-  for (int i=0; i<count(); i++) {
+  int limit = count();
+  for (int i = 0; i < limit; i++) {
     if (pc_at(i) == addr) {
       return handler_at(i);
     }
@@ -265,9 +266,11 @@
 
 bool ExceptionCache::add_address_and_handler(address addr, address handler) {
   if (test_address(addr) == handler) return true;
-  if (count() < cache_size) {
-    set_pc_at(count(),addr);
-    set_handler_at(count(), handler);
+
+  int index = count();
+  if (index < cache_size) {
+    set_pc_at(index, addr);
+    set_handler_at(index, handler);
     increment_count();
     return true;
   }
@@ -380,10 +383,11 @@
   assert(new_entry != NULL,"Must be non null");
   assert(new_entry->next() == NULL, "Must be null");
 
-  if (exception_cache() != NULL) {
-    new_entry->set_next(exception_cache());
+  ExceptionCache *ec = exception_cache();
+  if (ec != NULL) {
+    new_entry->set_next(ec);
   }
-  set_exception_cache(new_entry);
+  release_set_exception_cache(new_entry);
 }
 
 void nmethod::clean_exception_cache(BoolObjectClosure* is_alive) {
--- a/src/share/vm/code/nmethod.hpp	Mon Mar 27 11:31:27 2017 -0700
+++ b/src/share/vm/code/nmethod.hpp	Thu Apr 13 08:28:56 2017 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2017, 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
@@ -39,15 +39,16 @@
   Klass*   _exception_type;
   address  _pc[cache_size];
   address  _handler[cache_size];
-  int      _count;
+  volatile int _count;
   ExceptionCache* _next;
 
   address pc_at(int index)                     { assert(index >= 0 && index < count(),""); return _pc[index]; }
   void    set_pc_at(int index, address a)      { assert(index >= 0 && index < cache_size,""); _pc[index] = a; }
   address handler_at(int index)                { assert(index >= 0 && index < count(),""); return _handler[index]; }
   void    set_handler_at(int index, address a) { assert(index >= 0 && index < cache_size,""); _handler[index] = a; }
-  int     count()                              { return _count; }
-  void    increment_count()                    { _count++; }
+  int     count()                              { return OrderAccess::load_acquire(&_count); }
+  // increment_count is only called under lock, but there may be concurrent readers.
+  void    increment_count()                    { OrderAccess::release_store(&_count, _count + 1); }
 
  public:
 
@@ -237,7 +238,7 @@
   // counter is decreased (by 1) while sweeping.
   int _hotness_counter;
 
-  ExceptionCache *_exception_cache;
+  ExceptionCache * volatile _exception_cache;
   PcDescCache     _pc_desc_cache;
 
   // These are used for compiled synchronized native methods to
@@ -433,7 +434,7 @@
 
   // flag accessing and manipulation
   bool  is_in_use() const                         { return _state == in_use; }
-  bool  is_alive() const                          { return _state == in_use || _state == not_entrant; }
+  bool  is_alive() const                          { unsigned char s = _state; return s == in_use || s == not_entrant; }
   bool  is_not_entrant() const                    { return _state == not_entrant; }
   bool  is_zombie() const                         { return _state == zombie; }
   bool  is_unloaded() const                       { return _state == unloaded;   }
@@ -555,8 +556,10 @@
   void  set_stack_traversal_mark(long l)          { _stack_traversal_mark = l; }
 
   // Exception cache support
+  // Note: _exception_cache may be read concurrently. We rely on memory_order_consume here.
   ExceptionCache* exception_cache() const         { return _exception_cache; }
   void set_exception_cache(ExceptionCache *ec)    { _exception_cache = ec; }
+  void release_set_exception_cache(ExceptionCache *ec) { OrderAccess::release_store_ptr(&_exception_cache, ec); }
   address handler_for_exception_and_pc(Handle exception, address pc);
   void add_handler_for_exception_and_pc(Handle exception, address pc, address handler);
   void clean_exception_cache(BoolObjectClosure* is_alive);
--- a/src/share/vm/opto/connode.cpp	Mon Mar 27 11:31:27 2017 -0700
+++ b/src/share/vm/opto/connode.cpp	Thu Apr 13 08:28:56 2017 -0700
@@ -999,8 +999,7 @@
   }
 
 #ifdef _LP64
-  // Convert ConvI2L(AddI(x, y)) to AddL(ConvI2L(x), ConvI2L(y)) or
-  // ConvI2L(CastII(AddI(x, y))) to AddL(ConvI2L(CastII(x)), ConvI2L(CastII(y))),
+  // Convert ConvI2L(AddI(x, y)) to AddL(ConvI2L(x), ConvI2L(y))
   // but only if x and y have subranges that cannot cause 32-bit overflow,
   // under the assumption that x+y is in my own subrange this->type().
 
@@ -1024,13 +1023,6 @@
 
   Node* z = in(1);
   int op = z->Opcode();
-  Node* ctrl = NULL;
-  if (op == Op_CastII && z->as_CastII()->has_range_check()) {
-    // Skip CastII node but save control dependency
-    ctrl = z->in(0);
-    z = z->in(1);
-    op = z->Opcode();
-  }
   if (op == Op_AddI || op == Op_SubI) {
     Node* x = z->in(1);
     Node* y = z->in(2);
@@ -1090,8 +1082,8 @@
     }
     assert(rxlo == (int)rxlo && rxhi == (int)rxhi, "x should not overflow");
     assert(rylo == (int)rylo && ryhi == (int)ryhi, "y should not overflow");
-    Node* cx = phase->C->constrained_convI2L(phase, x, TypeInt::make(rxlo, rxhi, widen), ctrl);
-    Node* cy = phase->C->constrained_convI2L(phase, y, TypeInt::make(rylo, ryhi, widen), ctrl);
+    Node* cx = phase->C->constrained_convI2L(phase, x, TypeInt::make(rxlo, rxhi, widen), NULL);
+    Node* cy = phase->C->constrained_convI2L(phase, y, TypeInt::make(rylo, ryhi, widen), NULL);
     switch (op) {
     case Op_AddI:  return new (phase->C) AddLNode(cx, cy);
     case Op_SubI:  return new (phase->C) SubLNode(cx, cy);
--- a/src/share/vm/prims/jni.cpp	Mon Mar 27 11:31:27 2017 -0700
+++ b/src/share/vm/prims/jni.cpp	Thu Apr 13 08:28:56 2017 -0700
@@ -5129,6 +5129,7 @@
     run_unit_test(TestKlass_test());
     run_unit_test(Test_linked_list());
     run_unit_test(TestChunkedList_test());
+    run_unit_test(ObjectMonitor::sanity_checks());
 #if INCLUDE_VM_STRUCTS
     run_unit_test(VMStructs::test());
 #endif
--- a/src/share/vm/runtime/objectMonitor.cpp	Mon Mar 27 11:31:27 2017 -0700
+++ b/src/share/vm/runtime/objectMonitor.cpp	Thu Apr 13 08:28:56 2017 -0700
@@ -2529,6 +2529,10 @@
   SETKNOB(FastHSSEC) ;
   #undef SETKNOB
 
+  if (Knob_Verbose) {
+    sanity_checks();
+  }
+
   if (os::is_MP()) {
      BackOffMask = (1 << Knob_SpinBackOff) - 1 ;
      if (Knob_ReportSettings) ::printf ("BackOffMask=%X\n", BackOffMask) ;
@@ -2549,6 +2553,66 @@
   InitDone = 1 ;
 }
 
+void ObjectMonitor::sanity_checks() {
+  int error_cnt = 0;
+  int warning_cnt = 0;
+  bool verbose = Knob_Verbose != 0 NOT_PRODUCT(|| VerboseInternalVMTests);
+
+  if (verbose) {
+    tty->print_cr("INFO: sizeof(ObjectMonitor)=" SIZE_FORMAT,
+                  sizeof(ObjectMonitor));
+  }
+
+  uint cache_line_size = VM_Version::L1_data_cache_line_size();
+  if (verbose) {
+    tty->print_cr("INFO: L1_data_cache_line_size=%u", cache_line_size);
+  }
+
+  ObjectMonitor dummy;
+  u_char *addr_begin  = (u_char*)&dummy;
+  u_char *addr_header = (u_char*)&dummy._header;
+  u_char *addr_owner  = (u_char*)&dummy._owner;
+
+  uint offset_header = (uint)(addr_header - addr_begin);
+  if (verbose) tty->print_cr("INFO: offset(_header)=%u", offset_header);
+
+  uint offset_owner = (uint)(addr_owner - addr_begin);
+  if (verbose) tty->print_cr("INFO: offset(_owner)=%u", offset_owner);
+
+  if ((uint)(addr_header - addr_begin) != 0) {
+    tty->print_cr("ERROR: offset(_header) must be zero (0).");
+    error_cnt++;
+  }
+
+  if (cache_line_size != 0) {
+    // We were able to determine the L1 data cache line size so
+    // do some cache line specific sanity checks
+
+    if ((offset_owner - offset_header) < cache_line_size) {
+      tty->print_cr("WARNING: the _header and _owner fields are closer "
+                    "than a cache line which permits false sharing.");
+      warning_cnt++;
+    }
+
+    if ((sizeof(ObjectMonitor) % cache_line_size) != 0) {
+      tty->print_cr("WARNING: ObjectMonitor size is not a multiple of "
+                    "a cache line which permits false sharing.");
+      warning_cnt++;
+    }
+  }
+
+  ObjectSynchronizer::sanity_checks(verbose, cache_line_size, &error_cnt,
+                                    &warning_cnt);
+
+  if (verbose || error_cnt != 0 || warning_cnt != 0) {
+    tty->print_cr("INFO: error_cnt=%d", error_cnt);
+    tty->print_cr("INFO: warning_cnt=%d", warning_cnt);
+  }
+
+  guarantee(error_cnt == 0,
+            "Fatal error(s) found in ObjectMonitor::sanity_checks()");
+}
+
 #ifndef PRODUCT
 void ObjectMonitor::verify() {
 }
--- a/src/share/vm/runtime/objectMonitor.hpp	Mon Mar 27 11:31:27 2017 -0700
+++ b/src/share/vm/runtime/objectMonitor.hpp	Thu Apr 13 08:28:56 2017 -0700
@@ -189,6 +189,8 @@
   bool      check(TRAPS);       // true if the thread owns the monitor.
   void      check_slow(TRAPS);
   void      clear();
+  static void sanity_checks();  // public for -XX:+ExecuteInternalVMTests
+                                // in PRODUCT for -XX:SyncKnobs=Verbose=1
 #ifndef PRODUCT
   void      verify();
   void      print();
@@ -234,8 +236,6 @@
 
   // WARNING: this must be the very first word of ObjectMonitor
   // This means this class can't use any virtual member functions.
-  // TODO-FIXME: assert that offsetof(_header) is 0 or get rid of the
-  // implicit 0 offset in emitted code.
 
   volatile markOop   _header;       // displaced object header word - mark
   void*     volatile _object;       // backward object pointer - strong root
--- a/src/share/vm/runtime/synchronizer.cpp	Mon Mar 27 11:31:27 2017 -0700
+++ b/src/share/vm/runtime/synchronizer.cpp	Thu Apr 13 08:28:56 2017 -0700
@@ -437,19 +437,22 @@
 // Hash Code handling
 //
 // Performance concern:
-// OrderAccess::storestore() calls release() which STs 0 into the global volatile
-// OrderAccess::Dummy variable.  This store is unnecessary for correctness.
-// Many threads STing into a common location causes considerable cache migration
-// or "sloshing" on large SMP system.  As such, I avoid using OrderAccess::storestore()
-// until it's repaired.  In some cases OrderAccess::fence() -- which incurs local
-// latency on the executing processor -- is a better choice as it scales on SMP
-// systems.  See http://blogs.sun.com/dave/entry/biased_locking_in_hotspot for a
-// discussion of coherency costs.  Note that all our current reference platforms
-// provide strong ST-ST order, so the issue is moot on IA32, x64, and SPARC.
+// OrderAccess::storestore() calls release() which at one time stored 0
+// into the global volatile OrderAccess::dummy variable. This store was
+// unnecessary for correctness. Many threads storing into a common location
+// causes considerable cache migration or "sloshing" on large SMP systems.
+// As such, I avoided using OrderAccess::storestore(). In some cases
+// OrderAccess::fence() -- which incurs local latency on the executing
+// processor -- is a better choice as it scales on SMP systems.
+//
+// See http://blogs.oracle.com/dave/entry/biased_locking_in_hotspot for
+// a discussion of coherency costs. Note that all our current reference
+// platforms provide strong ST-ST order, so the issue is moot on IA32,
+// x64, and SPARC.
 //
 // As a general policy we use "volatile" to control compiler-based reordering
-// and explicit fences (barriers) to control for architectural reordering performed
-// by the CPU(s) or platform.
+// and explicit fences (barriers) to control for architectural reordering
+// performed by the CPU(s) or platform.
 
 struct SharedGlobals {
     // These are highly shared mostly-read variables.
@@ -1636,7 +1639,55 @@
 }
 
 //------------------------------------------------------------------------------
-// Non-product code
+// Debugging code
+
+void ObjectSynchronizer::sanity_checks(const bool verbose,
+                                       const uint cache_line_size,
+                                       int *error_cnt_ptr,
+                                       int *warning_cnt_ptr) {
+  u_char *addr_begin      = (u_char*)&GVars;
+  u_char *addr_stwRandom  = (u_char*)&GVars.stwRandom;
+  u_char *addr_hcSequence = (u_char*)&GVars.hcSequence;
+
+  if (verbose) {
+    tty->print_cr("INFO: sizeof(SharedGlobals)=" SIZE_FORMAT,
+                  sizeof(SharedGlobals));
+  }
+
+  uint offset_stwRandom = (uint)(addr_stwRandom - addr_begin);
+  if (verbose) tty->print_cr("INFO: offset(stwRandom)=%u", offset_stwRandom);
+
+  uint offset_hcSequence = (uint)(addr_hcSequence - addr_begin);
+  if (verbose) {
+    tty->print_cr("INFO: offset(_hcSequence)=%u", offset_hcSequence);
+  }
+
+  if (cache_line_size != 0) {
+    // We were able to determine the L1 data cache line size so
+    // do some cache line specific sanity checks
+
+    if (offset_stwRandom < cache_line_size) {
+      tty->print_cr("WARNING: the SharedGlobals.stwRandom field is closer "
+                    "to the struct beginning than a cache line which permits "
+                    "false sharing.");
+      (*warning_cnt_ptr)++;
+    }
+
+    if ((offset_hcSequence - offset_stwRandom) < cache_line_size) {
+      tty->print_cr("WARNING: the SharedGlobals.stwRandom and "
+                    "SharedGlobals.hcSequence fields are closer than a cache "
+                    "line which permits false sharing.");
+      (*warning_cnt_ptr)++;
+    }
+
+    if ((sizeof(SharedGlobals) - offset_hcSequence) < cache_line_size) {
+      tty->print_cr("WARNING: the SharedGlobals.hcSequence field is closer "
+                    "to the struct end than a cache line which permits false "
+                    "sharing.");
+      (*warning_cnt_ptr)++;
+    }
+  }
+}
 
 #ifndef PRODUCT
 
--- a/src/share/vm/runtime/synchronizer.hpp	Mon Mar 27 11:31:27 2017 -0700
+++ b/src/share/vm/runtime/synchronizer.hpp	Thu Apr 13 08:28:56 2017 -0700
@@ -121,6 +121,9 @@
   static void oops_do(OopClosure* f);
 
   // debugging
+  static void sanity_checks(const bool verbose,
+                            const unsigned int cache_line_size,
+                            int *error_cnt_ptr, int *warning_cnt_ptr);
   static void verify() PRODUCT_RETURN;
   static int  verify_objmon_isinpool(ObjectMonitor *addr) PRODUCT_RETURN0;
 
--- a/src/share/vm/runtime/vmStructs.cpp	Mon Mar 27 11:31:27 2017 -0700
+++ b/src/share/vm/runtime/vmStructs.cpp	Thu Apr 13 08:28:56 2017 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2000, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2017, 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
@@ -879,7 +879,7 @@
   nonstatic_field(nmethod,             _stack_traversal_mark,                         long)                                  \
   nonstatic_field(nmethod,             _compile_id,                                   int)                                   \
   nonstatic_field(nmethod,             _comp_level,                                   int)                                   \
-  nonstatic_field(nmethod,             _exception_cache,                              ExceptionCache*)                       \
+  volatile_nonstatic_field(nmethod,    _exception_cache,                              ExceptionCache*)                       \
   nonstatic_field(nmethod,             _marked_for_deoptimization,                    bool)                                  \
                                                                                                                              \
   unchecked_c2_static_field(Deoptimization,         _trap_reason_name,                   void*)                              \
--- a/src/share/vm/runtime/vm_version.cpp	Mon Mar 27 11:31:27 2017 -0700
+++ b/src/share/vm/runtime/vm_version.cpp	Thu Apr 13 08:28:56 2017 -0700
@@ -50,6 +50,7 @@
 bool Abstract_VM_Version::_supports_atomic_getadd4 = false;
 bool Abstract_VM_Version::_supports_atomic_getadd8 = false;
 unsigned int Abstract_VM_Version::_logical_processors_per_package = 1U;
+unsigned int Abstract_VM_Version::_L1_data_cache_line_size = 0;
 int Abstract_VM_Version::_reserve_for_allocation_prefetch = 0;
 
 #ifndef HOTSPOT_RELEASE_VERSION
--- a/src/share/vm/runtime/vm_version.hpp	Mon Mar 27 11:31:27 2017 -0700
+++ b/src/share/vm/runtime/vm_version.hpp	Thu Apr 13 08:28:56 2017 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2014, 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
@@ -42,6 +42,7 @@
   static bool         _supports_atomic_getadd4;
   static bool         _supports_atomic_getadd8;
   static unsigned int _logical_processors_per_package;
+  static unsigned int _L1_data_cache_line_size;
   static int          _vm_major_version;
   static int          _vm_minor_version;
   static int          _vm_build_number;
@@ -114,6 +115,10 @@
     return _logical_processors_per_package;
   }
 
+  static unsigned int L1_data_cache_line_size() {
+    return _L1_data_cache_line_size;
+  }
+
   // Need a space at the end of TLAB for prefetch instructions
   // which may fault when accessing memory outside of heap.
   static int reserve_for_allocation_prefetch() {
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/compiler/c1/TestUnresolvedField.jasm	Thu Apr 13 08:28:56 2017 -0700
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2017, 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
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+public class compiler/c1/TestUnresolvedField version 52:0 {
+    public static Method testGetField:"()V" stack 1 locals 1 {
+        aconst_null;
+        getfield Field T.f:I; // T does not exist
+        return;
+    }
+
+    public static Method testPutField:"()V" stack 2 locals 1 {
+        aconst_null;
+        iconst_0;
+        putfield Field T.f:I; // T does not exist
+        return;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/compiler/c1/TestUnresolvedFieldMain.java	Thu Apr 13 08:28:56 2017 -0700
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 2017, 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
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 8173373
+ * @compile TestUnresolvedField.jasm
+ * @run main/othervm -XX:TieredStopAtLevel=1 -Xcomp
+ *                   -XX:CompileCommand=compileonly,compiler.c1.TestUnresolvedField::test*
+ *                   compiler.c1.TestUnresolvedFieldMain
+ */
+
+package compiler.c1;
+
+public class TestUnresolvedFieldMain {
+    public static void main(String[] args) {
+        try {
+          TestUnresolvedField.testGetField();
+        } catch (java.lang.NoClassDefFoundError error) {
+          // Expected
+        }
+        try {
+          TestUnresolvedField.testPutField();
+        } catch (java.lang.NoClassDefFoundError error) {
+          // Expected
+        }
+    }
+}
--- a/test/compiler/loopopts/TestLoopPeeling.java	Mon Mar 27 11:31:27 2017 -0700
+++ b/test/compiler/loopopts/TestLoopPeeling.java	Thu Apr 13 08:28:56 2017 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2017, 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,10 +23,16 @@
 
 /*
  * @test
- * @bug 8078262
+ * @bug 8078262 8177095
  * @summary Tests correct dominator information after loop peeling.
- * @run main/othervm -Xcomp -XX:CompileCommand=compileonly,TestLoopPeeling::test* TestLoopPeeling
+ *
+ * @run main/othervm -Xcomp
+ *      -XX:CompileCommand=compileonly,compiler.loopopts.TestLoopPeeling::test*
+ *      compiler.loopopts.TestLoopPeeling
  */
+
+package compiler.loopopts;
+
 public class TestLoopPeeling {
 
     public int[] array = new int[100];
@@ -34,14 +40,16 @@
     public static void main(String args[]) {
         TestLoopPeeling test = new TestLoopPeeling();
         try {
-            test.testArrayAccess(0, 1);
+            test.testArrayAccess1(0, 1);
+            test.testArrayAccess2(0);
+            test.testArrayAccess3(0, false);
             test.testArrayAllocation(0, 1);
         } catch (Exception e) {
             // Ignore exceptions
         }
     }
 
-    public void testArrayAccess(int index, int inc) {
+    public void testArrayAccess1(int index, int inc) {
         int storeIndex = -1;
 
         for (; index < 10; index += inc) {
@@ -57,7 +65,7 @@
 
             if (index == 42) {
                 // This store and the corresponding range check are moved out of the
-                // loop and both used after old loop and the peeled iteration exit.
+                // loop and both used after main loop and the peeled iteration exit.
                 // For the peeled iteration, storeIndex is always -1 and the ConvI2L
                 // is replaced by TOP. However, the range check is not folded because
                 // we don't do the split if optimization in PhaseIdealLoop2.
@@ -71,6 +79,44 @@
         }
     }
 
+    public int testArrayAccess2(int index) {
+        // Load1 and the corresponding range check are moved out of the loop
+        // and both are used after the main loop and the peeled iteration exit.
+        // For the peeled iteration, storeIndex is always Integer.MIN_VALUE and
+        // for the main loop it is 0. Hence, the merging phi has type int:<=0.
+        // Load1 reads the array at index ConvI2L(CastII(AddI(storeIndex, -1)))
+        // where the CastII is range check dependent and has type int:>=0.
+        // The CastII gets pushed through the AddI and its type is changed to int:>=1
+        // which does not overlap with the input type of storeIndex (int:<=0).
+        // The CastII is replaced by TOP causing a cascade of other eliminations.
+        // Since the control path through the range check CmpU(AddI(storeIndex, -1))
+        // is not eliminated, the graph is in a corrupted state. We fail once we merge
+        // with the result of Load2 because we get data from a non-dominating region.
+        int storeIndex = Integer.MIN_VALUE;
+        for (; index < 10; ++index) {
+            if (index == 42) {
+                return array[storeIndex-1]; // Load1
+            }
+            storeIndex = 0;
+        }
+        return array[42]; // Load2
+    }
+
+    public int testArrayAccess3(int index, boolean b) {
+        // Same as testArrayAccess2 but manifests as crash in register allocator.
+        int storeIndex = Integer.MIN_VALUE;
+        for (; index < 10; ++index) {
+            if (b) {
+                return 0;
+            }
+            if (index == 42) {
+                return array[storeIndex-1]; // Load1
+            }
+            storeIndex = 0;
+        }
+        return array[42]; // Load2
+    }
+
     public byte[] testArrayAllocation(int index, int inc) {
         int allocationCount = -1;
         byte[] result;
@@ -82,7 +128,7 @@
 
             if (index == 42) {
                 // This allocation and the corresponding size check are moved out of the
-                // loop and both used after old loop and the peeled iteration exit.
+                // loop and both used after main loop and the peeled iteration exit.
                 // For the peeled iteration, allocationCount is always -1 and the ConvI2L
                 // is replaced by TOP. However, the size check is not folded because
                 // we don't do the split if optimization in PhaseIdealLoop2.