changeset 8436:b1b140f0c504

Merge
author asaha
date Thu, 16 Feb 2017 13:21:41 -0800
parents e49557628945 (current diff) c468dc338392 (diff)
children 268b63233d3e
files .hgtags
diffstat 19 files changed, 282 insertions(+), 49 deletions(-) [+]
line wrap: on
line diff
--- a/.hgtags	Mon Jan 23 17:09:40 2017 -0800
+++ b/.hgtags	Thu Feb 16 13:21:41 2017 -0800
@@ -931,6 +931,8 @@
 b28d012a24cab8f4ceeee0c9d3252969757423ed jdk8u112-b15
 e134dc1879b72124e478be01680b0646a2fbf585 jdk8u112-b16
 87440ed4e1de7753a436f957d35555d8b4e26f1d jdk8u112-b31
+ba25f5833a128b8062e597f794efda26b30f095d jdk8u112-b32
+919ffdca10c2721ee0f6f233e704709174556510 jdk8u112-b33
 3b0e5f01891f5ebbf67797b1aae786196f1bb4f6 jdk8u121-b00
 251a2493b1857f2ff4f11eab2dfd8b2fe8ed441b jdk8u121-b01
 70c4a50f576a01ec975d0a02b3642ee33db39ed8 jdk8u121-b02
@@ -945,10 +947,14 @@
 11f91811e4d7e5ddfaf938dcf386ec8fe5bf7b7c jdk8u121-b11
 b132b08b28bf23a26329928cf6b4ffda5857f4d3 jdk8u121-b12
 90f94521c3515e5f27af0ab9b31d036e88bb322a jdk8u121-b13
+351bf1d4ff9a41137f91e2ec97ec59ed29a38d8b jdk8u121-b31
+41daac438a2ac5a80755dc3de88b76e4ac66750a jdk8u121-b32
 c0a1ba0df20fda10ddb8599e888eb56ad98b3874 jdk8u131-b00
 0b85ccd6240991e1a501602ff5addec6b88ae0af jdk8u131-b01
 ef90c721a4e59b01ca36f25619010a1afe9ed4d5 jdk8u131-b02
 0ca47d0811b01ecf8651b6045a1e33a4a9bed0ee jdk8u131-b03
 dab1d597165207e14b6886b1823c1e990bc776a3 jdk8u131-b04
+c965fc1aa840a0903709ad69aa0e2100330ccd84 jdk8u131-b05
+6e4cfbc7534f83902692132efb61683528c04a59 jdk8u131-b06
 692bc6b674dcab72453de08ee9da0856a7e41c0f jdk8u141-b00
 2d5100bddeb80cf767485b787fc3051311e3d7b9 jdk8u151-b00
--- a/src/cpu/sparc/vm/macroAssembler_sparc.cpp	Mon Jan 23 17:09:40 2017 -0800
+++ b/src/cpu/sparc/vm/macroAssembler_sparc.cpp	Thu Feb 16 13:21:41 2017 -0800
@@ -4261,6 +4261,7 @@
   assert(UseBlockZeroing && VM_Version::has_block_zeroing(), "only works with BIS zeroing");
   Register end = count;
   int cache_line_size = VM_Version::prefetch_data_size();
+  assert(cache_line_size > 0, "cache line size should be known for this code");
   // Minimum count when BIS zeroing can be used since
   // it needs membar which is expensive.
   int block_zero_size  = MAX2(cache_line_size*3, (int)BlockZeroingLowLimit);
--- a/src/cpu/sparc/vm/vm_version_sparc.cpp	Mon Jan 23 17:09:40 2017 -0800
+++ b/src/cpu/sparc/vm/vm_version_sparc.cpp	Thu Feb 16 13:21:41 2017 -0800
@@ -74,7 +74,7 @@
     AllocatePrefetchDistance = AllocatePrefetchStepSize;
   }
 
-  if (AllocatePrefetchStyle == 3 && !has_blk_init()) {
+  if (AllocatePrefetchStyle == 3 && (!has_blk_init() || cache_line_size <= 0)) {
     warning("BIS instructions are not available on this CPU");
     FLAG_SET_DEFAULT(AllocatePrefetchStyle, 1);
   }
@@ -138,7 +138,7 @@
       FLAG_SET_DEFAULT(InteriorEntryAlignment, 4);
     }
     if (is_niagara_plus()) {
-      if (has_blk_init() && UseTLAB &&
+      if (has_blk_init() && (cache_line_size > 0) && UseTLAB &&
           FLAG_IS_DEFAULT(AllocatePrefetchInstr)) {
         // Use BIS instruction for TLAB allocation prefetch.
         FLAG_SET_ERGO(intx, AllocatePrefetchInstr, 1);
--- a/src/os/linux/vm/globals_linux.hpp	Mon Jan 23 17:09:40 2017 -0800
+++ b/src/os/linux/vm/globals_linux.hpp	Thu Feb 16 13:21:41 2017 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2005, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2016, 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
@@ -47,7 +47,10 @@
           "Load DLLs with executable-stack attribute in the VM Thread") \
                                                                         \
   product(bool, UseSHM, false,                                          \
-          "Use SYSV shared memory for large pages")
+          "Use SYSV shared memory for large pages")                     \
+                                                                        \
+  diagnostic(bool, PrintActiveCpus, false,                              \
+          "Print the number of CPUs detected in os::active_processor_count")
 
 //
 // Defines Linux-specific default values. The flags are available on all
--- a/src/os/linux/vm/os_linux.cpp	Mon Jan 23 17:09:40 2017 -0800
+++ b/src/os/linux/vm/os_linux.cpp	Thu Feb 16 13:21:41 2017 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1999, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 2016, 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
@@ -104,6 +104,14 @@
 
 PRAGMA_FORMAT_MUTE_WARNINGS_FOR_GCC
 
+#ifndef _GNU_SOURCE
+  #define _GNU_SOURCE
+  #include <sched.h>
+  #undef _GNU_SOURCE
+#else
+  #include <sched.h>
+#endif
+
 // if RUSAGE_THREAD for getrusage() has not been defined, do it here. The code calling
 // getrusage() is prepared to handle the associated failure.
 #ifndef RUSAGE_THREAD
@@ -1067,29 +1075,30 @@
 
 // Locate initial thread stack. This special handling of initial thread stack
 // is needed because pthread_getattr_np() on most (all?) Linux distros returns
-// bogus value for initial thread.
+// bogus value for the primordial process thread. While the launcher has created
+// the VM in a new thread since JDK 6, we still have to allow for the use of the
+// JNI invocation API from a primordial thread.
 void os::Linux::capture_initial_stack(size_t max_size) {
-  // stack size is the easy part, get it from RLIMIT_STACK
-  size_t stack_size;
+
+  // max_size is either 0 (which means accept OS default for thread stacks) or
+  // a user-specified value known to be at least the minimum needed. If we
+  // are actually on the primordial thread we can make it appear that we have a
+  // smaller max_size stack by inserting the guard pages at that location. But we
+  // cannot do anything to emulate a larger stack than what has been provided by
+  // the OS or threading library. In fact if we try to use a stack greater than
+  // what is set by rlimit then we will crash the hosting process.
+
+  // Maximum stack size is the easy part, get it from RLIMIT_STACK.
+  // If this is "unlimited" then it will be a huge value.
   struct rlimit rlim;
   getrlimit(RLIMIT_STACK, &rlim);
-  stack_size = rlim.rlim_cur;
+  size_t stack_size = rlim.rlim_cur;
 
   // 6308388: a bug in ld.so will relocate its own .data section to the
   //   lower end of primordial stack; reduce ulimit -s value a little bit
   //   so we won't install guard page on ld.so's data section.
   stack_size -= 2 * page_size();
 
-  // 4441425: avoid crash with "unlimited" stack size on SuSE 7.1 or Redhat
-  //   7.1, in both cases we will get 2G in return value.
-  // 4466587: glibc 2.2.x compiled w/o "--enable-kernel=2.4.0" (RH 7.0,
-  //   SuSE 7.2, Debian) can not handle alternate signal stack correctly
-  //   for initial thread if its stack size exceeds 6M. Cap it at 2M,
-  //   in case other parts in glibc still assumes 2M max stack size.
-  // FIXME: alt signal stack is gone, maybe we can relax this constraint?
-  // Problem still exists RH7.2 (IA64 anyway) but 2MB is a little small
-  if (stack_size > 2 * K * K IA64_ONLY(*2))
-      stack_size = 2 * K * K IA64_ONLY(*2);
   // Try to figure out where the stack base (top) is. This is harder.
   //
   // When an application is started, glibc saves the initial stack pointer in
@@ -1249,14 +1258,18 @@
   // stack_top could be partially down the page so align it
   stack_top = align_size_up(stack_top, page_size());
 
-  if (max_size && stack_size > max_size) {
-     _initial_thread_stack_size = max_size;
+  // Allowed stack value is minimum of max_size and what we derived from rlimit
+  if (max_size > 0) {
+    _initial_thread_stack_size = MIN2(max_size, stack_size);
   } else {
-     _initial_thread_stack_size = stack_size;
+    // Accept the rlimit max, but if stack is unlimited then it will be huge, so
+    // clamp it at 8MB as we do on Solaris
+    _initial_thread_stack_size = MIN2(stack_size, 8*M);
   }
 
   _initial_thread_stack_size = align_size_down(_initial_thread_stack_size, page_size());
   _initial_thread_stack_bottom = (address)stack_top - _initial_thread_stack_size;
+  assert(_initial_thread_stack_bottom < (address)stack_top, "overflow!");
 }
 
 ////////////////////////////////////////////////////////////////////////////////
@@ -5016,12 +5029,42 @@
   }
 };
 
+static int os_cpu_count(const cpu_set_t* cpus) {
+  int count = 0;
+  // only look up to the number of configured processors
+  for (int i = 0; i < os::processor_count(); i++) {
+    if (CPU_ISSET(i, cpus)) {
+      count++;
+    }
+  }
+  return count;
+}
+
+// Get the current number of available processors for this process.
+// This value can change at any time during a process's lifetime.
+// sched_getaffinity gives an accurate answer as it accounts for cpusets.
+// If anything goes wrong we fallback to returning the number of online
+// processors - which can be greater than the number available to the process.
 int os::active_processor_count() {
-  // Linux doesn't yet have a (official) notion of processor sets,
-  // so just return the number of online processors.
-  int online_cpus = ::sysconf(_SC_NPROCESSORS_ONLN);
-  assert(online_cpus > 0 && online_cpus <= processor_count(), "sanity check");
-  return online_cpus;
+  cpu_set_t cpus;  // can represent at most 1024 (CPU_SETSIZE) processors
+  int cpus_size = sizeof(cpu_set_t);
+  int cpu_count = 0;
+
+  // pid 0 means the current thread - which we have to assume represents the process
+  if (sched_getaffinity(0, cpus_size, &cpus) == 0) {
+    cpu_count = os_cpu_count(&cpus);
+    if (PrintActiveCpus) {
+      tty->print_cr("active_processor_count: sched_getaffinity processor count: %d", cpu_count);
+    }
+  }
+  else {
+    cpu_count = ::sysconf(_SC_NPROCESSORS_ONLN);
+    warning("sched_getaffinity failed (%s)- using online processor count (%d) "
+            "which may exceed available processors", strerror(errno), cpu_count);
+  }
+
+  assert(cpu_count > 0 && cpu_count <= processor_count(), "sanity check");
+  return cpu_count;
 }
 
 void os::set_native_thread_name(const char *name) {
--- a/src/share/vm/classfile/systemDictionary.cpp	Mon Jan 23 17:09:40 2017 -0800
+++ b/src/share/vm/classfile/systemDictionary.cpp	Thu Feb 16 13:21:41 2017 -0800
@@ -1084,15 +1084,18 @@
                                                              THREAD);
 
   const char* pkg = "java/";
+  size_t pkglen = strlen(pkg);
   if (!HAS_PENDING_EXCEPTION &&
       !class_loader.is_null() &&
       parsed_name != NULL &&
-      !strncmp((const char*)parsed_name->bytes(), pkg, strlen(pkg))) {
+      parsed_name->utf8_length() >= (int)pkglen &&
+      !strncmp((const char*)parsed_name->bytes(), pkg, pkglen)) {
     // It is illegal to define classes in the "java." package from
     // JVM_DefineClass or jni_DefineClass unless you're the bootclassloader
     ResourceMark rm(THREAD);
     char* name = parsed_name->as_C_string();
     char* index = strrchr(name, '/');
+    assert(index != NULL, "must be");
     *index = '\0'; // chop to just the package name
     while ((index = strchr(name, '/')) != NULL) {
       *index = '.'; // replace '/' with '.' in package name
--- a/src/share/vm/gc_implementation/g1/concurrentMark.cpp	Mon Jan 23 17:09:40 2017 -0800
+++ b/src/share/vm/gc_implementation/g1/concurrentMark.cpp	Thu Feb 16 13:21:41 2017 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2001, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2001, 2016, 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
@@ -631,11 +631,10 @@
       double overall_cm_overhead =
         (double) MaxGCPauseMillis * marking_overhead /
         (double) GCPauseIntervalMillis;
-      double cpu_ratio = 1.0 / (double) os::processor_count();
+      double cpu_ratio = 1.0 / os::initial_active_processor_count();
       double marking_thread_num = ceil(overall_cm_overhead / cpu_ratio);
       double marking_task_overhead =
-        overall_cm_overhead / marking_thread_num *
-                                                (double) os::processor_count();
+        overall_cm_overhead / marking_thread_num * os::initial_active_processor_count();
       double sleep_factor =
                          (1.0 - marking_task_overhead) / marking_task_overhead;
 
--- a/src/share/vm/gc_implementation/g1/dirtyCardQueue.cpp	Mon Jan 23 17:09:40 2017 -0800
+++ b/src/share/vm/gc_implementation/g1/dirtyCardQueue.cpp	Thu Feb 16 13:21:41 2017 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2001, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2001, 2016, 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
@@ -80,7 +80,7 @@
 
 // Determines how many mutator threads can process the buffers in parallel.
 uint DirtyCardQueueSet::num_par_ids() {
-  return (uint)os::processor_count();
+  return (uint)os::initial_active_processor_count();
 }
 
 void DirtyCardQueueSet::initialize(CardTableEntryClosure* cl, Monitor* cbl_mon, Mutex* fl_lock,
--- a/src/share/vm/opto/cfgnode.hpp	Mon Jan 23 17:09:40 2017 -0800
+++ b/src/share/vm/opto/cfgnode.hpp	Thu Feb 16 13:21:41 2017 -0800
@@ -119,6 +119,9 @@
 // input in slot 0.
 class PhiNode : public TypeNode {
   const TypePtr* const _adr_type; // non-null only for Type::MEMORY nodes.
+  // The following fields are only used for data PhiNodes to indicate
+  // that the PhiNode represents the value of a known instance field.
+        int _inst_mem_id; // Instance memory id (node index of the memory Phi)
   const int _inst_id;     // Instance id of the memory slice.
   const int _inst_index;  // Alias index of the instance memory slice.
   // Array elements references have the same alias_idx but different offset.
@@ -138,11 +141,13 @@
   };
 
   PhiNode( Node *r, const Type *t, const TypePtr* at = NULL,
+           const int imid = -1,
            const int iid = TypeOopPtr::InstanceTop,
            const int iidx = Compile::AliasIdxTop,
            const int ioffs = Type::OffsetTop )
     : TypeNode(t,r->req()),
       _adr_type(at),
+      _inst_mem_id(imid),
       _inst_id(iid),
       _inst_index(iidx),
       _inst_offset(ioffs)
@@ -187,11 +192,14 @@
   virtual bool pinned() const { return in(0) != 0; }
   virtual const TypePtr *adr_type() const { verify_adr_type(true); return _adr_type; }
 
+  void  set_inst_mem_id(int inst_mem_id) { _inst_mem_id = inst_mem_id; }
+  const int inst_mem_id() const { return _inst_mem_id; }
   const int inst_id()     const { return _inst_id; }
   const int inst_index()  const { return _inst_index; }
   const int inst_offset() const { return _inst_offset; }
-  bool is_same_inst_field(const Type* tp, int id, int index, int offset) {
+  bool is_same_inst_field(const Type* tp, int mem_id, int id, int index, int offset) {
     return type()->basic_type() == tp->basic_type() &&
+           inst_mem_id() == mem_id &&
            inst_id()     == id     &&
            inst_index()  == index  &&
            inst_offset() == offset &&
--- a/src/share/vm/opto/macro.cpp	Mon Jan 23 17:09:40 2017 -0800
+++ b/src/share/vm/opto/macro.cpp	Thu Feb 16 13:21:41 2017 -0800
@@ -401,7 +401,7 @@
   for (DUIterator_Fast kmax, k = region->fast_outs(kmax); k < kmax; k++) {
     Node* phi = region->fast_out(k);
     if (phi->is_Phi() && phi != mem &&
-        phi->as_Phi()->is_same_inst_field(phi_type, instance_id, alias_idx, offset)) {
+        phi->as_Phi()->is_same_inst_field(phi_type, (int)mem->_idx, instance_id, alias_idx, offset)) {
       return phi;
     }
   }
@@ -420,7 +420,7 @@
   GrowableArray <Node *> values(length, length, NULL, false);
 
   // create a new Phi for the value
-  PhiNode *phi = new (C) PhiNode(mem->in(0), phi_type, NULL, instance_id, alias_idx, offset);
+  PhiNode *phi = new (C) PhiNode(mem->in(0), phi_type, NULL, mem->_idx, instance_id, alias_idx, offset);
   transform_later(phi);
   value_phis->push(phi, mem->_idx);
 
--- a/src/share/vm/opto/memnode.cpp	Mon Jan 23 17:09:40 2017 -0800
+++ b/src/share/vm/opto/memnode.cpp	Thu Feb 16 13:21:41 2017 -0800
@@ -1155,7 +1155,7 @@
     for (DUIterator_Fast imax, i = region->fast_outs(imax); i < imax; i++) {
       Node* phi = region->fast_out(i);
       if (phi->is_Phi() && phi != mem &&
-          phi->as_Phi()->is_same_inst_field(this_type, this_iid, this_index, this_offset)) {
+          phi->as_Phi()->is_same_inst_field(this_type, (int)mem->_idx, this_iid, this_index, this_offset)) {
         return phi;
       }
     }
@@ -1400,7 +1400,7 @@
     this_iid = base->_idx;
   }
   PhaseIterGVN* igvn = phase->is_IterGVN();
-  Node* phi = new (C) PhiNode(region, this_type, NULL, this_iid, this_index, this_offset);
+  Node* phi = new (C) PhiNode(region, this_type, NULL, mem->_idx, this_iid, this_index, this_offset);
   for (uint i = 1; i < region->req(); i++) {
     Node* x;
     Node* the_clone = NULL;
--- a/src/share/vm/opto/phaseX.cpp	Mon Jan 23 17:09:40 2017 -0800
+++ b/src/share/vm/opto/phaseX.cpp	Thu Feb 16 13:21:41 2017 -0800
@@ -481,6 +481,8 @@
   uint current_idx = 0; // The current new node ID. Incremented after every assignment.
   for (uint i = 0; i < _useful.size(); i++) {
     Node* n = _useful.at(i);
+    // Sanity check that fails if we ever decide to execute this phase after EA
+    assert(!n->is_Phi() || n->as_Phi()->inst_mem_id() == -1, "should not be linked to data Phi");
     const Type* type = gvn->type_or_null(n);
     new_type_array.map(current_idx, type);
 
@@ -1378,6 +1380,18 @@
     i -= num_edges;    // we deleted 1 or more copies of this edge
   }
 
+  // Search for instance field data PhiNodes in the same region pointing to the old
+  // memory PhiNode and update their instance memory ids to point to the new node.
+  if (old->is_Phi() && old->as_Phi()->type()->has_memory() && old->in(0) != NULL) {
+    Node* region = old->in(0);
+    for (DUIterator_Fast imax, i = region->fast_outs(imax); i < imax; i++) {
+      PhiNode* phi = region->fast_out(i)->isa_Phi();
+      if (phi != NULL && phi->inst_mem_id() == (int)old->_idx) {
+        phi->set_inst_mem_id((int)nn->_idx);
+      }
+    }
+  }
+
   // Smash all inputs to 'old', isolating him completely
   Node *temp = new (C) Node(1);
   temp->init_req(0,nn);     // Add a use to nn to prevent him from dying
--- a/src/share/vm/opto/type.hpp	Mon Jan 23 17:09:40 2017 -0800
+++ b/src/share/vm/opto/type.hpp	Thu Feb 16 13:21:41 2017 -0800
@@ -882,7 +882,7 @@
 
   // If not InstanceTop or InstanceBot, indicates that this is
   // a particular instance of this type which is distinct.
-  // This is the the node index of the allocation node creating this instance.
+  // This is the node index of the allocation node creating this instance.
   int           _instance_id;
 
   // Extra type information profiling gave us. We propagate it the
--- a/src/share/vm/runtime/arguments.cpp	Mon Jan 23 17:09:40 2017 -0800
+++ b/src/share/vm/runtime/arguments.cpp	Thu Feb 16 13:21:41 2017 -0800
@@ -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
@@ -1768,10 +1768,39 @@
     FLAG_SET_CMDLINE(uintx, MaxRAMFraction, DefaultMaxRAMFraction);
   }
 
-  const julong phys_mem =
+  julong phys_mem =
     FLAG_IS_DEFAULT(MaxRAM) ? MIN2(os::physical_memory(), (julong)MaxRAM)
                             : (julong)MaxRAM;
 
+  // Experimental support for CGroup memory limits
+  if (UseCGroupMemoryLimitForHeap) {
+    // This is a rough indicator that a CGroup limit may be in force
+    // for this process
+    const char* lim_file = "/sys/fs/cgroup/memory/memory.limit_in_bytes";
+    FILE *fp = fopen(lim_file, "r");
+    if (fp != NULL) {
+      julong cgroup_max = 0;
+      int ret = fscanf(fp, JULONG_FORMAT, &cgroup_max);
+      if (ret == 1 && cgroup_max > 0) {
+        // If unlimited, cgroup_max will be a very large, but unspecified
+        // value, so use initial phys_mem as a limit
+        if (PrintGCDetails && Verbose) {
+          // Cannot use gclog_or_tty yet.
+          tty->print_cr("Setting phys_mem to the min of cgroup limit ("
+                        JULONG_FORMAT "MB) and initial phys_mem ("
+                        JULONG_FORMAT "MB)", cgroup_max/M, phys_mem/M);
+        }
+        phys_mem = MIN2(cgroup_max, phys_mem);
+      } else {
+        warning("Unable to read/parse cgroup memory limit from %s: %s",
+                lim_file, errno != 0 ? strerror(errno) : "unknown error");
+      }
+      fclose(fp);
+    } else {
+      warning("Unable to open cgroup memory limit file %s (%s)", lim_file, strerror(errno));
+    }
+  }
+
   // If the maximum heap size has not been set with -Xmx,
   // then set it as fraction of the size of physical memory,
   // respecting the maximum and minimum sizes of the heap.
--- a/src/share/vm/runtime/globals.hpp	Mon Jan 23 17:09:40 2017 -0800
+++ b/src/share/vm/runtime/globals.hpp	Thu Feb 16 13:21:41 2017 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2016, 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
@@ -2068,6 +2068,10 @@
           "Maximum ergonomically set heap size (in bytes); zero means use " \
           "MaxRAM / MaxRAMFraction")                                        \
                                                                             \
+  experimental(bool, UseCGroupMemoryLimitForHeap, false,                    \
+          "Use CGroup memory limit as physical memory limit for heap "      \
+          "sizing")                                                         \
+                                                                            \
   product(uintx, MaxRAMFraction, 4,                                         \
           "Maximum fraction (1/n) of real memory used for maximum heap "    \
           "size")                                                           \
--- a/src/share/vm/runtime/os.cpp	Mon Jan 23 17:09:40 2017 -0800
+++ b/src/share/vm/runtime/os.cpp	Thu Feb 16 13:21:41 2017 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2016, 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
@@ -78,6 +78,7 @@
 uintptr_t         os::_serialize_page_mask = 0;
 long              os::_rand_seed          = 1;
 int               os::_processor_count    = 0;
+int               os::_initial_active_processor_count = 0;
 size_t            os::_page_sizes[os::page_sizes_max];
 
 #ifndef PRODUCT
@@ -322,6 +323,7 @@
 }
 
 void os::init_before_ergo() {
+  initialize_initial_active_processor_count();
   // We need to initialize large page support here because ergonomics takes some
   // decisions depending on large page support and the calculated large page size.
   large_page_init();
@@ -835,7 +837,11 @@
   st->print("CPU:");
   st->print("total %d", os::processor_count());
   // It's not safe to query number of active processors after crash
-  // st->print("(active %d)", os::active_processor_count());
+  // st->print("(active %d)", os::active_processor_count()); but we can
+  // print the initial number of active processors.
+  // We access the raw value here because the assert in the accessor will
+  // fail if the crash occurs before initialization of this value.
+  st->print(" (initial active %d)", _initial_active_processor_count);
   st->print(" %s", VM_Version::cpu_features());
   st->cr();
   pd_print_cpu_info(st);
@@ -1418,6 +1424,11 @@
   return result;
 }
 
+void os::initialize_initial_active_processor_count() {
+  assert(_initial_active_processor_count == 0, "Initial active processor count already set.");
+  _initial_active_processor_count = active_processor_count();
+}
+
 void os::SuspendedThreadTask::run() {
   assert(Threads_lock->owned_by_self() || (_thread == VMThread::vm_thread()), "must have threads lock to call this");
   internal_do_task();
--- a/src/share/vm/runtime/os.hpp	Mon Jan 23 17:09:40 2017 -0800
+++ b/src/share/vm/runtime/os.hpp	Thu Feb 16 13:21:41 2017 -0800
@@ -151,6 +151,7 @@
 
   static size_t page_size_for_region(size_t region_size, size_t min_pages, bool must_be_aligned);
 
+  static void initialize_initial_active_processor_count();
  public:
   static void init(void);                      // Called before command line parsing
   static void init_before_ergo(void);          // Called after command line parsing
@@ -238,6 +239,13 @@
   // Note that on some OSes this can change dynamically.
   static int active_processor_count();
 
+  // At startup the number of active CPUs this process is allowed to run on.
+  // This value does not change dynamically. May be different from active_processor_count().
+  static int initial_active_processor_count() {
+    assert(_initial_active_processor_count > 0, "Initial active processor count not set yet.");
+    return _initial_active_processor_count;
+  }
+
   // Bind processes to processors.
   //     This is a two step procedure:
   //     first you generate a distribution of processes to processors,
@@ -975,8 +983,9 @@
 
 
  protected:
-  static long _rand_seed;                   // seed for random number generator
-  static int _processor_count;              // number of processors
+  static long _rand_seed;                     // seed for random number generator
+  static int _processor_count;                // number of processors
+  static int _initial_active_processor_count; // number of active processors during initialization.
 
   static char* format_boot_path(const char* format_string,
                                 const char* home,
--- a/src/share/vm/runtime/vm_version.cpp	Mon Jan 23 17:09:40 2017 -0800
+++ b/src/share/vm/runtime/vm_version.cpp	Thu Feb 16 13:21:41 2017 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1998, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1998, 2016, 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
@@ -296,7 +296,7 @@
     // processor after the first 8.  For example, on a 72 cpu machine
     // and a chosen fraction of 5/8
     // use 8 + (72 - 8) * (5/8) == 48 worker threads.
-    unsigned int ncpus = (unsigned int) os::active_processor_count();
+    unsigned int ncpus = (unsigned int) os::initial_active_processor_count();
     return (ncpus <= switch_pt) ?
            ncpus :
           (switch_pt + ((ncpus - switch_pt) * num) / den);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/runtime/os/AvailableProcessors.java	Thu Feb 16 13:21:41 2017 -0800
@@ -0,0 +1,103 @@
+/*
+ * Copyright (c) 2016, 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.
+ */
+import java.io.File;
+import com.oracle.java.testlibrary.ProcessTools;
+import com.oracle.java.testlibrary.OutputAnalyzer;
+import java.util.ArrayList;
+
+/*
+ * @test
+ * @bug 6515172
+ * @summary Check that availableProcessors reports the correct value when running in a cpuset on linux
+ * @requires os.family == "linux"
+ * @library /testlibrary
+ * @build com.oracle.java.testlibrary.*
+ * @run driver AvailableProcessors
+ */
+public class AvailableProcessors {
+
+    static final String SUCCESS_STRING = "Found expected processors: ";
+
+    public static void main(String[] args) throws Throwable {
+        if (args.length > 0)
+            checkProcessors(Integer.parseInt(args[0]));
+        else {
+            // run ourselves under different cpu configurations
+            // using the taskset command
+            String taskset;
+            final String taskset1 = "/bin/taskset";
+            final String taskset2 = "/usr/bin/taskset";
+            if (new File(taskset1).exists())
+                taskset = taskset1;
+            else if (new File(taskset2).exists())
+                taskset = taskset2;
+            else {
+                System.out.println("Skipping test: could not find taskset command");
+                return;
+            }
+
+            int available = Runtime.getRuntime().availableProcessors();
+
+            if (available == 1) {
+                System.out.println("Skipping test: only one processor available");
+                return;
+            }
+
+            // Get the java command we want to execute
+            // Enable logging for easier failure diagnosis
+            ProcessBuilder master =
+                    ProcessTools.createJavaProcessBuilder(false,
+                                                          "-XX:+UnlockDiagnosticVMOptions",
+                                                          "-XX:+PrintActiveCpus",
+                                                          "AvailableProcessors");
+
+            int[] expected = new int[] { 1, available/2, available-1, available };
+
+            for (int i : expected) {
+                System.out.println("Testing for " + i + " processors ...");
+                int max = i - 1;
+                ArrayList<String> cmdline = new ArrayList<>(master.command());
+                // prepend taskset command
+                cmdline.add(0, "0-" + max);
+                cmdline.add(0, "-c");
+                cmdline.add(0, taskset);
+                // append expected processor count
+                cmdline.add(String.valueOf(i));
+                ProcessBuilder pb = new ProcessBuilder(cmdline);
+                System.out.println("Final command line: " +
+                                   ProcessTools.getCommandLine(pb));
+                OutputAnalyzer output = ProcessTools.executeProcess(pb);
+                output.shouldContain(SUCCESS_STRING);
+            }
+        }
+    }
+
+    static void checkProcessors(int expected) {
+        int available = Runtime.getRuntime().availableProcessors();
+        if (available != expected)
+            throw new Error("Expected " + expected + " processors, but found "
+                            + available);
+        else
+            System.out.println(SUCCESS_STRING + available);
+    }
+}