sssssssss88


  {
    int test_array[] = {76,46,81,8,64,56,75,11,51,55,11,71,59,27,9,64,69,75,21,25,39,40,44,32,7,8,40,41,24,78,24,74,9,65,28,6,40,31,22,13,27,82};
    int expected_array[] = {6,7,8,8,9,9,11,11,13,21,22,24,24,25,27,27,28,31,32,39,40,40,40,41,44,46,51,55,56,59,64,64,65,69,71,74,75,75,76,78,81,82};
    assert(sort_and_compare(test_array, expected_array, 42, test_comparator), "Not correctly sorted");
  }
  {
    int test_array[] = {2,8,1,4};
    int expected_array[] = {1,4,2,8};
    assert(sort_and_compare(test_array, expected_array, 4, test_even_odd_comparator), "Even/odd not sorted correctly");
  }
  {  // Some idempotent tests
    {
      int test_array[] = {1,4,8};
      int expected_array[] = {1,4,8};
      assert(sort_and_compare(test_array, expected_array, 3, test_even_odd_comparator, true), "Even/odd not idempotent");
    }
    {
      int test_array[] = {1,7,9,4,8,2};
      int expected_array[] = {1,7,9,4,8,2};
      assert(sort_and_compare(test_array, expected_array, 6, test_even_odd_comparator, true), "Even/odd not idempotent");
    }
    {
      int test_array[] = {1,9,7,4,2,8};
      int expected_array[] = {1,9,7,4,2,8};
      assert(sort_and_compare(test_array, expected_array, 6, test_even_odd_comparator, true), "Even/odd not idempotent");
    }
    {
      int test_array[] = {7,9,1,2,8,4};
      int expected_array[] = {7,9,1,2,8,4};
      assert(sort_and_compare(test_array, expected_array, 6, test_even_odd_comparator, true), "Even/odd not idempotent");
    }
    {
      int test_array[] = {7,1,9,2,4,8};
      int expected_array[] = {7,1,9,2,4,8};
      assert(sort_and_compare(test_array, expected_array, 6, test_even_odd_comparator, true), "Even/odd not idempotent");
    }
    {
      int test_array[] = {9,1,7,4,8,2};
      int expected_array[] = {9,1,7,4,8,2};
      assert(sort_and_compare(test_array, expected_array, 6, test_even_odd_comparator, true), "Even/odd not idempotent");
    }
    {
      int test_array[] = {9,7,1,4,2,8};
      int expected_array[] = {9,7,1,4,2,8};
      assert(sort_and_compare(test_array, expected_array, 6, test_even_odd_comparator, true), "Even/odd not idempotent");
    }
  }
  for (int i = 0; i < 1000; i++) {
    int length = os::random() % 100;
    int* test_array = NEW_C_HEAP_ARRAY(int, length, mtInternal);
    int* expected_array = NEW_C_HEAP_ARRAY(int, length, mtInternal);
    for (int j = 0; j < length; j++) {
        test_array[j] = os::random() % (length * 2);
        expected_array[j] = test_array[j];
    }
    qsort(expected_array, length, sizeof(int), test_stdlib_comparator);
    assert(sort_and_compare(test_array, expected_array, length, test_comparator), "Random array not correctly sorted");
    sort(expected_array, length, test_even_odd_comparator, true);
    sort(test_array, length, test_even_odd_comparator, true);
    assert(compare_arrays(test_array, expected_array, length), "Sorting identical arrays rendered different results");
    sort(test_array, length, test_even_odd_comparator, true);
    assert(compare_arrays(test_array, expected_array, length), "Sorting already sorted array changed order of elements - not idempotent");
    FREE_C_HEAP_ARRAY(int, test_array, mtInternal);
    FREE_C_HEAP_ARRAY(int, expected_array, mtInternal);
  }
}
#endif
C:\hotspot-69087d08d473\src\share\vm/utilities/quickSort.hpp
#ifndef SHARE_VM_UTILITIES_QUICKSORT_HPP
#define SHARE_VM_UTILITIES_QUICKSORT_HPP
#include "memory/allocation.hpp"
#include "runtime/globals.hpp"
#include "utilities/debug.hpp"
class QuickSort : AllStatic {
 private:
  template<class T>
  static void swap(T* array, int x, int y) {
    T tmp = array[x];
    array[x] = array[y];
    array[y] = tmp;
  }
  template<class T, class C>
  static int find_pivot(T* array, int length, C comparator) {
    assert(length > 1, "length of array must be > 0");
    int middle_index = length / 2;
    int last_index = length - 1;
    if (comparator(array[0], array[middle_index]) == 1) {
      swap(array, 0, middle_index);
    }
    if (comparator(array[0], array[last_index]) == 1) {
      swap(array, 0, last_index);
    }
    if (comparator(array[middle_index], array[last_index]) == 1) {
      swap(array, middle_index, last_index);
    }
    return middle_index;
  }
  template<class T, class C, bool idempotent>
  static int partition(T* array, int pivot, int length, C comparator) {
    int left_index = -1;
    int right_index = length;
    T pivot_val = array[pivot];
    while (true) {
      do {
        left_index++;
      } while (comparator(array[left_index], pivot_val) == -1);
      do {
        right_index--;
      } while (comparator(array[right_index], pivot_val) == 1);
      if (left_index < right_index) {
        if (!idempotent || comparator(array[left_index], array[right_index]) != 0) {
          swap(array, left_index, right_index);
        }
      } else {
        return right_index;
      }
    }
    ShouldNotReachHere();
    return 0;
  }
  template<class T, class C, bool idempotent>
  static void inner_sort(T* array, int length, C comparator) {
    if (length < 2) {
      return;
    }
    int pivot = find_pivot(array, length, comparator);
    if (length < 4) {
      return;
    }
    int split = partition<T, C, idempotent>(array, pivot, length, comparator);
    int first_part_length = split + 1;
    inner_sort<T, C, idempotent>(array, first_part_length, comparator);
    inner_sort<T, C, idempotent>(&array[first_part_length], length - first_part_length, comparator);
  }
 public:
  template<class T, class C>
  static void sort(T* array, int length, C comparator, bool idempotent) {
    if (idempotent) {
      inner_sort<T, C, true>(array, length, comparator);
    } else {
      inner_sort<T, C, false>(array, length, comparator);
    }
  }
#ifndef PRODUCT
  static void print_array(const char* prefix, int* array, int length);
  static bool compare_arrays(int* actual, int* expected, int length);
  template <class C> static bool sort_and_compare(int* arrayToSort, int* expectedResult, int length, C comparator, bool idempotent = false);
  static void test_quick_sort();
#endif
};
#endif //SHARE_VM_UTILITIES_QUICKSORT_HPP
C:\hotspot-69087d08d473\src\share\vm/utilities/resourceHash.cpp
#include "precompiled.hpp"
#include "memory/allocation.hpp"
#include "memory/resourceArea.hpp"
#include "utilities/debug.hpp"
#include "utilities/resourceHash.hpp"
#ifndef PRODUCT
class TestResourceHashtable : public AllStatic {
  typedef void* K;
  typedef int V;
  static unsigned identity_hash(const K& k) {
    return (unsigned)(uintptr_t)k;
  }
  static unsigned bad_hash(const K& k) {
    return 1;
  }
  class EqualityTestIter {
   public:
    bool do_entry(K const& k, V const& v) {
      assert((uintptr_t)k == (uintptr_t)v, "");
      return true; // continue iteration
    }
  };
  template<
  unsigned (*HASH)  (K const&)           = primitive_hash<K>,
  bool     (*EQUALS)(K const&, K const&) = primitive_equals<K>,
  unsigned SIZE = 256,
  ResourceObj::allocation_type ALLOC_TYPE = ResourceObj::RESOURCE_AREA,
  MEMFLAGS MEM_TYPE = mtInternal
  >
  class Runner : public AllStatic {
    static void* as_K(uintptr_t val) { return (void*)val; }
   public:
    static void test_small() {
      EqualityTestIter et;
      ResourceHashtable<K, V, HASH, EQUALS, SIZE, ALLOC_TYPE, MEM_TYPE> rh;
      assert(!rh.contains(as_K(0x1)), "");
      assert(rh.put(as_K(0x1), 0x1), "");
      assert(rh.contains(as_K(0x1)), "");
      assert(!rh.put(as_K(0x1), 0x1), "");
      assert(rh.put(as_K(0x2), 0x2), "");
      assert(rh.put(as_K(0x3), 0x3), "");
      assert(rh.put(as_K(0x4), 0x4), "");
      assert(rh.put(as_K(0x5), 0x5), "");
      assert(!rh.remove(as_K(0x0)), "");
      rh.iterate(&et);
      assert(rh.remove(as_K(0x1)), "");
      rh.iterate(&et);
    }
    static void test_small_shifted() {
      EqualityTestIter et;
      ResourceHashtable<K, V, HASH, EQUALS, SIZE, ALLOC_TYPE, MEM_TYPE> rh;
      assert(!rh.contains(as_K(0x10)), "");
      assert(rh.put(as_K(0x10), 0x10), "");
      assert(rh.contains(as_K(0x10)), "");
      assert(!rh.put(as_K(0x10), 0x10), "");
      assert(rh.put(as_K(0x20), 0x20), "");
      assert(rh.put(as_K(0x30), 0x30), "");
      assert(rh.put(as_K(0x40), 0x40), "");
      assert(rh.put(as_K(0x50), 0x50), "");
      assert(!rh.remove(as_K(0x00)), "");
      assert(rh.remove(as_K(0x10)), "");
      rh.iterate(&et);
    }
    static void test(unsigned num_elements = SIZE) {
      EqualityTestIter et;
      ResourceHashtable<K, V, HASH, EQUALS, SIZE, ALLOC_TYPE, MEM_TYPE> rh;
      for (uintptr_t i = 0; i < num_elements; ++i) {
        assert(rh.put(as_K(i), i), "");
      }
      rh.iterate(&et);
      for (uintptr_t i = num_elements; i > 0; --i) {
        uintptr_t index = i - 1;
        assert(rh.remove(as_K(index)), "");
      }
      rh.iterate(&et);
      for (uintptr_t i = num_elements; i > 0; --i) {
        uintptr_t index = i - 1;
        assert(!rh.remove(as_K(index)), "");
      }
      rh.iterate(&et);
    }
  };
 public:
  static void run_tests() {
    {
      ResourceMark rm;
      Runner<>::test_small();
      Runner<>::test_small_shifted();
      Runner<>::test();
    }
    {
      ResourceMark rm;
      Runner<identity_hash>::test_small();
      Runner<identity_hash>::test_small_shifted();
      Runner<identity_hash>::test();
    }
    {
      ResourceMark rm;
      Runner<bad_hash>::test_small();
      Runner<bad_hash>::test_small_shifted();
      Runner<bad_hash>::test();
    }
    assert(Thread::current()->resource_area()->nesting() == 0, "this code depends on not having an active ResourceMark");
    Runner<primitive_hash<K>, primitive_equals<K>, 512, ResourceObj::C_HEAP>::test_small();
    Runner<primitive_hash<K>, primitive_equals<K>, 512, ResourceObj::C_HEAP>::test_small_shifted();
    Runner<primitive_hash<K>, primitive_equals<K>, 512, ResourceObj::C_HEAP>::test();
    Runner<bad_hash, primitive_equals<K>, 512, ResourceObj::C_HEAP>::test_small();
    Runner<bad_hash, primitive_equals<K>, 512, ResourceObj::C_HEAP>::test_small_shifted();
    Runner<bad_hash, primitive_equals<K>, 512, ResourceObj::C_HEAP>::test();
    Runner<identity_hash, primitive_equals<K>, 1, ResourceObj::C_HEAP>::test_small();
    Runner<identity_hash, primitive_equals<K>, 1, ResourceObj::C_HEAP>::test_small_shifted();
    Runner<identity_hash, primitive_equals<K>, 1, ResourceObj::C_HEAP>::test(512);
  }
};
void TestResourcehash_test() {
  TestResourceHashtable::run_tests();
}
#endif // not PRODUCT
C:\hotspot-69087d08d473\src\share\vm/utilities/resourceHash.hpp
#ifndef SHARE_VM_UTILITIES_RESOURCEHASH_HPP
#define SHARE_VM_UTILITIES_RESOURCEHASH_HPP
#include "memory/allocation.hpp"
#include "utilities/top.hpp"
template<typename K> struct ResourceHashtableFns {
    typedef unsigned (*hash_fn)(K const&);
    typedef bool (*equals_fn)(K const&, K const&);
};
template<typename K> unsigned primitive_hash(const K& k) {
  unsigned hash = (unsigned)((uintptr_t)k);
  return hash ^ (hash >> 3); // just in case we're dealing with aligned ptrs
}
template<typename K> bool primitive_equals(const K& k0, const K& k1) {
  return k0 == k1;
}
template<
    typename K, typename V,
    unsigned (*HASH)  (K const&)           = primitive_hash<K>,
    bool     (*EQUALS)(K const&, K const&) = primitive_equals<K>,
    unsigned SIZE = 256,
    ResourceObj::allocation_type ALLOC_TYPE = ResourceObj::RESOURCE_AREA,
    MEMFLAGS MEM_TYPE = mtInternal
    >
class ResourceHashtable : public ResourceObj {
 private:
  class Node : public ResourceObj {
   public:
    unsigned _hash;
    K _key;
    V _value;
    Node* _next;
    Node(unsigned hash, K const& key, V const& value) :
        _hash(hash), _key(key), _value(value), _next(NULL) {}
  };
  Node* _table[SIZE];
  Node** lookup_node(unsigned hash, K const& key) {
    unsigned index = hash % SIZE;
    Node** ptr = &_table[index];
    while (*ptr != NULL) {
      Node* node = *ptr;
      if (node->_hash == hash && EQUALS(key, node->_key)) {
        break;
      }
      ptr = &(node->_next);
    }
    return ptr;
  }
  Node const** lookup_node(unsigned hash, K const& key) const {
    return const_cast<Node const**>(
        const_cast<ResourceHashtable*>(this)->lookup_node(hash, key));
  }
 public:
  ResourceHashtable() { memset(_table, 0, SIZE * sizeof(Node*)); }
  ~ResourceHashtable() {
    if (ALLOC_TYPE == C_HEAP) {
      Node* const* bucket = _table;
      while (bucket < &_table[SIZE]) {
        Node* node = *bucket;
        while (node != NULL) {
          Node* cur = node;
          node = node->_next;
          delete cur;
        }
        ++bucket;
      }
    }
  }
  bool contains(K const& key) const {
    return get(key) != NULL;
  }
  V* get(K const& key) const {
    unsigned hv = HASH(key);
    Node const** ptr = lookup_node(hv, key);
    if (*ptr != NULL) {
      return const_cast<V*>(&(*ptr)->_value);
    } else {
      return NULL;
    }
  }
  bool put(K const& key, V const& value) {
    unsigned hv = HASH(key);
    Node** ptr = lookup_node(hv, key);
    if (*ptr != NULL) {
      (*ptr)->_value = value;
      return false;
    } else {
      return true;
    }
  }
  bool remove(K const& key) {
    unsigned hv = HASH(key);
    Node** ptr = lookup_node(hv, key);
    Node* node = *ptr;
    if (node != NULL) {
      if (ALLOC_TYPE == C_HEAP) {
        delete node;
      }
      return true;
    }
    return false;
  }
  template<class ITER>
  void iterate(ITER* iter) const {
    Node* const* bucket = _table;
    while (bucket < &_table[SIZE]) {
      Node* node = *bucket;
      while (node != NULL) {
        bool cont = iter->do_entry(node->_key, node->_value);
        if (!cont) { return; }
        node = node->_next;
      }
      ++bucket;
    }
  }
  static size_t node_size() {
    return sizeof(Node);
  }
};
#endif // SHARE_VM_UTILITIES_RESOURCEHASH_HPP
C:\hotspot-69087d08d473\src\share\vm/utilities/sizes.cpp
#include "precompiled.hpp"
#include "utilities/sizes.hpp"
C:\hotspot-69087d08d473\src\share\vm/utilities/sizes.hpp
#ifndef SHARE_VM_UTILITIES_SIZES_HPP
#define SHARE_VM_UTILITIES_SIZES_HPP
#include "memory/allocation.hpp"
#include "utilities/globalDefinitions.hpp"
#ifdef ASSERT
class ByteSize VALUE_OBJ_CLASS_SPEC {
 private:
  int _size;
  ByteSize(int size)                                  { _size = size; }
 public:
  inline friend ByteSize in_ByteSize(int size);
  inline friend int in_bytes(ByteSize x);
  friend ByteSize operator + (ByteSize x, ByteSize y) { return ByteSize(in_bytes(x) + in_bytes(y)); }
  friend ByteSize operator - (ByteSize x, ByteSize y) { return ByteSize(in_bytes(x) - in_bytes(y)); }
  friend ByteSize operator * (ByteSize x, int      y) { return ByteSize(in_bytes(x) * y          ); }
  friend bool operator == (ByteSize x, ByteSize y)    { return in_bytes(x) == in_bytes(y); }
  friend bool operator != (ByteSize x, ByteSize y)    { return in_bytes(x) != in_bytes(y); }
  friend bool operator <  (ByteSize x, ByteSize y)    { return in_bytes(x) <  in_bytes(y); }
  friend bool operator <= (ByteSize x, ByteSize y)    { return in_bytes(x) <= in_bytes(y); }
  friend bool operator >  (ByteSize x, ByteSize y)    { return in_bytes(x) >  in_bytes(y); }
  friend bool operator >= (ByteSize x, ByteSize y)    { return in_bytes(x) >= in_bytes(y); }
};
inline ByteSize in_ByteSize(int size) { return ByteSize(size); }
inline int      in_bytes(ByteSize x)  { return x._size; }
class WordSize VALUE_OBJ_CLASS_SPEC {
 private:
  int _size;
  WordSize(int size)                                  { _size = size; }
 public:
  inline friend WordSize in_WordSize(int size);
  inline friend int in_words(WordSize x);
  friend WordSize operator + (WordSize x, WordSize y) { return WordSize(in_words(x) + in_words(y)); }
  friend WordSize operator - (WordSize x, WordSize y) { return WordSize(in_words(x) - in_words(y)); }
  friend WordSize operator * (WordSize x, int      y) { return WordSize(in_words(x) * y          ); }
  friend bool operator == (WordSize x, WordSize y)    { return in_words(x) == in_words(y); }
  friend bool operator != (WordSize x, WordSize y)    { return in_words(x) != in_words(y); }
  friend bool operator <  (WordSize x, WordSize y)    { return in_words(x) <  in_words(y); }
  friend bool operator <= (WordSize x, WordSize y)    { return in_words(x) <= in_words(y); }
  friend bool operator >  (WordSize x, WordSize y)    { return in_words(x) >  in_words(y); }
  friend bool operator >= (WordSize x, WordSize y)    { return in_words(x) >= in_words(y); }
};
inline WordSize in_WordSize(int size) { return WordSize(size); }
inline int      in_words(WordSize x)  { return x._size; }
#else // ASSERT
typedef int ByteSize;
inline ByteSize in_ByteSize(int size)                 { return size; }
inline int      in_bytes   (ByteSize x)               { return x; }
typedef int WordSize;
inline WordSize in_WordSize(int size)                 { return size; }
inline int      in_words   (WordSize x)               { return x; }
#endif // ASSERT
#define byte_offset_of(klass,field)   in_ByteSize((int)offset_of(klass, field))
#endif // SHARE_VM_UTILITIES_SIZES_HPP
C:\hotspot-69087d08d473\src\share\vm/utilities/stack.hpp
#ifndef SHARE_VM_UTILITIES_STACK_HPP
#define SHARE_VM_UTILITIES_STACK_HPP
#include "memory/allocation.hpp"
#include "memory/allocation.inline.hpp"
template <class E, MEMFLAGS F> class StackIterator;
template <MEMFLAGS F> class StackBase
{
public:
  size_t segment_size()   const { return _seg_size; } // Elements per segment.
  size_t max_size()       const { return _max_size; } // Max elements allowed.
  size_t max_cache_size() const { return _max_cache_size; } // Max segments
  size_t cache_size() const { return _cache_size; }   // Segments in the cache.
protected:
  inline StackBase(size_t segment_size, size_t max_cache_size, size_t max_size);
  static inline size_t adjust_max_size(size_t max_size, size_t seg_size);
protected:
  const size_t _seg_size;       // Number of items per segment.
  const size_t _max_size;       // Maximum number of items allowed in the stack.
  const size_t _max_cache_size; // Maximum number of segments to cache.
  size_t       _cur_seg_size;   // Number of items in the current segment.
  size_t       _full_seg_size;  // Number of items in already-filled segments.
  size_t       _cache_size;     // Number of segments in the cache.
};
#ifdef __GNUC__
#define inline
#endif // __GNUC__
template <class E, MEMFLAGS F>
class Stack:  public StackBase<F>
{
public:
  friend class StackIterator<E, F>;
  static const size_t _default_segment_size =  (4096 - 2 * sizeof(E*)) / sizeof(E);
  static size_t default_segment_size() { return _default_segment_size; }
  inline Stack(size_t segment_size = _default_segment_size,
               size_t max_cache_size = 4, size_t max_size = 0);
  inline ~Stack() { clear(true); }
  inline bool is_empty() const { return this->_cur_seg == NULL; }
  inline bool is_full()  const { return this->_full_seg_size >= this->max_size(); }
  inline size_t size() const {
    return is_empty() ? 0 : this->_full_seg_size + this->_cur_seg_size;
  }
  inline void push(E elem);
  inline E    pop();
  void clear(bool clear_cache = false);
protected:
  static inline size_t adjust_segment_size(size_t seg_size);
  inline size_t link_offset() const;              // Byte offset of link field.
  inline size_t segment_bytes() const;            // Segment size in bytes.
  inline E**    link_addr(E* seg) const;          // Address of the link field.
  inline E*     get_link(E* seg) const;           // Extract the link from seg.
  inline E*     set_link(E* new_seg, E* old_seg); // new_seg.link = old_seg.
  virtual E*    alloc(size_t bytes);
  virtual void  free(E* addr, size_t bytes);
  void push_segment();
  void pop_segment();
  void free_segments(E* seg);          // Free all segments in the list.
  inline void reset(bool reset_cache); // Reset all data fields.
  DEBUG_ONLY(void verify(bool at_empty_transition) const;)
  DEBUG_ONLY(void zap_segment(E* seg, bool zap_link_field) const;)
private:
  E* _cur_seg;    // Current segment.
  E* _cache;      // Segment cache to avoid ping-ponging.
};
template <class E, MEMFLAGS F> class ResourceStack:  public Stack<E, F>, public ResourceObj
{
public:
  ResourceStack(size_t segment_size): Stack<E, F>(segment_size, max_uintx)
    { }
  ~ResourceStack() { Stack<E, F>::reset(true); }
protected:
  virtual E*   alloc(size_t bytes);
  virtual void free(E* addr, size_t bytes);
private:
  void clear(bool clear_cache = false);
};
template <class E, MEMFLAGS F>
class StackIterator: public StackObj
{
public:
  StackIterator(Stack<E, F>& stack): _stack(stack) { sync(); }
  Stack<E, F>& stack() const { return _stack; }
  bool is_empty() const { return _cur_seg == NULL; }
  E  next() { return *next_addr(); }
  E* next_addr();
  void sync(); // Sync the iterator's state to the stack's current state.
private:
  Stack<E, F>& _stack;
  size_t    _cur_seg_size;
  E*        _cur_seg;
  size_t    _full_seg_size;
};
#ifdef __GNUC__
#undef inline
#endif // __GNUC__
#endif // SHARE_VM_UTILITIES_STACK_HPP
C:\hotspot-69087d08d473\src\share\vm/utilities/stack.inline.hpp
#ifndef SHARE_VM_UTILITIES_STACK_INLINE_HPP
#define SHARE_VM_UTILITIES_STACK_INLINE_HPP
#include "utilities/stack.hpp"
#include "utilities/copy.hpp"
template <MEMFLAGS F> StackBase<F>::StackBase(size_t segment_size, size_t max_cache_size,
                     size_t max_size):
  _seg_size(segment_size),
  _max_cache_size(max_cache_size),
  _max_size(adjust_max_size(max_size, segment_size))
{
  assert(_max_size % _seg_size == 0, "not a multiple");
}
template <MEMFLAGS F> size_t StackBase<F>::adjust_max_size(size_t max_size, size_t seg_size)
{
  assert(seg_size > 0, "cannot be 0");
  assert(max_size >= seg_size || max_size == 0, "max_size too small");
  const size_t limit = max_uintx - (seg_size - 1);
  if (max_size == 0 || max_size > limit) {
    max_size = limit;
  }
  return (max_size + seg_size - 1) / seg_size * seg_size;
}
template <class E, MEMFLAGS F>
Stack<E, F>::Stack(size_t segment_size, size_t max_cache_size, size_t max_size):
  StackBase<F>(adjust_segment_size(segment_size), max_cache_size, max_size)
{
  reset(true);
}
template <class E, MEMFLAGS F>
void Stack<E, F>::push(E item)
{
  assert(!is_full(), "pushing onto a full stack");
  if (this->_cur_seg_size == this->_seg_size) {
    push_segment();
  }
  this->_cur_seg[this->_cur_seg_size] = item;
  ++this->_cur_seg_size;
}
template <class E, MEMFLAGS F>
E Stack<E, F>::pop()
{
  assert(!is_empty(), "popping from an empty stack");
  if (this->_cur_seg_size == 1) {
    E tmp = _cur_seg[--this->_cur_seg_size];
    pop_segment();
    return tmp;
  }
  return this->_cur_seg[--this->_cur_seg_size];
}
template <class E, MEMFLAGS F>
void Stack<E, F>::clear(bool clear_cache)
{
  free_segments(_cur_seg);
  if (clear_cache) free_segments(_cache);
  reset(clear_cache);
}
template <class E, MEMFLAGS F>
size_t Stack<E, F>::adjust_segment_size(size_t seg_size)
{
  const size_t elem_sz = sizeof(E);
  const size_t ptr_sz = sizeof(E*);
  assert(elem_sz % ptr_sz == 0 || ptr_sz % elem_sz == 0, "bad element size");
  if (elem_sz < ptr_sz) {
    return align_size_up(seg_size * elem_sz, ptr_sz) / elem_sz;
  }
  return seg_size;
}
template <class E, MEMFLAGS F>
size_t Stack<E, F>::link_offset() const
{
  return align_size_up(this->_seg_size * sizeof(E), sizeof(E*));
}
template <class E, MEMFLAGS F>
size_t Stack<E, F>::segment_bytes() const
{
  return link_offset() + sizeof(E*);
}
template <class E, MEMFLAGS F>
E** Stack<E, F>::link_addr(E* seg) const
{
  return (E**) ((char*)seg + link_offset());
}
template <class E, MEMFLAGS F>
E* Stack<E, F>::get_link(E* seg) const
{
  return *link_addr(seg);
}
template <class E, MEMFLAGS F>
E* Stack<E, F>::set_link(E* new_seg, E* old_seg)
{
  return new_seg;
}
template <class E, MEMFLAGS F>
E* Stack<E, F>::alloc(size_t bytes)
{
  return (E*) NEW_C_HEAP_ARRAY(char, bytes, F);
}
template <class E, MEMFLAGS F>
void Stack<E, F>::free(E* addr, size_t bytes)
{
  FREE_C_HEAP_ARRAY(char, (char*) addr, F);
}
template <class E, MEMFLAGS F>
void Stack<E, F>::push_segment()
{
  assert(this->_cur_seg_size == this->_seg_size, "current segment is not full");
  E* next;
  if (this->_cache_size > 0) {
    next = _cache;
    _cache = get_link(_cache);
    --this->_cache_size;
  } else {
    next = alloc(segment_bytes());
    DEBUG_ONLY(zap_segment(next, true);)
  }
  const bool at_empty_transition = is_empty();
  this->_cur_seg = set_link(next, _cur_seg);
  this->_cur_seg_size = 0;
  this->_full_seg_size += at_empty_transition ? 0 : this->_seg_size;
  DEBUG_ONLY(verify(at_empty_transition);)
}
template <class E, MEMFLAGS F>
void Stack<E, F>::pop_segment()
{
  assert(this->_cur_seg_size == 0, "current segment is not empty");
  E* const prev = get_link(_cur_seg);
  if (this->_cache_size < this->_max_cache_size) {
    DEBUG_ONLY(zap_segment(_cur_seg, false);)
    _cache = set_link(_cur_seg, _cache);
    ++this->_cache_size;
  } else {
    DEBUG_ONLY(zap_segment(_cur_seg, true);)
    free(_cur_seg, segment_bytes());
  }
  const bool at_empty_transition = prev == NULL;
  this->_cur_seg = prev;
  this->_cur_seg_size = this->_seg_size;
  this->_full_seg_size -= at_empty_transition ? 0 : this->_seg_size;
  DEBUG_ONLY(verify(at_empty_transition);)
}
template <class E, MEMFLAGS F>
void Stack<E, F>::free_segments(E* seg)
{
  const size_t bytes = segment_bytes();
  while (seg != NULL) {
    E* const prev = get_link(seg);
    free(seg, bytes);
    seg = prev;
  }
}
template <class E, MEMFLAGS F>
void Stack<E, F>::reset(bool reset_cache)
{
  this->_cur_seg_size = this->_seg_size; // So push() will alloc a new segment.
  this->_full_seg_size = 0;
  _cur_seg = NULL;
  if (reset_cache) {
    this->_cache_size = 0;
    _cache = NULL;
  }
}
#ifdef ASSERT
template <class E, MEMFLAGS F>
void Stack<E, F>::verify(bool at_empty_transition) const
{
  assert(size() <= this->max_size(), "stack exceeded bounds");
  assert(this->cache_size() <= this->max_cache_size(), "cache exceeded bounds");
  assert(this->_cur_seg_size <= this->segment_size(), "segment index exceeded bounds");
  assert(this->_full_seg_size % this->_seg_size == 0, "not a multiple");
  assert(at_empty_transition || is_empty() == (size() == 0), "mismatch");
  assert((_cache == NULL) == (this->cache_size() == 0), "mismatch");
  if (is_empty()) {
    assert(this->_cur_seg_size == this->segment_size(), "sanity");
  }
}
template <class E, MEMFLAGS F>
void Stack<E, F>::zap_segment(E* seg, bool zap_link_field) const
{
  if (!ZapStackSegments) return;
  const size_t zap_bytes = segment_bytes() - (zap_link_field ? 0 : sizeof(E*));
  Copy::fill_to_bytes(seg, zap_bytes, badStackSegVal);
}
#endif
template <class E, MEMFLAGS F>
E* ResourceStack<E, F>::alloc(size_t bytes)
{
  return (E*) resource_allocate_bytes(bytes);
}
template <class E, MEMFLAGS F>
void ResourceStack<E, F>::free(E* addr, size_t bytes)
{
  resource_free_bytes((char*) addr, bytes);
}
template <class E, MEMFLAGS F>
void StackIterator<E, F>::sync()
{
  _full_seg_size = _stack._full_seg_size;
  _cur_seg_size = _stack._cur_seg_size;
  _cur_seg = _stack._cur_seg;
}
template <class E, MEMFLAGS F>
E* StackIterator<E, F>::next_addr()
{
  assert(!is_empty(), "no items left");
  if (_cur_seg_size == 1) {
    E* addr = _cur_seg;
    _cur_seg = _stack.get_link(_cur_seg);
    _cur_seg_size = _stack.segment_size();
    _full_seg_size -= _stack.segment_size();
    return addr;
  }
  return _cur_seg + --_cur_seg_size;
}
#endif // SHARE_VM_UTILITIES_STACK_INLINE_HPP
C:\hotspot-69087d08d473\src\share\vm/utilities/stringUtils.cpp
#include "precompiled.hpp"
#include "utilities/stringUtils.hpp"
int StringUtils::replace_no_expand(char* string, const char* from, const char* to) {
  int replace_count = 0;
  size_t from_len = strlen(from);
  size_t to_len = strlen(to);
  assert(from_len >= to_len, "must not expand input");
  for (char* dst = string; *dst && (dst = strstr(dst, from)) != NULL;) {
    char* left_over = dst + from_len;
    memmove(dst, to, to_len);                       // does not copy trailing 0 of <to>
    dst += to_len;                                  // skip over the replacement.
    memmove(dst, left_over, strlen(left_over) + 1); // copies the trailing 0 of <left_over>
    ++ replace_count;
  }
  return replace_count;
}
C:\hotspot-69087d08d473\src\share\vm/utilities/stringUtils.hpp
#ifndef SHARE_VM_UTILITIES_STRINGUTILS_HPP
#define SHARE_VM_UTILITIES_STRINGUTILS_HPP
#include "memory/allocation.hpp"
class StringUtils : AllStatic {
public:
  static int replace_no_expand(char* string, const char* from, const char* to);
};
#endif // SHARE_VM_UTILITIES_STRINGUTILS_HPP
C:\hotspot-69087d08d473\src\share\vm/utilities/taskqueue.cpp
#include "precompiled.hpp"
#include "oops/oop.inline.hpp"
#include "runtime/os.hpp"
#include "runtime/thread.inline.hpp"
#include "utilities/debug.hpp"
#include "utilities/stack.inline.hpp"
#include "utilities/taskqueue.hpp"
PRAGMA_FORMAT_MUTE_WARNINGS_FOR_GCC
#ifdef TRACESPINNING
uint ParallelTaskTerminator::_total_yields = 0;
uint ParallelTaskTerminator::_total_spins = 0;
uint ParallelTaskTerminator::_total_peeks = 0;
#endif
#if TASKQUEUE_STATS
const char * const TaskQueueStats::_names[last_stat_id] = {
  "qpush", "qpop", "qpop-s", "qattempt", "qsteal", "opush", "omax"
};
TaskQueueStats & TaskQueueStats::operator +=(const TaskQueueStats & addend)
{
  for (unsigned int i = 0; i < last_stat_id; ++i) {
    _stats[i] += addend._stats[i];
  }
  return *this;
}
void TaskQueueStats::print_header(unsigned int line, outputStream* const stream,
                                  unsigned int width)
{
  const unsigned int max_width = 40;
  const unsigned int w = MAX2(MIN2(width, max_width), 1U);
  if (line == 0) { // spaces equal in width to the header
    const unsigned int hdr_width = w * last_stat_id + last_stat_id - 1;
    stream->print("%*s", hdr_width, " ");
  } else if (line == 1) { // labels
    stream->print("%*s", w, _names[0]);
    for (unsigned int i = 1; i < last_stat_id; ++i) {
      stream->print(" %*s", w, _names[i]);
    }
  } else if (line == 2) { // dashed lines
    char dashes[max_width + 1];
    memset(dashes, '-', w);
    dashes[w] = '\0';
    stream->print("%s", dashes);
    for (unsigned int i = 1; i < last_stat_id; ++i) {
      stream->print(" %s", dashes);
    }
  }
}
void TaskQueueStats::print(outputStream* stream, unsigned int width) const
{
  #define FMT SIZE_FORMAT_W(*)
  stream->print(FMT, width, _stats[0]);
  for (unsigned int i = 1; i < last_stat_id; ++i) {
    stream->print(" " FMT, width, _stats[i]);
  }
  #undef FMT
}
#ifdef ASSERT
void TaskQueueStats::verify() const
{
  assert(get(push) == get(pop) + get(steal),
         err_msg("push=" SIZE_FORMAT " pop=" SIZE_FORMAT " steal=" SIZE_FORMAT,
                 get(push), get(pop), get(steal)));
  assert(get(pop_slow) <= get(pop),
         err_msg("pop_slow=" SIZE_FORMAT " pop=" SIZE_FORMAT,
                 get(pop_slow), get(pop)));
  assert(get(steal) <= get(steal_attempt),
         err_msg("steal=" SIZE_FORMAT " steal_attempt=" SIZE_FORMAT,
                 get(steal), get(steal_attempt)));
  assert(get(overflow) == 0 || get(push) != 0,
         err_msg("overflow=" SIZE_FORMAT " push=" SIZE_FORMAT,
                 get(overflow), get(push)));
  assert(get(overflow_max_len) == 0 || get(overflow) != 0,
         err_msg("overflow_max_len=" SIZE_FORMAT " overflow=" SIZE_FORMAT,
                 get(overflow_max_len), get(overflow)));
}
#endif // ASSERT
#endif // TASKQUEUE_STATS
int TaskQueueSetSuper::randomParkAndMiller(int *seed0) {
  const int a =      16807;
  const int m = 2147483647;
  const int q =     127773;  /* m div a */
  const int r =       2836;  /* m mod a */
  assert(sizeof(int) == 4, "I think this relies on that");
  int seed = *seed0;
  int hi   = seed / q;
  int lo   = seed % q;
  int test = a * lo - r * hi;
  if (test > 0)
    seed = test;
  else
    seed = test + m;
  return seed;
}
ParallelTaskTerminator::
ParallelTaskTerminator(int n_threads, TaskQueueSetSuper* queue_set) :
  _n_threads(n_threads),
  _queue_set(queue_set),
  _offered_termination(0) {}
bool ParallelTaskTerminator::peek_in_queue_set() {
  return _queue_set->peek();
}
void ParallelTaskTerminator::yield() {
  assert(_offered_termination <= _n_threads, "Invariant");
  os::yield();
}
void ParallelTaskTerminator::sleep(uint millis) {
  assert(_offered_termination <= _n_threads, "Invariant");
  os::sleep(Thread::current(), millis, false);
}
bool
ParallelTaskTerminator::offer_termination(TerminatorTerminator* terminator) {
  assert(_n_threads > 0, "Initialization is incorrect");
  assert(_offered_termination < _n_threads, "Invariant");
  Atomic::inc(&_offered_termination);
  uint yield_count = 0;
  uint hard_spin_count = 0;
  uint hard_spin_limit = WorkStealingHardSpins;
  if (WorkStealingSpinToYieldRatio > 0) {
    hard_spin_limit = WorkStealingHardSpins >> WorkStealingSpinToYieldRatio;
    hard_spin_limit = MAX2(hard_spin_limit, 1U);
  }
  uint hard_spin_start = hard_spin_limit;
  while (true) {
    assert(_offered_termination <= _n_threads, "Invariant");
    if (_offered_termination == _n_threads) {
      return true;
    } else {
      if (yield_count <= WorkStealingYieldsBeforeSleep) {
        yield_count++;
        if (hard_spin_count > WorkStealingSpinToYieldRatio) {
          yield();
          hard_spin_count = 0;
          hard_spin_limit = hard_spin_start;
#ifdef TRACESPINNING
          _total_yields++;
#endif
        } else {
          hard_spin_limit = MIN2(2*hard_spin_limit,
                                 (uint) WorkStealingHardSpins);
          for (uint j = 0; j < hard_spin_limit; j++) {
            SpinPause();
          }
          hard_spin_count++;
#ifdef TRACESPINNING
          _total_spins++;
#endif
        }
      } else {
        if (PrintGCDetails && Verbose) {
         gclog_or_tty->print_cr("ParallelTaskTerminator::offer_termination() "
           "thread %d sleeps after %d yields",
           Thread::current(), yield_count);
        }
        yield_count = 0;
        sleep(WorkStealingSleepMillis);
      }
#ifdef TRACESPINNING
      _total_peeks++;
#endif
      if (peek_in_queue_set() ||
          (terminator != NULL && terminator->should_exit_termination())) {
        Atomic::dec(&_offered_termination);
        assert(_offered_termination < _n_threads, "Invariant");
        return false;
      }
    }
  }
}
#ifdef TRACESPINNING
void ParallelTaskTerminator::print_termination_counts() {
  gclog_or_tty->print_cr("ParallelTaskTerminator Total yields: " UINT32_FORMAT
    " Total spins: " UINT32_FORMAT " Total peeks: " UINT32_FORMAT,
    total_yields(),
    total_spins(),
    total_peeks());
}
#endif
void ParallelTaskTerminator::reset_for_reuse() {
  if (_offered_termination != 0) {
    assert(_offered_termination == _n_threads,
           "Terminator may still be in use");
    _offered_termination = 0;
  }
}
#ifdef ASSERT
bool ObjArrayTask::is_valid() const {
  return _obj != NULL && _obj->is_objArray() && _index > 0 &&
    _index < objArrayOop(_obj)->length();
}
#endif // ASSERT
void ParallelTaskTerminator::reset_for_reuse(int n_threads) {
  reset_for_reuse();
  _n_threads = n_threads;
}
C:\hotspot-69087d08d473\src\share\vm/utilities/taskqueue.hpp
#ifndef SHARE_VM_UTILITIES_TASKQUEUE_HPP
#define SHARE_VM_UTILITIES_TASKQUEUE_HPP
#include "memory/allocation.hpp"
#include "memory/allocation.inline.hpp"
#include "memory/padded.hpp"
#include "runtime/mutex.hpp"
#include "runtime/orderAccess.inline.hpp"
#include "utilities/globalDefinitions.hpp"
#include "utilities/stack.hpp"
#if !defined(TASKQUEUE_STATS) && defined(ASSERT)
#define TASKQUEUE_STATS 1
#elif !defined(TASKQUEUE_STATS)
#define TASKQUEUE_STATS 0
#endif
#if TASKQUEUE_STATS
#define TASKQUEUE_STATS_ONLY(code) code
#else
#define TASKQUEUE_STATS_ONLY(code)
#endif // TASKQUEUE_STATS
#if TASKQUEUE_STATS
class TaskQueueStats {
public:
  enum StatId {
    push,             // number of taskqueue pushes
    pop,              // number of taskqueue pops
    pop_slow,         // subset of taskqueue pops that were done slow-path
    steal_attempt,    // number of taskqueue steal attempts
    steal,            // number of taskqueue steals
    overflow,         // number of overflow pushes
    overflow_max_len, // max length of overflow stack
    last_stat_id
  };
public:
  inline TaskQueueStats()       { reset(); }
  inline void record_push()     { ++_stats[push]; }
  inline void record_pop()      { ++_stats[pop]; }
  inline void record_pop_slow() { record_pop(); ++_stats[pop_slow]; }
  inline void record_steal(bool success);
  inline void record_overflow(size_t new_length);
  TaskQueueStats & operator +=(const TaskQueueStats & addend);
  inline size_t get(StatId id) const { return _stats[id]; }
  inline const size_t* get() const   { return _stats; }
  inline void reset();
  static void print_header(unsigned int line, outputStream* const stream = tty,
                           unsigned int width = 10);
  void print(outputStream* const stream = tty, unsigned int width = 10) const;
  DEBUG_ONLY(void verify() const;)
private:
  size_t                    _stats[last_stat_id];
  static const char * const _names[last_stat_id];
};
void TaskQueueStats::record_steal(bool success) {
  ++_stats[steal_attempt];
  if (success) ++_stats[steal];
}
void TaskQueueStats::record_overflow(size_t new_len) {
  ++_stats[overflow];
  if (new_len > _stats[overflow_max_len]) _stats[overflow_max_len] = new_len;
}
void TaskQueueStats::reset() {
  memset(_stats, 0, sizeof(_stats));
}
#endif // TASKQUEUE_STATS
template <unsigned int N, MEMFLAGS F>
class TaskQueueSuper: public CHeapObj<F> {
protected:
  typedef NOT_LP64(uint16_t) LP64_ONLY(uint32_t) idx_t;
  enum { MOD_N_MASK = N - 1 };
  class Age {
  public:
    Age(size_t data = 0)         { _data = data; }
    Age(const Age& age)          { _data = age._data; }
    Age(idx_t top, idx_t tag)    { _fields._top = top; _fields._tag = tag; }
    Age   get()        const volatile { return _data; }
    void  set(Age age) volatile       { _data = age._data; }
    idx_t top()        const volatile { return _fields._top; }
    idx_t tag()        const volatile { return _fields._tag; }
    void increment() {
      _fields._top = increment_index(_fields._top);
      if (_fields._top == 0) ++_fields._tag;
    }
    Age cmpxchg(const Age new_age, const Age old_age) volatile {
      return (size_t) Atomic::cmpxchg_ptr((intptr_t)new_age._data,
                                          (volatile intptr_t *)&_data,
                                          (intptr_t)old_age._data);
    }
    bool operator ==(const Age& other) const { return _data == other._data; }
  private:
    struct fields {
      idx_t _top;
      idx_t _tag;
    };
    union {
      size_t _data;
      fields _fields;
    };
  };
  volatile uint _bottom;
  DEFINE_PAD_MINUS_SIZE(0, DEFAULT_CACHE_LINE_SIZE, sizeof(uint));
  volatile Age _age;
  static uint increment_index(uint ind) {
    return (ind + 1) & MOD_N_MASK;
  }
  static uint decrement_index(uint ind) {
    return (ind - 1) & MOD_N_MASK;
  }
  uint dirty_size(uint bot, uint top) const {
    return (bot - top) & MOD_N_MASK;
  }
  uint size(uint bot, uint top) const {
    uint sz = dirty_size(bot, top);
    return (sz == N - 1) ? 0 : sz;
  }
public:
  TaskQueueSuper() : _bottom(0), _age() {}
  bool peek()     const { return _bottom != _age.top(); }
  bool is_empty() const { return size() == 0; }
  uint size() const {
    return size(_bottom, _age.top());
  }
  uint dirty_size() const {
    return dirty_size(_bottom, _age.top());
  }
  void set_empty() {
    _bottom = 0;
    _age.set(0);
  }
  uint max_elems() const { return N - 2; }
  static const uint total_size() { return N; }
  TASKQUEUE_STATS_ONLY(TaskQueueStats stats;)
};
template <class E, MEMFLAGS F, unsigned int N = TASKQUEUE_SIZE>
class GenericTaskQueue: public TaskQueueSuper<N, F> {
  ArrayAllocator<E, F> _array_allocator;
protected:
  typedef typename TaskQueueSuper<N, F>::Age Age;
  typedef typename TaskQueueSuper<N, F>::idx_t idx_t;
  using TaskQueueSuper<N, F>::_bottom;
  using TaskQueueSuper<N, F>::_age;
  using TaskQueueSuper<N, F>::increment_index;
  using TaskQueueSuper<N, F>::decrement_index;
  using TaskQueueSuper<N, F>::dirty_size;
public:
  using TaskQueueSuper<N, F>::max_elems;
  using TaskQueueSuper<N, F>::size;
#if  TASKQUEUE_STATS
  using TaskQueueSuper<N, F>::stats;
#endif
private:
  bool push_slow(E t, uint dirty_n_elems);
  bool pop_local_slow(uint localBot, Age oldAge);
public:
  typedef E element_type;
  GenericTaskQueue();
  void initialize();
  inline bool push(E t);
  inline bool pop_local(volatile E& t);
  bool pop_global(volatile E& t);
  ~GenericTaskQueue();
  void oops_do(OopClosure* f);
private:
  volatile E* _elems;
};
template<class E, MEMFLAGS F, unsigned int N>
GenericTaskQueue<E, F, N>::GenericTaskQueue() {
  assert(sizeof(Age) == sizeof(size_t), "Depends on this.");
}
template<class E, MEMFLAGS F, unsigned int N>
void GenericTaskQueue<E, F, N>::initialize() {
  _elems = _array_allocator.allocate(N);
}
template<class E, MEMFLAGS F, unsigned int N>
void GenericTaskQueue<E, F, N>::oops_do(OopClosure* f) {
  uint iters = size();
  uint index = _bottom;
  for (uint i = 0; i < iters; ++i) {
    index = decrement_index(index);
    E* t = (E*)&_elems[index];      // cast away volatility
    oop* p = (oop*)t;
    assert(UseG1GC || (*t)->is_oop_or_null(), "Not an oop or null");
    f->do_oop(p);
  }
}
template<class E, MEMFLAGS F, unsigned int N>
bool GenericTaskQueue<E, F, N>::push_slow(E t, uint dirty_n_elems) {
  if (dirty_n_elems == N - 1) {
    uint localBot = _bottom;
    (void)const_cast<E&>(_elems[localBot] = t);
    OrderAccess::release_store(&_bottom, increment_index(localBot));
    TASKQUEUE_STATS_ONLY(stats.record_push());
    return true;
  }
  return false;
}
template<class E, MEMFLAGS F, unsigned int N>
bool GenericTaskQueue<E, F, N>::pop_local_slow(uint localBot, Age oldAge) {
  Age newAge((idx_t)localBot, oldAge.tag() + 1);
  if (localBot == oldAge.top()) {
    Age tempAge = _age.cmpxchg(newAge, oldAge);
    if (tempAge == oldAge) {
      assert(dirty_size(localBot, _age.top()) != N - 1, "sanity");
      TASKQUEUE_STATS_ONLY(stats.record_pop_slow());
      return true;
    }
  }
  _age.set(newAge);
  assert(dirty_size(localBot, _age.top()) != N - 1, "sanity");
  return false;
}
template<class E, MEMFLAGS F, unsigned int N>
bool GenericTaskQueue<E, F, N>::pop_global(volatile E& t) {
  Age oldAge = _age.get();
#if !(defined SPARC || defined IA32 || defined AMD64)
  OrderAccess::fence();
#endif
  uint localBot = OrderAccess::load_acquire((volatile juint*)&_bottom);
  uint n_elems = size(localBot, oldAge.top());
  if (n_elems == 0) {
    return false;
  }
  (void) const_cast<E&>(t = _elems[oldAge.top()]);
  Age newAge(oldAge);
  newAge.increment();
  Age resAge = _age.cmpxchg(newAge, oldAge);
  assert(dirty_size(localBot, newAge.top()) != N - 1, "sanity");
  return resAge == oldAge;
}
template<class E, MEMFLAGS F, unsigned int N>
GenericTaskQueue<E, F, N>::~GenericTaskQueue() {}
template<class E, MEMFLAGS F, unsigned int N = TASKQUEUE_SIZE>
class OverflowTaskQueue: public GenericTaskQueue<E, F, N>
{
public:
  typedef Stack<E, F>               overflow_t;
  typedef GenericTaskQueue<E, F, N> taskqueue_t;
  TASKQUEUE_STATS_ONLY(using taskqueue_t::stats;)
  inline bool push(E t);
  inline bool try_push_to_taskqueue(E t);
  inline bool pop_overflow(E& t);
  inline overflow_t* overflow_stack() { return &_overflow_stack; }
  inline bool taskqueue_empty() const { return taskqueue_t::is_empty(); }
  inline bool overflow_empty()  const { return _overflow_stack.is_empty(); }
  inline bool is_empty()        const {
    return taskqueue_empty() && overflow_empty();
  }
private:
  overflow_t _overflow_stack;
};
template <class E, MEMFLAGS F, unsigned int N>
bool OverflowTaskQueue<E, F, N>::push(E t)
{
  if (!taskqueue_t::push(t)) {
    overflow_stack()->push(t);
    TASKQUEUE_STATS_ONLY(stats.record_overflow(overflow_stack()->size()));
  }
  return true;
}
template <class E, MEMFLAGS F, unsigned int N>
bool OverflowTaskQueue<E, F, N>::pop_overflow(E& t)
{
  if (overflow_empty()) return false;
  t = overflow_stack()->pop();
  return true;
}
template <class E, MEMFLAGS F, unsigned int N>
bool OverflowTaskQueue<E, F, N>::try_push_to_taskqueue(E t) {
  return taskqueue_t::push(t);
}
class TaskQueueSetSuper {
protected:
  static int randomParkAndMiller(int* seed0);
public:
  virtual bool peek() = 0;
};
template <MEMFLAGS F> class TaskQueueSetSuperImpl: public CHeapObj<F>, public TaskQueueSetSuper {
};
template<class T, MEMFLAGS F>
class GenericTaskQueueSet: public TaskQueueSetSuperImpl<F> {
private:
  uint _n;
  T** _queues;
public:
  typedef typename T::element_type E;
  GenericTaskQueueSet(int n) : _n(n) {
    typedef T* GenericTaskQueuePtr;
    _queues = NEW_C_HEAP_ARRAY(GenericTaskQueuePtr, n, F);
    for (int i = 0; i < n; i++) {
      _queues[i] = NULL;
    }
  }
  bool steal_best_of_2(uint queue_num, int* seed, E& t);
  void register_queue(uint i, T* q);
  T* queue(uint n);
  bool steal(uint queue_num, int* seed, E& t);
  bool peek();
};
template<class T, MEMFLAGS F> void
GenericTaskQueueSet<T, F>::register_queue(uint i, T* q) {
  assert(i < _n, "index out of range.");
  _queues[i] = q;
}
template<class T, MEMFLAGS F> T*
GenericTaskQueueSet<T, F>::queue(uint i) {
  return _queues[i];
}
template<class T, MEMFLAGS F> bool
GenericTaskQueueSet<T, F>::steal(uint queue_num, int* seed, E& t) {
  for (uint i = 0; i < 2 * _n; i++) {
    if (steal_best_of_2(queue_num, seed, t)) {
      TASKQUEUE_STATS_ONLY(queue(queue_num)->stats.record_steal(true));
      return true;
    }
  }
  TASKQUEUE_STATS_ONLY(queue(queue_num)->stats.record_steal(false));
  return false;
}
template<class T, MEMFLAGS F> bool
GenericTaskQueueSet<T, F>::steal_best_of_2(uint queue_num, int* seed, E& t) {
  if (_n > 2) {
    uint k1 = queue_num;
    while (k1 == queue_num) k1 = TaskQueueSetSuper::randomParkAndMiller(seed) % _n;
    uint k2 = queue_num;
    while (k2 == queue_num || k2 == k1) k2 = TaskQueueSetSuper::randomParkAndMiller(seed) % _n;
    uint sz1 = _queues[k1]->size();
    uint sz2 = _queues[k2]->size();
    if (sz2 > sz1) return _queues[k2]->pop_global(t);
    else return _queues[k1]->pop_global(t);
  } else if (_n == 2) {
    uint k = (queue_num + 1) % 2;
    return _queues[k]->pop_global(t);
  } else {
    assert(_n == 1, "can't be zero.");
    return false;
  }
}
template<class T, MEMFLAGS F>
bool GenericTaskQueueSet<T, F>::peek() {
  for (uint j = 0; j < _n; j++) {
    if (_queues[j]->peek())
      return true;
  }
  return false;
}
class TerminatorTerminator: public CHeapObj<mtInternal> {
public:
  virtual bool should_exit_termination() = 0;
};
#undef TRACESPINNING
class ParallelTaskTerminator: public StackObj {
private:
  int _n_threads;
  TaskQueueSetSuper* _queue_set;
  char _pad_before[DEFAULT_CACHE_LINE_SIZE];
  int _offered_termination;
  char _pad_after[DEFAULT_CACHE_LINE_SIZE];
#ifdef TRACESPINNING
  static uint _total_yields;
  static uint _total_spins;
  static uint _total_peeks;
#endif
  bool peek_in_queue_set();
protected:
  virtual void yield();
  void sleep(uint millis);
public:
  ParallelTaskTerminator(int n_threads, TaskQueueSetSuper* queue_set);
  bool offer_termination() {
    return offer_termination(NULL);
  }
  bool offer_termination(TerminatorTerminator* terminator);
  void reset_for_reuse();
  void reset_for_reuse(int n_threads);
#ifdef TRACESPINNING
  static uint total_yields() { return _total_yields; }
  static uint total_spins() { return _total_spins; }
  static uint total_peeks() { return _total_peeks; }
  static void print_termination_counts();
#endif
};
template<class E, MEMFLAGS F, unsigned int N> inline bool
GenericTaskQueue<E, F, N>::push(E t) {
  uint localBot = _bottom;
  assert(localBot < N, "_bottom out of range.");
  idx_t top = _age.top();
  uint dirty_n_elems = dirty_size(localBot, top);
  assert(dirty_n_elems < N, "n_elems out of range.");
  if (dirty_n_elems < max_elems()) {
    (void) const_cast<E&>(_elems[localBot] = t);
    OrderAccess::release_store(&_bottom, increment_index(localBot));
    TASKQUEUE_STATS_ONLY(stats.record_push());
    return true;
  } else {
    return push_slow(t, dirty_n_elems);
  }
}
template<class E, MEMFLAGS F, unsigned int N> inline bool
GenericTaskQueue<E, F, N>::pop_local(volatile E& t) {
  uint localBot = _bottom;
  uint dirty_n_elems = dirty_size(localBot, _age.top());
  assert(dirty_n_elems != N - 1, "Shouldn't be possible...");
  if (dirty_n_elems == 0) return false;
  localBot = decrement_index(localBot);
  _bottom = localBot;
  OrderAccess::fence();
  (void) const_cast<E&>(t = _elems[localBot]);
  idx_t tp = _age.top();    // XXX
  if (size(localBot, tp) > 0) {
    assert(dirty_size(localBot, tp) != N - 1, "sanity");
    TASKQUEUE_STATS_ONLY(stats.record_pop());
    return true;
  } else {
    OrderAccess::loadload();
    return pop_local_slow(localBot, _age.get());
  }
}
typedef GenericTaskQueue<oop, mtGC>             OopTaskQueue;
typedef GenericTaskQueueSet<OopTaskQueue, mtGC> OopTaskQueueSet;
#ifdef _MSC_VER
#pragma warning(push)
#pragma warning(disable:4522)
#endif
class StarTask {
  void*  _holder;        // either union oop* or narrowOop*
  enum { COMPRESSED_OOP_MASK = 1 };
 public:
  StarTask(narrowOop* p) {
    assert(((uintptr_t)p & COMPRESSED_OOP_MASK) == 0, "Information loss!");
    _holder = (void *)((uintptr_t)p | COMPRESSED_OOP_MASK);
  }
  StarTask(oop* p)       {
    assert(((uintptr_t)p & COMPRESSED_OOP_MASK) == 0, "Information loss!");
    _holder = (void*)p;
  }
  StarTask()             { _holder = NULL; }
  operator oop*()        { return (oop*)_holder; }
  operator narrowOop*()  {
    return (narrowOop*)((uintptr_t)_holder & ~COMPRESSED_OOP_MASK);
  }
  StarTask& operator=(const StarTask& t) {
    _holder = t._holder;
    return *this;
  }
  volatile StarTask& operator=(const volatile StarTask& t) volatile {
    _holder = t._holder;
    return *this;
  }
  bool is_narrow() const {
    return (((uintptr_t)_holder & COMPRESSED_OOP_MASK) != 0);
  }
};
class ObjArrayTask
{
public:
  ObjArrayTask(oop o = NULL, int idx = 0): _obj(o), _index(idx) { }
  ObjArrayTask(oop o, size_t idx): _obj(o), _index(int(idx)) {
    assert(idx <= size_t(max_jint), "too big");
  }
  ObjArrayTask(const ObjArrayTask& t): _obj(t._obj), _index(t._index) { }
  ObjArrayTask& operator =(const ObjArrayTask& t) {
    _obj = t._obj;
    _index = t._index;
    return *this;
  }
  volatile ObjArrayTask&
  operator =(const volatile ObjArrayTask& t) volatile {
    (void)const_cast<oop&>(_obj = t._obj);
    _index = t._index;
    return *this;
  }
  inline oop obj()   const { return _obj; }
  inline int index() const { return _index; }
  DEBUG_ONLY(bool is_valid() const); // Tasks to be pushed/popped must be valid.
private:
  oop _obj;
  int _index;
};
#ifdef _MSC_VER
#pragma warning(pop)
#endif
typedef OverflowTaskQueue<StarTask, mtClass>           OopStarTaskQueue;
typedef GenericTaskQueueSet<OopStarTaskQueue, mtClass> OopStarTaskQueueSet;
typedef OverflowTaskQueue<size_t, mtInternal>             RegionTaskQueue;
typedef GenericTaskQueueSet<RegionTaskQueue, mtClass>     RegionTaskQueueSet;
#endif // SHARE_VM_UTILITIES_TASKQUEUE_HPP
C:\hotspot-69087d08d473\src\share\vm/utilities/ticks.cpp
#include "precompiled.hpp"
#include "runtime/os.hpp"
#include "utilities/ticks.hpp"
#if defined(X86) && !defined(ZERO)
#include "rdtsc_x86.hpp"
#endif
template <typename TimeSource, const int unit>
inline double conversion(typename TimeSource::Type& value) {
  return (double)value * ((double)unit / (double)TimeSource::frequency());
}
uint64_t ElapsedCounterSource::frequency() {
  static const uint64_t freq = (uint64_t)os::elapsed_frequency();
  return freq;
}
ElapsedCounterSource::Type ElapsedCounterSource::now() {
  return os::elapsed_counter();
}
double ElapsedCounterSource::seconds(Type value) {
  return conversion<ElapsedCounterSource, 1>(value);
}
uint64_t ElapsedCounterSource::milliseconds(Type value) {
  return (uint64_t)conversion<ElapsedCounterSource, MILLIUNITS>(value);
}
uint64_t ElapsedCounterSource::microseconds(Type value) {
  return (uint64_t)conversion<ElapsedCounterSource, MICROUNITS>(value);
}
uint64_t ElapsedCounterSource::nanoseconds(Type value) {
  return (uint64_t)conversion<ElapsedCounterSource, NANOUNITS>(value);
}
uint64_t FastUnorderedElapsedCounterSource::frequency() {
#if defined(X86) && !defined(ZERO)
  static bool valid_rdtsc = Rdtsc::initialize();
  if (valid_rdtsc) {
    static const uint64_t freq = (uint64_t)Rdtsc::frequency();
    return freq;
  }
#endif
  static const uint64_t freq = (uint64_t)os::elapsed_frequency();
  return freq;
}
FastUnorderedElapsedCounterSource::Type FastUnorderedElapsedCounterSource::now() {
#if defined(X86) && !defined(ZERO)
  static bool valid_rdtsc = Rdtsc::initialize();
  if (valid_rdtsc) {
    return Rdtsc::elapsed_counter();
  }
#endif
  return os::elapsed_counter();
}
double FastUnorderedElapsedCounterSource::seconds(Type value) {
  return conversion<FastUnorderedElapsedCounterSource, 1>(value);
}
uint64_t FastUnorderedElapsedCounterSource::milliseconds(Type value) {
  return (uint64_t)conversion<FastUnorderedElapsedCounterSource, MILLIUNITS>(value);
}
uint64_t FastUnorderedElapsedCounterSource::microseconds(Type value) {
  return (uint64_t)conversion<FastUnorderedElapsedCounterSource, MICROUNITS>(value);
}
uint64_t FastUnorderedElapsedCounterSource::nanoseconds(Type value) {
  return (uint64_t)conversion<FastUnorderedElapsedCounterSource, NANOUNITS>(value);
}
uint64_t CompositeElapsedCounterSource::frequency() {
  return ElapsedCounterSource::frequency();
}
CompositeElapsedCounterSource::Type CompositeElapsedCounterSource::now() {
  CompositeTime ct;
  ct.val1 = ElapsedCounterSource::now();
#if defined(X86) && !defined(ZERO)
  static bool initialized = false;
  static bool valid_rdtsc = false;
  if (!initialized) {
    valid_rdtsc = Rdtsc::initialize();
    initialized = true;
  }
  if (valid_rdtsc) {
    ct.val2 = Rdtsc::elapsed_counter();
  }
#endif
  return ct;
}
double CompositeElapsedCounterSource::seconds(Type value) {
  return conversion<ElapsedCounterSource, 1>(value.val1);
}
uint64_t CompositeElapsedCounterSource::milliseconds(Type value) {
  return (uint64_t)conversion<ElapsedCounterSource, MILLIUNITS>(value.val1);
}
uint64_t CompositeElapsedCounterSource::microseconds(Type value) {
  return (uint64_t)conversion<ElapsedCounterSource, MICROUNITS>(value.val1);
}
uint64_t CompositeElapsedCounterSource::nanoseconds(Type value) {
  return (uint64_t)conversion<ElapsedCounterSource, NANOUNITS>(value.val1);
}
C:\hotspot-69087d08d473\src\share\vm/utilities/ticks.hpp
#ifndef SHARE_VM_UTILITIES_TICKS_HPP
#define SHARE_VM_UTILITIES_TICKS_HPP
#include "jni.h"
#include "memory/allocation.hpp"
#include "utilities/macros.hpp"
class ElapsedCounterSource {
 public:
  typedef jlong Type;
  static uint64_t frequency();
  static Type now();
  static double seconds(Type value);
  static uint64_t milliseconds(Type value);
  static uint64_t microseconds(Type value);
  static uint64_t nanoseconds(Type value);
};
class FastUnorderedElapsedCounterSource {
 public:
  typedef jlong Type;
  static uint64_t frequency();
  static Type now();
  static double seconds(Type value);
  static uint64_t milliseconds(Type value);
  static uint64_t microseconds(Type value);
  static uint64_t nanoseconds(Type value);
};
template <typename T1, typename T2>
class PairRep {
 public:
  T1 val1;
  T2 val2;
  PairRep() : val1((T1)0), val2((T2)0) {}
  void operator+=(const PairRep& rhs) {
    val1 += rhs.val1;
    val2 += rhs.val2;
  }
  void operator-=(const PairRep& rhs) {
    val1 -= rhs.val1;
    val2 -= rhs.val2;
  }
  bool operator==(const PairRep& rhs) const {
    return val1 == rhs.val1;
  }
  bool operator!=(const PairRep& rhs) const {
    return !operator==(rhs);
  }
  bool operator<(const PairRep& rhs) const {
    return val1 < rhs.val1;
  }
  bool operator>(const PairRep& rhs) const {
    return val1 > rhs.val1;
  }
};
template <typename T1, typename T2>
PairRep<T1, T2> operator-(const PairRep<T1, T2>& lhs, const PairRep<T1, T2>& rhs) {
  PairRep<T1, T2> temp(lhs);
  temp -= rhs;
  return temp;
}
typedef PairRep<ElapsedCounterSource::Type, FastUnorderedElapsedCounterSource::Type> CompositeTime;
class CompositeElapsedCounterSource {
 public:
  typedef CompositeTime Type;
  static uint64_t frequency();
  static Type now();
  static double seconds(Type value);
  static uint64_t milliseconds(Type value);
  static uint64_t microseconds(Type value);
  static uint64_t nanoseconds(Type value);
};
template <typename TimeSource>
class Representation {
 public:
  typedef typename TimeSource::Type Type;
 protected:
  Type _rep;
  Representation(const Representation<TimeSource>& end, const Representation<TimeSource>& start) : _rep(end._rep - start._rep) {}
  Representation() : _rep() {}
 public:
  void operator+=(const Representation<TimeSource>& rhs) {
    _rep += rhs._rep;
  }
  void operator-=(const Representation<TimeSource>& rhs) {
    _rep -= rhs._rep;
  }
  bool operator==(const Representation<TimeSource>& rhs) const {
    return _rep == rhs._rep;
  }
  bool operator!=(const Representation<TimeSource>& rhs) const {
    return !operator==(rhs);
  }
  bool operator<(const Representation<TimeSource>& rhs) const {
    return _rep < rhs._rep;
  }
  bool operator>(const Representation<TimeSource>& rhs) const {
    return _rep > rhs._rep;
  }
  bool operator<=(const Representation<TimeSource>& rhs) const {
    return !operator>(rhs);
  }
  bool operator>=(const Representation<TimeSource>& rhs) const {
    return !operator<(rhs);
  }
  double seconds() const {
    return TimeSource::seconds(_rep);
  }
  uint64_t milliseconds() const {
    return TimeSource::milliseconds(_rep);
  }
  uint64_t microseconds() const {
    return TimeSource::microseconds(_rep);
  }
  uint64_t nanoseconds() const {
    return TimeSource::nanoseconds(_rep);
  }
};
template <typename TimeSource>
class CounterRepresentation : public Representation<TimeSource> {
 protected:
  CounterRepresentation(const CounterRepresentation& end, const CounterRepresentation& start) : Representation<TimeSource>(end, start) {}
  explicit CounterRepresentation(jlong value) : Representation<TimeSource>() {
    this->_rep = value;
  }
 public:
  CounterRepresentation() : Representation<TimeSource>() {}
  typename TimeSource::Type value() const { return this->_rep; }
  operator typename TimeSource::Type() { return value(); }
};
template <typename TimeSource>
class CompositeCounterRepresentation : public Representation<TimeSource> {
 protected:
  CompositeCounterRepresentation(const CompositeCounterRepresentation& end, const CompositeCounterRepresentation& start) :
    Representation<TimeSource>(end, start) {}
  explicit CompositeCounterRepresentation(jlong value) : Representation<TimeSource>() {
    this->_rep.val1 = value;
    this->_rep.val2 = value;
  }
 public:
  CompositeCounterRepresentation() : Representation<TimeSource>() {}
  ElapsedCounterSource::Type value() const { return this->_rep.val1; }
  FastUnorderedElapsedCounterSource::Type ft_value() const { return this->_rep.val2; }
};
template <template <typename> class, typename>
class TimeInstant;
template <template <typename> class Rep, typename TimeSource>
class TimeInterval : public Rep<TimeSource> {
  template <template <typename> class, typename>
  friend class TimeInstant;
  TimeInterval(const TimeInstant<Rep, TimeSource>& end, const TimeInstant<Rep, TimeSource>& start) : Rep<TimeSource>(end, start) {}
 public:
  TimeInterval() : Rep<TimeSource>() {}
  TimeInterval<Rep, TimeSource> operator+(const TimeInterval<Rep, TimeSource>& rhs) const {
    TimeInterval<Rep, TimeSource> temp(*this);
    temp += rhs;
    return temp;
  }
  TimeInterval<Rep, TimeSource> operator-(const TimeInterval<Rep, TimeSource>& rhs) const {
    TimeInterval<Rep, TimeSource> temp(*this);
    temp -= rhs;
    return temp;
  }
};
template <template <typename> class Rep, typename TimeSource>
class TimeInstant : public Rep<TimeSource> {
 public:
  TimeInstant() : Rep<TimeSource>() {}
  TimeInstant<Rep, TimeSource>& operator+=(const TimeInterval<Rep, TimeSource>& rhs) {
    Rep<TimeSource>::operator+=(rhs);
    return *this;
  }
  TimeInstant<Rep, TimeSource>& operator-=(const TimeInterval<Rep, TimeSource>& rhs) {
    Rep<TimeSource>::operator-=(rhs);
    return *this;
  }
  TimeInterval<Rep, TimeSource> operator+(const TimeInstant<Rep, TimeSource>& end) const {
    return TimeInterval<Rep, TimeSource>(end, *this);
  }
  TimeInterval<Rep, TimeSource> operator-(const TimeInstant<Rep, TimeSource>& start) const {
    return TimeInterval<Rep, TimeSource>(*this, start);
  }
  void stamp() {
    this->_rep = TimeSource::now();
  }
  static TimeInstant<Rep, TimeSource> now() {
    TimeInstant<Rep, TimeSource> temp;
    temp.stamp();
    return temp;
  }
 private:
  TimeInstant(jlong ticks) : Rep<TimeSource>(ticks) {}
  friend class GranularTimer;
  friend class ObjectSample;
  friend class TimePartitionPhasesIteratorTest;
  friend class GCTimerTest;
};
#if INCLUDE_JFR
typedef TimeInstant<CompositeCounterRepresentation, CompositeElapsedCounterSource> Ticks;
typedef TimeInterval<CompositeCounterRepresentation, CompositeElapsedCounterSource> Tickspan;
#else
typedef TimeInstant<CounterRepresentation, ElapsedCounterSource> Ticks;
typedef TimeInterval<CounterRepresentation, ElapsedCounterSource> Tickspan;
#endif
#endif // SHARE_VM_UTILITIES_TICKS_HPP
C:\hotspot-69087d08d473\src\share\vm/utilities/top.hpp
#ifndef SHARE_VM_UTILITIES_TOP_HPP
#define SHARE_VM_UTILITIES_TOP_HPP
#include "oops/oopsHierarchy.hpp"
#include "runtime/globals.hpp"
#include "utilities/debug.hpp"
#include "utilities/exceptions.hpp"
#include "utilities/globalDefinitions.hpp"
#include "utilities/macros.hpp"
#include "utilities/ostream.hpp"
#include "utilities/sizes.hpp"
#if INCLUDE_ALL_GCS
#include "gc_implementation/g1/g1_globals.hpp"
#endif // INCLUDE_ALL_GCS
#ifdef COMPILER1
#include "c1/c1_globals.hpp"
#endif
#ifdef COMPILER2
#include "opto/c2_globals.hpp"
#endif
#endif // SHARE_VM_UTILITIES_TOP_HPP
C:\hotspot-69087d08d473\src\share\vm/utilities/utf8.cpp
#include "precompiled.hpp"
#include "utilities/utf8.hpp"
char* UTF8::next(const char* str, jchar* value) {
  unsigned const char *ptr = (const unsigned char *)str;
  unsigned char ch, ch2, ch3;
  int length = -1;              /* bad length */
  jchar result;
  switch ((ch = ptr[0]) >> 4) {
    default:
    result = ch;
    length = 1;
    break;
  case 0x8: case 0x9: case 0xA: case 0xB: case 0xF:
    break;
  case 0xC: case 0xD:
    if (((ch2 = ptr[1]) & 0xC0) == 0x80) {
      unsigned char high_five = ch & 0x1F;
      unsigned char low_six = ch2 & 0x3F;
      result = (high_five << 6) + low_six;
      length = 2;
      break;
    }
    break;
  case 0xE:
    if (((ch2 = ptr[1]) & 0xC0) == 0x80) {
      if (((ch3 = ptr[2]) & 0xC0) == 0x80) {
        unsigned char high_four = ch & 0x0f;
        unsigned char mid_six = ch2 & 0x3f;
        unsigned char low_six = ch3 & 0x3f;
        result = (((high_four << 6) + mid_six) << 6) + low_six;
        length = 3;
      }
    }
    break;
  } /* end of switch */
  if (length <= 0) {
    return (char*)(ptr + 1); // make progress somehow
  }
  return (char *)(ptr + length);
}
char* UTF8::next_character(const char* str, jint* value) {
  unsigned const char *ptr = (const unsigned char *)str;
     11101101 1010xxxx 10xxxxxx 11101101 1011xxxx 10xxxxxx */
  if (is_supplementary_character(ptr)) {
    return (char *)(ptr + 6);
  }
  jchar result;
  char* next_ch = next(str, &result);
  return next_ch;
}
int UTF8::unicode_length(const char* str, int len) {
  int num_chars = len;
  for (int i = 0; i < len; i++) {
    if ((str[i] & 0xC0) == 0x80) {
      --num_chars;
    }
  }
  return num_chars;
}
int UTF8::unicode_length(const char* str) {
  int num_chars = 0;
  for (const char* p = str; *p; p++) {
    if (((*p) & 0xC0) != 0x80) {
      num_chars++;
    }
  }
  return num_chars;
}
static u_char* utf8_write(u_char* base, jchar ch) {
  if ((ch != 0) && (ch <=0x7f)) {
    base[0] = (u_char) ch;
    return base + 1;
  }
  if (ch <= 0x7FF) {
    unsigned char high_five = ch >> 6;
    unsigned char low_six = ch & 0x3F;
    base[0] = high_five | 0xC0; /* 110xxxxx */
    base[1] = low_six | 0x80;   /* 10xxxxxx */
    return base + 2;
  }
  char high_four = ch >> 12;
  char mid_six = (ch >> 6) & 0x3F;
  char low_six = ch & 0x3f;
  base[0] = high_four | 0xE0; /* 1110xxxx */
  base[1] = mid_six | 0x80;   /* 10xxxxxx */
  base[2] = low_six | 0x80;   /* 10xxxxxx */
  return base + 3;
}
void UTF8::convert_to_unicode(const char* utf8_str, jchar* unicode_str, int unicode_length) {
  unsigned char ch;
  const char *ptr = utf8_str;
  int index = 0;
  for (; index < unicode_length; index++) {
    if((ch = ptr[0]) > 0x7F) { break; }
    unicode_str[index] = ch;
    ptr = (const char *)(ptr + 1);
  }
  for (; index < unicode_length; index++) {
    ptr = UTF8::next(ptr, &unicode_str[index]);
  }
}
int UTF8::quoted_ascii_length(const char* utf8_str, int utf8_length) {
  const char *ptr = utf8_str;
  const char* end = ptr + utf8_length;
  int result = 0;
  while (ptr < end) {
    jchar c;
    ptr = UTF8::next(ptr, &c);
    if (c >= 32 && c < 127) {
      result++;
    } else {
      result += 6;
    }
  }
  return result;
}
void UTF8::as_quoted_ascii(const char* utf8_str, int utf8_length, char* buf, int buflen) {
  const char *ptr = utf8_str;
  const char *utf8_end = ptr + utf8_length;
  char* p = buf;
  char* end = buf + buflen;
  while (ptr < utf8_end) {
    jchar c;
    ptr = UTF8::next(ptr, &c);
    if (c >= 32 && c < 127) {
      if (p + 1 >= end) break;      // string is truncated
    } else {
      if (p + 6 >= end) break;      // string is truncated
      sprintf(p, "\\u%04x", c);
      p += 6;
    }
  }
  assert(p < end, "sanity");
}
const char* UTF8::from_quoted_ascii(const char* quoted_ascii_str) {
  const char *ptr = quoted_ascii_str;
  char* result = NULL;
  while (*ptr != '\0') {
    char c = *ptr;
    if (c < 32 || c >= 127) break;
  }
  if (*ptr == '\0') {
    return quoted_ascii_str;
  }
  int length = ptr - quoted_ascii_str;
  char* buffer = NULL;
  for (int round = 0; round < 2; round++) {
    while (*ptr != '\0') {
      if (*ptr != '\\') {
        if (buffer != NULL) {
          buffer[length] = *ptr;
        }
        length++;
      } else {
        switch (ptr[1]) {
          case 'u': {
            ptr += 2;
            jchar value=0;
            for (int i=0; i<4; i++) {
              char c = *ptr++;
              switch (c) {
                case '0': case '1': case '2': case '3': case '4':
                case '5': case '6': case '7': case '8': case '9':
                  value = (value << 4) + c - '0';
                  break;
                case 'a': case 'b': case 'c':
                case 'd': case 'e': case 'f':
                  value = (value << 4) + 10 + c - 'a';
                  break;
                case 'A': case 'B': case 'C':
                case 'D': case 'E': case 'F':
                  value = (value << 4) + 10 + c - 'A';
                  break;
                default:
                  ShouldNotReachHere();
              }
            }
            if (buffer == NULL) {
              char utf8_buffer[4];
              char* next = (char*)utf8_write((u_char*)utf8_buffer, value);
              length += next - utf8_buffer;
            } else {
              char* next = (char*)utf8_write((u_char*)&buffer[length], value);
              length += next - &buffer[length];
            }
            break;
          }
          case 't': if (buffer != NULL) buffer[length] = '\t'; ptr += 2; length++; break;
          case 'n': if (buffer != NULL) buffer[length] = '\n'; ptr += 2; length++; break;
          case 'r': if (buffer != NULL) buffer[length] = '\r'; ptr += 2; length++; break;
          case 'f': if (buffer != NULL) buffer[length] = '\f'; ptr += 2; length++; break;
          default:
            ShouldNotReachHere();
        }
      }
    }
    if (round == 0) {
      buffer = NEW_RESOURCE_ARRAY(char, length + 1);
      ptr = quoted_ascii_str;
    } else {
      buffer[length] = '\0';
    }
  }
  return buffer;
}
const jbyte* UTF8::strrchr(const jbyte* base, int length, jbyte c) {
  assert(length >= 0, "sanity check");
  assert(c >= 0, "does not work for non-ASCII characters");
  while(--length >= 0 && base[length] != c);
  return (length < 0) ? NULL : &base[length];
}
bool UTF8::equal(const jbyte* base1, int length1, const jbyte* base2, int length2) {
  if (length1 != length2) return false;
  for (int i = 0; i < length1; i++) {
    if (base1[i] != base2[i]) return false;
  }
  return true;
}
bool UTF8::is_supplementary_character(const unsigned char* str) {
  return ((str[0] & 0xFF) == 0xED) && ((str[1] & 0xF0) == 0xA0) && ((str[2] & 0xC0) == 0x80)
      && ((str[3] & 0xFF) == 0xED) && ((str[4] & 0xF0) == 0xB0) && ((str[5] & 0xC0) == 0x80);
}
jint UTF8::get_supplementary_character(const unsigned char* str) {
  return 0x10000 + ((str[1] & 0x0f) << 16) + ((str[2] & 0x3f) << 10)
                 + ((str[4] & 0x0f) << 6)  + (str[5] & 0x3f);
}
int UNICODE::utf8_size(jchar c) {
  if ((0x0001 <= c) && (c <= 0x007F)) return 1;
  if (c <= 0x07FF) return 2;
  return 3;
}
int UNICODE::utf8_length(jchar* base, int length) {
  int result = 0;
  for (int index = 0; index < length; index++) {
    jchar c = base[index];
    if ((0x0001 <= c) && (c <= 0x007F)) result += 1;
    else if (c <= 0x07FF) result += 2;
    else result += 3;
  }
  return result;
}
char* UNICODE::as_utf8(jchar* base, int length) {
  int utf8_len = utf8_length(base, length);
  u_char* result = NEW_RESOURCE_ARRAY(u_char, utf8_len + 1);
  u_char* p = result;
  for (int index = 0; index < length; index++) {
    p = utf8_write(p, base[index]);
  }
  assert(p == &result[utf8_len], "length prediction must be correct");
  return (char*) result;
}
char* UNICODE::as_utf8(jchar* base, int length, char* buf, int buflen) {
  u_char* p = (u_char*)buf;
  u_char* end = (u_char*)buf + buflen;
  for (int index = 0; index < length; index++) {
    jchar c = base[index];
    if (p + utf8_size(c) >= end) break;      // string is truncated
    p = utf8_write(p, base[index]);
  }
  return buf;
}
void UNICODE::convert_to_utf8(const jchar* base, int length, char* utf8_buffer) {
  for(int index = 0; index < length; index++) {
    utf8_buffer = (char*)utf8_write((u_char*)utf8_buffer, base[index]);
  }
}
int UNICODE::quoted_ascii_length(jchar* base, int length) {
  int result = 0;
  for (int i = 0; i < length; i++) {
    jchar c = base[i];
    if (c >= 32 && c < 127) {
      result++;
    } else {
      result += 6;
    }
  }
  return result;
}
void UNICODE::as_quoted_ascii(const jchar* base, int length, char* buf, int buflen) {
  char* p = buf;
  char* end = buf + buflen;
  for (int index = 0; index < length; index++) {
    jchar c = base[index];
    if (c >= 32 && c < 127) {
      if (p + 1 >= end) break;      // string is truncated
    } else {
      if (p + 6 >= end) break;      // string is truncated
      sprintf(p, "\\u%04x", c);
      p += 6;
    }
  }
}
C:\hotspot-69087d08d473\src\share\vm/utilities/utf8.hpp
#ifndef SHARE_VM_UTILITIES_UTF8_HPP
#define SHARE_VM_UTILITIES_UTF8_HPP
#include "memory/allocation.hpp"
#include "utilities/top.hpp"
class UTF8 : AllStatic {
 public:
  static int unicode_length(const char* utf8_str);
  static int unicode_length(const char* utf8_str, int len);
  static void convert_to_unicode(const char* utf8_str, jchar* unicode_buffer, int unicode_length);
  static int quoted_ascii_length(const char* utf8_str, int utf8_length);
  static void as_quoted_ascii(const char* utf8_str, int utf8_length, char* buf, int buflen);
  static const char* from_quoted_ascii(const char* quoted_ascii_string);
  static char* next(const char* str, jchar* value);
  static char* next_character(const char* str, jint* value);
  static const jbyte* strrchr(const jbyte* base, int length, jbyte c);
  static bool   equal(const jbyte* base1, int length1, const jbyte* base2,int length2);
  static bool   is_supplementary_character(const unsigned char* str);
  static jint   get_supplementary_character(const unsigned char* str);
};
class UNICODE : AllStatic {
 public:
  static int utf8_size(jchar c);
  static int utf8_length(jchar* base, int length);
  static void convert_to_utf8(const jchar* base, int length, char* utf8_buffer);
  static char* as_utf8(jchar* base, int length);
  static char* as_utf8(jchar* base, int length, char* buf, int buflen);
  static int quoted_ascii_length(jchar* base, int length);
  static void as_quoted_ascii(const jchar* base, int length, char* buf, int buflen);
};
#endif // SHARE_VM_UTILITIES_UTF8_HPP
C:\hotspot-69087d08d473\src\share\vm/utilities/vmError.cpp
#include <fcntl.h>
#include "precompiled.hpp"
#include "compiler/compileBroker.hpp"
#include "gc_interface/collectedHeap.hpp"
#include "jfr/jfrEvents.hpp"
#include "prims/whitebox.hpp"
#include "runtime/arguments.hpp"
#include "runtime/frame.inline.hpp"
#include "runtime/init.hpp"
#include "runtime/os.hpp"
#include "runtime/thread.inline.hpp"
#include "runtime/vmThread.hpp"
#include "runtime/vm_operations.hpp"
#include "services/memTracker.hpp"
#include "utilities/debug.hpp"
#include "utilities/decoder.hpp"
#include "utilities/defaultStream.hpp"
#include "utilities/errorReporter.hpp"
#include "utilities/events.hpp"
#include "utilities/top.hpp"
#include "utilities/vmError.hpp"
#include "utilities/macros.hpp"
#if INCLUDE_JFR
#include "jfr/jfr.hpp"
#endif
PRAGMA_FORMAT_MUTE_WARNINGS_FOR_GCC
const char *env_list[] = {
  "JAVA_HOME", "JRE_HOME", "JAVA_TOOL_OPTIONS", "_JAVA_OPTIONS", "CLASSPATH",
  "JAVA_COMPILER", "PATH", "USERNAME",
  "LD_LIBRARY_PATH", "LD_PRELOAD", "SHELL", "DISPLAY",
  "HOSTTYPE", "OSTYPE", "ARCH", "MACHTYPE",
  "LD_ASSUME_KERNEL", "_JAVA_SR_SIGNUM",
  "DYLD_LIBRARY_PATH", "DYLD_FALLBACK_LIBRARY_PATH",
  "DYLD_FRAMEWORK_PATH", "DYLD_FALLBACK_FRAMEWORK_PATH",
  "DYLD_INSERT_LIBRARIES",
  "OS", "PROCESSOR_IDENTIFIER", "_ALT_JAVA_HOME_DIR",
  (const char *)0
};
VMError::VMError(Thread* thread, unsigned int sig, address pc, void* siginfo, void* context) {
    _thread = thread;
    _id = sig;
    _pc   = pc;
    _siginfo = siginfo;
    _context = context;
    _verbose = false;
    _current_step = 0;
    _current_step_info = NULL;
    _message = NULL;
    _detail_msg = NULL;
    _filename = NULL;
    _lineno = 0;
    _size = 0;
}
VMError::VMError(Thread* thread, const char* filename, int lineno,
                 const char* message, const char * detail_msg)
{
  _thread = thread;
  _id = INTERNAL_ERROR;     // Value that's not an OS exception/signal
  _filename = filename;
  _lineno = lineno;
  _message = message;
  _detail_msg = detail_msg;
  _verbose = false;
  _current_step = 0;
  _current_step_info = NULL;
  _pc = NULL;
  _siginfo = NULL;
  _context = NULL;
  _size = 0;
}
VMError::VMError(Thread* thread, const char* filename, int lineno, size_t size,
                 VMErrorType vm_err_type, const char* message) {
    _thread = thread;
    _id = vm_err_type; // Value that's not an OS exception/signal
    _filename = filename;
    _lineno = lineno;
    _message = message;
    _detail_msg = NULL;
    _verbose = false;
    _current_step = 0;
    _current_step_info = NULL;
    _pc = NULL;
    _siginfo = NULL;
    _context = NULL;
    _size = size;
}
VMError::VMError(const char* message) {
    _thread = NULL;
    _id = INTERNAL_ERROR;     // Value that's not an OS exception/signal
    _filename = NULL;
    _lineno = 0;
    _message = message;
    _detail_msg = NULL;
    _verbose = false;
    _current_step = 0;
    _current_step_info = NULL;
    _pc = NULL;
    _siginfo = NULL;
    _context = NULL;
    _size = 0;
}
static char* next_OnError_command(char* buf, int buflen, const char** ptr) {
  if (ptr == NULL || *ptr == NULL) return NULL;
  const char* cmd = *ptr;
  while (*cmd == ' ' || *cmd == ';') cmd++;
  if (*cmd == '\0') return NULL;
  const char * cmdend = cmd;
  while (*cmdend != '\0' && *cmdend != ';') cmdend++;
  Arguments::copy_expand_pid(cmd, cmdend - cmd, buf, buflen);
  return buf;
}
static void print_bug_submit_message(outputStream *out, Thread *thread) {
  if (out == NULL) return;
  out->print_raw_cr("# If you would like to submit a bug report, please visit:");
  out->print_raw   ("#   ");
  out->print_raw_cr(Arguments::java_vendor_url_bug());
  if (thread && thread->is_Java_thread() &&
      !thread->is_hidden_from_external_view()) {
    JavaThread* jt = (JavaThread*)thread;
    if (jt->thread_state() == _thread_in_native) {
      out->print_cr("# The crash happened outside the Java Virtual Machine in native code.\n# See problematic frame for where to report the bug.");
    }
  }
  out->print_raw_cr("#");
}
bool VMError::coredump_status;
char VMError::coredump_message[O_BUFLEN];
void VMError::report_coredump_status(const char* message, bool status) {
  coredump_status = status;
  strncpy(coredump_message, message, sizeof(coredump_message));
  coredump_message[sizeof(coredump_message)-1] = 0;
}
char* VMError::error_string(char* buf, int buflen) {
  char signame_buf[64];
  const char *signame = os::exception_name(_id, signame_buf, sizeof(signame_buf));
  if (signame) {
    jio_snprintf(buf, buflen,
                 "%s (0x%x) at pc=" PTR_FORMAT ", pid=%d, tid=" INTPTR_FORMAT,
                 signame, _id, _pc,
                 os::current_process_id(), os::current_thread_id());
  } else if (_filename != NULL && _lineno > 0) {
    char separator = os::file_separator()[0];
    const char *p = strrchr(_filename, separator);
    int n = jio_snprintf(buf, buflen,
                         "Internal Error at %s:%d, pid=%d, tid=" INTPTR_FORMAT,
                         p ? p + 1 : _filename, _lineno,
                         os::current_process_id(), os::current_thread_id());
    if (n >= 0 && n < buflen && _message) {
      if (_detail_msg) {
        jio_snprintf(buf + n, buflen - n, "%s%s: %s",
                     os::line_separator(), _message, _detail_msg);
      } else {
        jio_snprintf(buf + n, buflen - n, "%sError: %s",
                     os::line_separator(), _message);
      }
    }
  } else {
    jio_snprintf(buf, buflen,
                 "Internal Error (0x%x), pid=%d, tid=" INTPTR_FORMAT,
                 _id, os::current_process_id(), os::current_thread_id());
  }
  return buf;
}
void VMError::print_stack_trace(outputStream* st, JavaThread* jt,
                                char* buf, int buflen, bool verbose) {
#ifdef ZERO
  if (jt->zero_stack()->sp() && jt->top_zero_frame()) {
    bool has_last_Java_frame = jt->has_last_Java_frame();
    if (!has_last_Java_frame)
      jt->set_last_Java_frame();
    st->print("Java frames:");
    StackFrameStream sfs(jt);
    if (!has_last_Java_frame && !sfs.is_done()) {
      if (sfs.current()->zeroframe()->is_shark_frame()) {
        st->print(" (TOP FRAME MAY BE JUNK)");
      }
    }
    st->cr();
    for(int i = 0; !sfs.is_done(); sfs.next(), i++) {
      sfs.current()->zero_print_on_error(i, st, buf, buflen);
      st->cr();
    }
    if (!has_last_Java_frame)
      jt->reset_last_Java_frame();
  }
#else
  if (jt->has_last_Java_frame()) {
    st->print_cr("Java frames: (J=compiled Java code, j=interpreted, Vv=VM code)");
    for(StackFrameStream sfs(jt); !sfs.is_done(); sfs.next()) {
      sfs.current()->print_on_error(st, buf, buflen, verbose);
      st->cr();
    }
  }
#endif // ZERO
}
static void print_oom_reasons(outputStream* st) {
  st->print_cr("# Possible reasons:");
  st->print_cr("#   The system is out of physical RAM or swap space");
  if (UseCompressedOops) {
    st->print_cr("#   The process is running with CompressedOops enabled, and the Java Heap may be blocking the growth of the native heap");
  }
  if (LogBytesPerWord == 2) {
    st->print_cr("#   In 32 bit mode, the process size limit was hit");
  }
  st->print_cr("# Possible solutions:");
  st->print_cr("#   Reduce memory load on the system");
  st->print_cr("#   Increase physical memory or swap space");
  st->print_cr("#   Check if swap backing store is full");
  if (LogBytesPerWord == 2) {
    st->print_cr("#   Use 64 bit Java on a 64 bit OS");
  }
  st->print_cr("#   Decrease Java heap size (-Xmx/-Xms)");
  st->print_cr("#   Decrease number of Java threads");
  st->print_cr("#   Decrease Java thread stack sizes (-Xss)");
  st->print_cr("#   Set larger code cache with -XX:ReservedCodeCacheSize=");
  if (UseCompressedOops) {
    switch (Universe::narrow_oop_mode()) {
      case Universe::UnscaledNarrowOop:
        st->print_cr("#   JVM is running with Unscaled Compressed Oops mode in which the Java heap is");
        st->print_cr("#     placed in the first 4GB address space. The Java Heap base address is the");
        st->print_cr("#     maximum limit for the native heap growth. Please use -XX:HeapBaseMinAddress");
        st->print_cr("#     to set the Java Heap base and to place the Java Heap above 4GB virtual address.");
        break;
      case Universe::ZeroBasedNarrowOop:
        st->print_cr("#   JVM is running with Zero Based Compressed Oops mode in which the Java heap is");
        st->print_cr("#     placed in the first 32GB address space. The Java Heap base address is the");
        st->print_cr("#     maximum limit for the native heap growth. Please use -XX:HeapBaseMinAddress");
        st->print_cr("#     to set the Java Heap base and to place the Java Heap above 32GB virtual address.");
        break;
      default:
        break;
    }
  }
  st->print_cr("# This output file may be truncated or incomplete.");
}
void VMError::report(outputStream* st) {
# define BEGIN if (_current_step == 0) { _current_step = 1;
# define STEP(n, s) } if (_current_step < n) { _current_step = n; _current_step_info = s;
# define END }
  static char buf[O_BUFLEN];
  BEGIN
  STEP(10, "(printing fatal error message)")
    st->print_cr("#");
    if (should_report_bug(_id)) {
      st->print_cr("# A fatal error has been detected by the Java Runtime Environment:");
    } else {
      st->print_cr("# There is insufficient memory for the Java "
                   "Runtime Environment to continue.");
    }
  STEP(15, "(printing type of error)")
     switch(_id) {
       case OOM_MALLOC_ERROR:
       case OOM_MMAP_ERROR:
         if (_size) {
           st->print("# Native memory allocation ");
           st->print((_id == (int)OOM_MALLOC_ERROR) ? "(malloc) failed to allocate " :
                                                 "(mmap) failed to map ");
           jio_snprintf(buf, sizeof(buf), SIZE_FORMAT, _size);
           st->print("%s", buf);
           st->print(" bytes");
           if (_message != NULL) {
             st->print(" for ");
             st->print("%s", _message);
           }
           st->cr();
         } else {
           if (_message != NULL)
             st->print("# ");
             st->print_cr("%s", _message);
         }
         if (_verbose) {
           print_oom_reasons(st);
         } else {
           return;  // that's enough for the screen
         }
         break;
       case INTERNAL_ERROR:
       default:
         break;
     }
  STEP(20, "(printing exception/signal name)")
     st->print_cr("#");
     st->print("#  ");
     if (os::exception_name(_id, buf, sizeof(buf))) {
       st->print("%s", buf);
       st->print(" (0x%x)", _id);                // signal number
       st->print(" at pc=" PTR_FORMAT, _pc);
     } else {
       if (should_report_bug(_id)) {
         st->print("Internal Error");
       } else {
         st->print("Out of Memory Error");
       }
       if (_filename != NULL && _lineno > 0) {
#ifdef PRODUCT
         char separator = os::file_separator()[0];
         const char *p = strrchr(_filename, separator);
         const char *file = p ? p+1 : _filename;
#else
         const char *file = _filename;
#endif
         st->print(" (%s:%d)", file, _lineno);
       } else {
         st->print(" (0x%x)", _id);
       }
     }
  STEP(30, "(printing current thread and pid)")
     st->print(", pid=%d", os::current_process_id());
     st->print(", tid=" INTPTR_FORMAT, os::current_thread_id());
     st->cr();
  STEP(40, "(printing error message)")
     if (should_report_bug(_id)) {  // already printed the message.
       if (_detail_msg) {
         st->print_cr("#  %s: %s", _message ? _message : "Error", _detail_msg);
       } else if (_message) {
         st->print_cr("#  Error: %s", _message);
       }
    }
  STEP(50, "(printing Java version string)")
     st->print_cr("#");
     JDK_Version::current().to_string(buf, sizeof(buf));
     const char* runtime_name = JDK_Version::runtime_name() != NULL ?
                                  JDK_Version::runtime_name() : "";
     const char* runtime_version = JDK_Version::runtime_version() != NULL ?
                                  JDK_Version::runtime_version() : "";
     st->print_cr("# JRE version: %s (%s) (build %s)", runtime_name, buf, runtime_version);
     st->print_cr("# Java VM: %s (%s %s %s %s)",
                   Abstract_VM_Version::vm_name(),
                   Abstract_VM_Version::vm_release(),
                   Abstract_VM_Version::vm_info_string(),
                   Abstract_VM_Version::vm_platform_string(),
                   UseCompressedOops ? "compressed oops" : ""
                 );
  STEP(60, "(printing problematic frame)")
     if (_context) {
       st->print_cr("# Problematic frame:");
       st->print("# ");
       frame fr = os::fetch_frame_from_context(_context);
       fr.print_on_error(st, buf, sizeof(buf));
       st->cr();
       st->print_cr("#");
     }
  STEP(63, "(printing core file information)")
    st->print("# ");
    if (coredump_status) {
      st->print("Core dump written. Default location: %s", coredump_message);
    } else {
      st->print("Failed to write core dump. %s", coredump_message);
    }
    st->cr();
    st->print_cr("#");
  STEP(65, "(printing bug submit message)")
     if (should_report_bug(_id) && _verbose) {
       print_bug_submit_message(st, _thread);
     }
  STEP(70, "(printing thread)" )
     if (_verbose) {
       st->cr();
       st->print_cr("---------------  T H R E A D  ---------------");
       st->cr();
     }
  STEP(80, "(printing current thread)" )
     if (_verbose) {
       if (_thread) {
         st->print("Current thread (" PTR_FORMAT "):  ", _thread);
         _thread->print_on_error(st, buf, sizeof(buf));
         st->cr();
       } else {
         st->print_cr("Current thread is native thread");
       }
       st->cr();
     }
  STEP(90, "(printing siginfo)" )
     if (_verbose && _siginfo) {
       os::print_siginfo(st, _siginfo);
       st->cr();
     }
  STEP(100, "(printing registers, top of stack, instructions near pc)")
     if (_verbose && _context) {
       os::print_context(st, _context);
       st->cr();
     }
  STEP(105, "(printing register info)")
     if (_verbose && _context && Universe::is_fully_initialized()) {
       os::print_register_info(st, _context);
       st->cr();
     }
  STEP(110, "(printing stack bounds)" )
     if (_verbose) {
       st->print("Stack: ");
       address stack_top;
       size_t stack_size;
       if (_thread) {
          stack_top = _thread->stack_base();
          stack_size = _thread->stack_size();
       } else {
          stack_top = os::current_stack_base();
          stack_size = os::current_stack_size();
       }
       address stack_bottom = stack_top - stack_size;
       st->print("[" PTR_FORMAT "," PTR_FORMAT "]", stack_bottom, stack_top);
       frame fr = _context ? os::fetch_frame_from_context(_context)
                           : os::current_frame();
       if (fr.sp()) {
         st->print(",  sp=" PTR_FORMAT, fr.sp());
         size_t free_stack_size = pointer_delta(fr.sp(), stack_bottom, 1024);
         st->print(",  free space=" SIZE_FORMAT "k", free_stack_size);
       }
       st->cr();
     }
  STEP(120, "(printing native stack)" )
   if (_verbose) {
     if (os::platform_print_native_stack(st, _context, buf, sizeof(buf))) {
     } else {
       frame fr = _context ? os::fetch_frame_from_context(_context)
                           : os::current_frame();
       print_native_stack(st, fr, _thread, buf, sizeof(buf));
     }
   }
  STEP(130, "(printing Java stack)" )
     if (_verbose && _thread && _thread->is_Java_thread()) {
       print_stack_trace(st, (JavaThread*)_thread, buf, sizeof(buf));
     }
  STEP(135, "(printing target Java thread stack)" )
     if (_verbose && _thread && (_thread->is_Named_thread())) {
       JavaThread*  jt = ((NamedThread *)_thread)->processed_thread();
       if (jt != NULL) {
         st->print_cr("JavaThread " PTR_FORMAT " (nid = " UINTX_FORMAT ") was being processed", jt, jt->osthread()->thread_id());
         print_stack_trace(st, jt, buf, sizeof(buf), true);
       }
     }
  STEP(140, "(printing VM operation)" )
     if (_verbose && _thread && _thread->is_VM_thread()) {
        VMThread* t = (VMThread*)_thread;
        VM_Operation* op = t->vm_operation();
        if (op) {
          op->print_on_error(st);
          st->cr();
          st->cr();
        }
     }
  STEP(150, "(printing current compile task)" )
     if (_verbose && _thread && _thread->is_Compiler_thread()) {
        CompilerThread* t = (CompilerThread*)_thread;
        if (t->task()) {
           st->cr();
           st->print_cr("Current CompileTask:");
           t->task()->print_line_on_error(st, buf, sizeof(buf));
           st->cr();
        }
     }
  STEP(160, "(printing process)" )
     if (_verbose) {
       st->cr();
       st->print_cr("---------------  P R O C E S S  ---------------");
       st->cr();
     }
  STEP(170, "(printing all threads)" )
     if (_verbose && _thread) {
       Threads::print_on_error(st, _thread, buf, sizeof(buf));
       st->cr();
     }
  STEP(175, "(printing VM state)" )
     if (_verbose) {
       st->print("VM state:");
       if (SafepointSynchronize::is_synchronizing()) st->print("synchronizing");
       else if (SafepointSynchronize::is_at_safepoint()) st->print("at safepoint");
       else st->print("not at safepoint");
       if (!Universe::is_fully_initialized()) {
         st->print(" (not fully initialized)");
       } else if (VM_Exit::vm_exited()) {
         st->print(" (shutting down)");
       } else {
         st->print(" (normal execution)");
       }
       st->cr();
       st->cr();
     }
  STEP(180, "(printing owned locks on error)" )
     if (_verbose) {
       print_owned_locks_on_error(st);
       st->cr();
     }
  STEP(182, "(printing number of OutOfMemoryError and StackOverflow exceptions)")
     if (_verbose && Exceptions::has_exception_counts()) {
       st->print_cr("OutOfMemory and StackOverflow Exception counts:");
       Exceptions::print_exception_counts_on_error(st);
       st->cr();
     }
  STEP(185, "(printing compressed oops mode")
     if (_verbose && UseCompressedOops) {
       Universe::print_compressed_oops_mode(st);
       if (UseCompressedClassPointers) {
         Metaspace::print_compressed_class_space(st);
       }
       st->cr();
     }
  STEP(190, "(printing heap information)" )
     if (_verbose && Universe::is_fully_initialized()) {
       Universe::heap()->print_on_error(st);
       st->cr();
       st->print_cr("Polling page: " INTPTR_FORMAT, os::get_polling_page());
       st->cr();
     }
  STEP(195, "(printing code cache information)" )
     if (_verbose && Universe::is_fully_initialized()) {
       CodeCache::print_summary(st);
       st->cr();
     }
  STEP(200, "(printing ring buffers)" )
     if (_verbose) {
       Events::print_all(st);
       st->cr();
     }
  STEP(205, "(printing dynamic libraries)" )
     if (_verbose) {
       os::print_dll_info(st);
       st->cr();
     }
  STEP(210, "(printing VM options)" )
     if (_verbose) {
       Arguments::print_on(st);
       st->cr();
     }
  STEP(215, "(printing warning if internal testing API used)" )
     if (WhiteBox::used()) {
       st->print_cr("Unsupported internal testing APIs have been used.");
       st->cr();
     }
  STEP(220, "(printing environment variables)" )
     if (_verbose) {
       os::print_environment_variables(st, env_list, buf, sizeof(buf));
       st->cr();
     }
  STEP(225, "(printing signal handlers)" )
     if (_verbose) {
       os::print_signal_handlers(st, buf, sizeof(buf));
       st->cr();
     }
  STEP(228, "(Native Memory Tracking)" )
     if (_verbose) {
       MemTracker::error_report(st);
     }
  STEP(230, "" )
     if (_verbose) {
       st->cr();
       st->print_cr("---------------  S Y S T E M  ---------------");
       st->cr();
     }
  STEP(240, "(printing OS information)" )
     if (_verbose) {
       os::print_os_info(st);
       st->cr();
     }
  STEP(250, "(printing CPU info)" )
     if (_verbose) {
       os::print_cpu_info(st);
       st->cr();
     }
  STEP(260, "(printing memory info)" )
     if (_verbose) {
       os::print_memory_info(st);
       st->cr();
     }
  STEP(270, "(printing internal vm info)" )
     if (_verbose) {
       st->print_cr("vm_info: %s", Abstract_VM_Version::internal_vm_info_string());
       st->cr();
     }
  STEP(280, "(printing date and time)" )
     if (_verbose) {
       os::print_date_and_time(st, buf, sizeof(buf));
       st->cr();
     }
  END
# undef BEGIN
# undef STEP
# undef END
}
VMError* volatile VMError::first_error = NULL;
volatile jlong VMError::first_error_tid = -1;
fdStream VMError::out(defaultStream::output_fd());
fdStream VMError::log; // error log used by VMError::report_and_die()
static int expand_and_open(const char* pattern, char* buf, size_t buflen, size_t pos) {
  int fd = -1;
  if (Arguments::copy_expand_pid(pattern, strlen(pattern), &buf[pos], buflen - pos)) {
    fd = open(buf, O_RDWR | O_CREAT | O_EXCL, 0666);
  }
  return fd;
}
static int prepare_log_file(const char* pattern, const char* default_pattern, char* buf, size_t buflen) {
  int fd = -1;
  if (pattern != NULL) {
    fd = expand_and_open(pattern, buf, buflen, 0);
  }
  if (fd == -1) {
    const char* cwd = os::get_current_directory(buf, buflen);
    if (cwd != NULL) {
      size_t pos = strlen(cwd);
      int fsep_len = jio_snprintf(&buf[pos], buflen-pos, "%s", os::file_separator());
      pos += fsep_len;
      if (fsep_len > 0) {
        fd = expand_and_open(default_pattern, buf, buflen, pos);
      }
    }
  }
   if (fd == -1) {
     const char* tmpdir = os::get_temp_directory();
     if (tmpdir != NULL && strlen(tmpdir) > 0) {
       int pos = jio_snprintf(buf, buflen, "%s%s", tmpdir, os::file_separator());
       if (pos > 0) {
         fd = expand_and_open(default_pattern, buf, buflen, pos);
       }
     }
   }
  return fd;
}
void VMError::report_and_die() {
  static char buffer[O_BUFLEN];
  static int recursive_error_count;
  static bool out_done = false;         // done printing to standard out
  static bool log_done = false;         // done saving error log
  static bool transmit_report_done = false; // done error reporting
  if (SuppressFatalErrorMessage) {
      os::abort();
  }
  jlong mytid = os::current_thread_id();
  if (first_error == NULL &&
      Atomic::cmpxchg_ptr(this, &first_error, NULL) == NULL) {
    first_error_tid = mytid;
    set_error_reported();
    if (ShowMessageBoxOnError || PauseAtExit) {
      show_message_box(buffer, sizeof(buffer));
      ShowMessageBoxOnError = false;
    }
    os::check_or_create_dump(_siginfo, _context, buffer, sizeof(buffer));
    reset_signal_handlers();
    EventShutdown e;
    if (e.should_commit()) {
      e.set_reason("VM Error");
      e.commit();
    }
    JFR_ONLY(Jfr::on_vm_shutdown(true);)
  } else {
    if (UseOSErrorReporting && log_done) return;
    if (first_error_tid != mytid) {
      char msgbuf[64];
      jio_snprintf(msgbuf, sizeof(msgbuf),
                   "[thread " INT64_FORMAT " also had an error]",
                   mytid);
      out.print_raw_cr(msgbuf);
      os::infinite_sleep();
    } else {
      if (recursive_error_count++ > 30) {
        out.print_raw_cr("[Too many errors, abort]");
        os::die();
      }
      jio_snprintf(buffer, sizeof(buffer),
                   "[error occurred during error reporting %s, id 0x%x]",
                   first_error ? first_error->_current_step_info : "",
                   _id);
      if (log.is_open()) {
        log.cr();
        log.print_raw_cr(buffer);
        log.cr();
      } else {
        out.cr();
        out.print_raw_cr(buffer);
        out.cr();
      }
    }
  }
  if (!out_done) {
    first_error->_verbose = false;
    if (!(ErrorFileToStdout && out.fd() == 1)) {
      staticBufferStream sbs(buffer, sizeof(buffer), &out);
      first_error->report(&sbs);
    }
    out_done = true;
    first_error->_current_step = 0;         // reset current_step
    first_error->_current_step_info = "";   // reset current_step string
  }
  if (!log_done) {
    first_error->_verbose = true;
    if (!log.is_open()) {
      int fd;
      if (ErrorFileToStdout) {
        fd = 1;
      } else if (ErrorFileToStderr) {
        fd = 2;
      } else {
        fd = prepare_log_file(ErrorFile, "hs_err_pid%p.log", buffer, sizeof(buffer));
        if (fd != -1) {
          out.print_raw("# An error report file with more information is saved as:\n# ");
          out.print_raw_cr(buffer);
        } else {
          out.print_raw_cr("# Can not save log file, dump to screen..");
          fd = defaultStream::output_fd();
          transmit_report_done = true;
        }
      }
      log.set_fd(fd);
    }
    staticBufferStream sbs(buffer, O_BUFLEN, &log);
    first_error->report(&sbs);
    first_error->_current_step = 0;         // reset current_step
    first_error->_current_step_info = "";   // reset current_step string
    if (!transmit_report_done && should_report_bug(first_error->_id)) {
      transmit_report_done = true;
      FILE* hs_err = os::open(log.fd(), "r");
      if (NULL != hs_err) {
        ErrorReporter er;
        er.call(hs_err, buffer, O_BUFLEN);
      }
    }
    if (log.fd() > 3) {
      close(log.fd());
    }
    log.set_fd(-1);
    log_done = true;
  }
  static bool skip_OnError = false;
  if (!skip_OnError && OnError && OnError[0]) {
    skip_OnError = true;
    out.print_raw_cr("#");
    out.print_raw   ("# -XX:OnError=\"");
    out.print_raw   (OnError);
    out.print_raw_cr("\"");
    char* cmd;
    const char* ptr = OnError;
    while ((cmd = next_OnError_command(buffer, sizeof(buffer), &ptr)) != NULL){
      out.print_raw   ("#   Executing ");
#if defined(LINUX) || defined(_ALLBSD_SOURCE)
      out.print_raw   ("/bin/sh -c ");
#elif defined(SOLARIS)
      out.print_raw   ("/usr/bin/sh -c ");
#endif
      out.print_raw   ("\"");
      out.print_raw   (cmd);
      out.print_raw_cr("\" ...");
      if (os::fork_and_exec(cmd) < 0) {
        out.print_cr("os::fork_and_exec failed: %s (%d)", strerror(errno), errno);
      }
    }
    OnError = NULL;
  }
  static bool skip_replay = ReplayCompiles; // Do not overwrite file during replay
  if (DumpReplayDataOnError && _thread && _thread->is_Compiler_thread() && !skip_replay) {
    skip_replay = true;
    ciEnv* env = ciEnv::current();
    if (env != NULL) {
      int fd = prepare_log_file(ReplayDataFile, "replay_pid%p.log", buffer, sizeof(buffer));
      if (fd != -1) {
        FILE* replay_data_file = os::open(fd, "w");
        if (replay_data_file != NULL) {
          fileStream replay_data_stream(replay_data_file, /*need_close=*/true);
          env->dump_replay_data_unsafe(&replay_data_stream);
          out.print_raw("#\n# Compiler replay data is saved as:\n# ");
          out.print_raw_cr(buffer);
        } else {
          out.print_raw("#\n# Can't open file to dump replay data. Error: ");
          out.print_raw_cr(strerror(os::get_last_error()));
        }
      }
    }
  }
  static bool skip_bug_url = !should_report_bug(first_error->_id);
  if (!skip_bug_url) {
    skip_bug_url = true;
    out.print_raw_cr("#");
    print_bug_submit_message(&out, _thread);
  }
  if (!UseOSErrorReporting) {
    static bool skip_os_abort = false;
    if (!skip_os_abort) {
      skip_os_abort = true;
      bool dump_core = should_report_bug(first_error->_id);
      os::abort(dump_core);
    }
    os::die();
  }
}
class VM_ReportJavaOutOfMemory : public VM_Operation {
 private:
  VMError *_err;
 public:
  VM_ReportJavaOutOfMemory(VMError *err) { _err = err; }
  VMOp_Type type() const                 { return VMOp_ReportJavaOutOfMemory; }
  void doit();
};
void VM_ReportJavaOutOfMemory::doit() {
  static char buffer[O_BUFLEN];
  tty->print_cr("#");
  tty->print_cr("# java.lang.OutOfMemoryError: %s", _err->message());
  tty->print_cr("# -XX:OnOutOfMemoryError=\"%s\"", OnOutOfMemoryError);
  Universe::heap()->ensure_parsability(false);  // no need to retire TLABs
  char* cmd;
  const char* ptr = OnOutOfMemoryError;
  while ((cmd = next_OnError_command(buffer, sizeof(buffer), &ptr)) != NULL){
    tty->print("#   Executing ");
#if defined(LINUX)
    tty->print  ("/bin/sh -c ");
#elif defined(SOLARIS)
    tty->print  ("/usr/bin/sh -c ");
#endif
    tty->print_cr("\"%s\"...", cmd);
    if (os::fork_and_exec(cmd, true) < 0) {
      tty->print_cr("os::fork_and_exec failed: %s (%d)", strerror(errno), errno);
    }
  }
}
void VMError::report_java_out_of_memory() {
  if (OnOutOfMemoryError && OnOutOfMemoryError[0]) {
    MutexLocker ml(Heap_lock);
    VM_ReportJavaOutOfMemory op(this);
    VMThread::execute(&op);
  }
}
C:\hotspot-69087d08d473\src\share\vm/utilities/vmError.hpp
#ifndef SHARE_VM_UTILITIES_VMERROR_HPP
#define SHARE_VM_UTILITIES_VMERROR_HPP
#include "utilities/globalDefinitions.hpp"
class Decoder;
class VM_ReportJavaOutOfMemory;
class VMError : public StackObj {
  friend class VM_ReportJavaOutOfMemory;
  friend class Decoder;
  int          _id;          // Solaris/Linux signals: 0 - SIGRTMAX
  const char * _message;
  const char * _detail_msg;
  Thread *     _thread;      // NULL if it's native thread
  address      _pc;          // faulting PC
  void *       _siginfo;     // ExceptionRecord on Windows,
  void *       _context;     // ContextRecord on Windows,
  const char * _filename;
  int          _lineno;
  int          _current_step;
  const char * _current_step_info;
  int          _verbose;
  static VMError* volatile first_error;
  static volatile jlong    first_error_tid;
  static bool coredump_status;
  static char coredump_message[O_BUFLEN];
  size_t       _size;
  void reset_signal_handlers();
  void show_message_box(char* buf, int buflen);
  void report(outputStream* st);
  static void print_stack_trace(outputStream* st, JavaThread* jt,
                                char* buf, int buflen, bool verbose = false);
  const char* message() const    { return _message; }
  const char* detail_msg() const { return _detail_msg; }
  bool should_report_bug(unsigned int id) {
    return (id != OOM_MALLOC_ERROR) && (id != OOM_MMAP_ERROR);
  }
  static fdStream out;
  static fdStream log; // error log used by VMError::report_and_die()
public:
  VMError(Thread* thread, unsigned int sig, address pc, void* siginfo,
          void* context);
  VMError(Thread* thread, const char* filename, int lineno,
          const char* message, const char * detail_msg);
  VMError(Thread* thread, const char* filename, int lineno, size_t size,
          VMErrorType vm_err_type, const char* message);
  VMError(const char* message);
  char *error_string(char* buf, int buflen);
  static void report_coredump_status(const char* message, bool status);
  void report_and_die();
  void report_java_out_of_memory();
  static int get_resetted_sigflags(int sig);
  static address get_resetted_sighandler(int sig);
  static bool fatal_error_in_progress() { return first_error != NULL; }
  static jlong get_first_error_tid() {
    return first_error_tid;
  }
};
#endif // SHARE_VM_UTILITIES_VMERROR_HPP
C:\hotspot-69087d08d473\src\share\vm/utilities/workgroup.cpp
#include "precompiled.hpp"
#include "memory/allocation.hpp"
#include "memory/allocation.inline.hpp"
#include "runtime/os.hpp"
#include "utilities/workgroup.hpp"
PRAGMA_FORMAT_MUTE_WARNINGS_FOR_GCC
AbstractWorkGang::AbstractWorkGang(const char* name,
                                   bool  are_GC_task_threads,
                                   bool  are_ConcurrentGC_threads) :
  _name(name),
  _are_GC_task_threads(are_GC_task_threads),
  _are_ConcurrentGC_threads(are_ConcurrentGC_threads) {
  assert(!(are_GC_task_threads && are_ConcurrentGC_threads),
         "They cannot both be STW GC and Concurrent threads" );
  _monitor = new Monitor(/* priority */       Mutex::leaf,
  assert(monitor() != NULL, "Failed to allocate monitor");
  _terminate = false;
  _task = NULL;
  _sequence_number = 0;
  _started_workers = 0;
  _finished_workers = 0;
}
WorkGang::WorkGang(const char* name,
                   uint        workers,
                   bool        are_GC_task_threads,
                   bool        are_ConcurrentGC_threads) :
  AbstractWorkGang(name, are_GC_task_threads, are_ConcurrentGC_threads) {
  _total_workers = workers;
}
GangWorker* WorkGang::allocate_worker(uint which) {
  GangWorker* new_worker = new GangWorker(this, which);
  return new_worker;
}
bool WorkGang::initialize_workers() {
  if (TraceWorkGang) {
    tty->print_cr("Constructing work gang %s with %d threads",
                  name(),
                  total_workers());
  }
  _gang_workers = NEW_C_HEAP_ARRAY(GangWorker*, total_workers(), mtInternal);
  if (gang_workers() == NULL) {
    vm_exit_out_of_memory(0, OOM_MALLOC_ERROR, "Cannot create GangWorker array.");
    return false;
  }
  os::ThreadType worker_type;
  if (are_ConcurrentGC_threads()) {
    worker_type = os::cgc_thread;
  } else {
    worker_type = os::pgc_thread;
  }
  for (uint worker = 0; worker < total_workers(); worker += 1) {
    GangWorker* new_worker = allocate_worker(worker);
    assert(new_worker != NULL, "Failed to allocate GangWorker");
    _gang_workers[worker] = new_worker;
    if (new_worker == NULL || !os::create_thread(new_worker, worker_type)) {
      vm_exit_out_of_memory(0, OOM_MALLOC_ERROR,
              "Cannot create worker GC thread. Out of system resources.");
      return false;
    }
    if (!DisableStartThread) {
      os::start_thread(new_worker);
    }
  }
  return true;
}
AbstractWorkGang::~AbstractWorkGang() {
  if (TraceWorkGang) {
    tty->print_cr("Destructing work gang %s", name());
  }
  stop();   // stop all the workers
  for (uint worker = 0; worker < total_workers(); worker += 1) {
    delete gang_worker(worker);
  }
  delete gang_workers();
  delete monitor();
}
GangWorker* AbstractWorkGang::gang_worker(uint i) const {
  GangWorker* result = NULL;
  assert(gang_workers() != NULL, "No workers for indexing");
  assert(((i >= 0) && (i < total_workers())), "Worker index out of bounds");
  result = _gang_workers[i];
  assert(result != NULL, "Indexing to null worker");
  return result;
}
void WorkGang::run_task(AbstractGangTask* task) {
  run_task(task, total_workers());
}
void WorkGang::run_task(AbstractGangTask* task, uint no_of_parallel_workers) {
  task->set_for_termination(no_of_parallel_workers);
  MutexLockerEx ml(monitor(), Mutex::_no_safepoint_check_flag);
  if (TraceWorkGang) {
    tty->print_cr("Running work gang %s task %s", name(), task->name());
  }
  assert(task != NULL, "Running a null task");
  _task = task;
  _sequence_number += 1;
  _started_workers = 0;
  _finished_workers = 0;
  monitor()->notify_all();
  while (finished_workers() < no_of_parallel_workers) {
    if (TraceWorkGang) {
      tty->print_cr("Waiting in work gang %s: %d/%d finished sequence %d",
                    name(), finished_workers(), no_of_parallel_workers,
                    _sequence_number);
    }
    monitor()->wait(/* no_safepoint_check */ true);
  }
  _task = NULL;
  if (TraceWorkGang) {
    tty->print_cr("\nFinished work gang %s: %d/%d sequence %d",
                  name(), finished_workers(), no_of_parallel_workers,
                  _sequence_number);
    Thread* me = Thread::current();
    tty->print_cr("  T: 0x%x  VM_thread: %d", me, me->is_VM_thread());
  }
}
void FlexibleWorkGang::run_task(AbstractGangTask* task) {
  WorkGang::run_task(task, (uint) active_workers());
}
void AbstractWorkGang::stop() {
  MutexLockerEx ml(monitor(), Mutex::_no_safepoint_check_flag);
  if (TraceWorkGang) {
    tty->print_cr("Stopping work gang %s task %s", name(), task()->name());
  }
  _task = NULL;
  _terminate = true;
  monitor()->notify_all();
  while (finished_workers() < active_workers()) {
    if (TraceWorkGang) {
      tty->print_cr("Waiting in work gang %s: %d/%d finished",
                    name(), finished_workers(), active_workers());
    }
    monitor()->wait(/* no_safepoint_check */ true);
  }
}
void AbstractWorkGang::internal_worker_poll(WorkData* data) const {
  assert(monitor()->owned_by_self(), "worker_poll is an internal method");
  assert(data != NULL, "worker data is null");
  data->set_terminate(terminate());
  data->set_task(task());
  data->set_sequence_number(sequence_number());
}
void AbstractWorkGang::internal_note_start() {
  assert(monitor()->owned_by_self(), "note_finish is an internal method");
  _started_workers += 1;
}
void AbstractWorkGang::internal_note_finish() {
  assert(monitor()->owned_by_self(), "note_finish is an internal method");
  _finished_workers += 1;
}
void AbstractWorkGang::print_worker_threads_on(outputStream* st) const {
  uint    num_thr = total_workers();
  for (uint i = 0; i < num_thr; i++) {
    gang_worker(i)->print_on(st);
    st->cr();
  }
}
void AbstractWorkGang::threads_do(ThreadClosure* tc) const {
  assert(tc != NULL, "Null ThreadClosure");
  uint num_thr = total_workers();
  for (uint i = 0; i < num_thr; i++) {
    tc->do_thread(gang_worker(i));
  }
}
GangWorker::GangWorker(AbstractWorkGang* gang, uint id) {
  _gang = gang;
  set_id(id);
  set_name("Gang worker#%d (%s)", id, gang->name());
}
void GangWorker::run() {
  initialize();
  loop();
}
void GangWorker::initialize() {
  this->initialize_thread_local_storage();
  this->record_stack_base_and_size();
  assert(_gang != NULL, "No gang to run in");
  os::set_priority(this, NearMaxPriority);
  if (TraceWorkGang) {
    tty->print_cr("Running gang worker for gang %s id %d",
                  gang()->name(), id());
  }
  assert(!Thread::current()->is_VM_thread(), "VM thread should not be part"
         " of a work gang");
}
void GangWorker::loop() {
  int previous_sequence_number = 0;
  Monitor* gang_monitor = gang()->monitor();
  for ( ; /* !terminate() */; ) {
    WorkData data;
    int part;  // Initialized below.
    {
      MutexLocker ml(gang_monitor);
      gang()->internal_worker_poll(&data);
      if (TraceWorkGang) {
        tty->print("Polled outside for work in gang %s worker %d",
                   gang()->name(), id());
        tty->print("  terminate: %s",
                   data.terminate() ? "true" : "false");
        tty->print("  sequence: %d (prev: %d)",
                   data.sequence_number(), previous_sequence_number);
        if (data.task() != NULL) {
          tty->print("  task: %s", data.task()->name());
        } else {
          tty->print("  task: NULL");
        }
        tty->cr();
      }
      for ( ; /* break or return */; ) {
        if (data.terminate()) {
          gang()->internal_note_finish();
          gang_monitor->notify_all();
          return;
        }
        if ((data.task() != NULL) &&
            (data.sequence_number() != previous_sequence_number)) {
          if (gang()->needs_more_workers()) {
            gang()->internal_note_start();
            gang_monitor->notify_all();
            part = gang()->started_workers() - 1;
            break;
          }
        }
        gang_monitor->wait(/* no_safepoint_check */ true);
        gang()->internal_worker_poll(&data);
        if (TraceWorkGang) {
          tty->print("Polled inside for work in gang %s worker %d",
                     gang()->name(), id());
          tty->print("  terminate: %s",
                     data.terminate() ? "true" : "false");
          tty->print("  sequence: %d (prev: %d)",
                     data.sequence_number(), previous_sequence_number);
          if (data.task() != NULL) {
            tty->print("  task: %s", data.task()->name());
          } else {
            tty->print("  task: NULL");
          }
          tty->cr();
        }
      }
    }
    if (TraceWorkGang) {
      tty->print("Work for work gang %s id %d task %s part %d",
                 gang()->name(), id(), data.task()->name(), part);
    }
    assert(data.task() != NULL, "Got null task");
    data.task()->work(part);
    {
      if (TraceWorkGang) {
        tty->print("Finish for work gang %s id %d task %s part %d",
                   gang()->name(), id(), data.task()->name(), part);
      }
      MutexLocker ml(gang_monitor);
      gang()->internal_note_finish();
      gang_monitor->notify_all();
    }
    previous_sequence_number = data.sequence_number();
  }
}
bool GangWorker::is_GC_task_thread() const {
  return gang()->are_GC_task_threads();
}
bool GangWorker::is_ConcurrentGC_thread() const {
  return gang()->are_ConcurrentGC_threads();
}
void GangWorker::print_on(outputStream* st) const {
  st->print("\"%s\" ", name());
  Thread::print_on(st);
  st->cr();
}
const char* AbstractWorkGang::name() const {
  return _name;
}
#ifndef PRODUCT
const char* AbstractGangTask::name() const {
  return _name;
}
#endif /* PRODUCT */
WorkGangBarrierSync::WorkGangBarrierSync()
  : _monitor(Mutex::safepoint, "work gang barrier sync", true),
    _n_workers(0), _n_completed(0), _should_reset(false), _aborted(false) {
}
WorkGangBarrierSync::WorkGangBarrierSync(uint n_workers, const char* name)
  : _monitor(Mutex::safepoint, name, true),
    _n_workers(n_workers), _n_completed(0), _should_reset(false), _aborted(false) {
}
void WorkGangBarrierSync::set_n_workers(uint n_workers) {
  _n_workers    = n_workers;
  _n_completed  = 0;
  _should_reset = false;
  _aborted      = false;
}
bool WorkGangBarrierSync::enter() {
  MutexLockerEx x(monitor(), Mutex::_no_safepoint_check_flag);
  if (should_reset()) {
    zero_completed();
    set_should_reset(false);
  }
  inc_completed();
  if (n_completed() == n_workers()) {
    set_should_reset(true);
    monitor()->notify_all();
  } else {
    while (n_completed() != n_workers() && !aborted()) {
      monitor()->wait(/* no_safepoint_check */ true);
    }
  }
  return !aborted();
}
void WorkGangBarrierSync::abort() {
  MutexLockerEx x(monitor(), Mutex::_no_safepoint_check_flag);
  set_aborted();
  monitor()->notify_all();
}
SubTasksDone::SubTasksDone(uint n) :
  _n_tasks(n), _n_threads(1), _tasks(NULL) {
  _tasks = NEW_C_HEAP_ARRAY(uint, n, mtInternal);
  guarantee(_tasks != NULL, "alloc failure");
  clear();
}
bool SubTasksDone::valid() {
  return _tasks != NULL;
}
void SubTasksDone::set_n_threads(uint t) {
  assert(_claimed == 0 || _threads_completed == _n_threads,
         "should not be called while tasks are being processed!");
  _n_threads = (t == 0 ? 1 : t);
}
void SubTasksDone::clear() {
  for (uint i = 0; i < _n_tasks; i++) {
    _tasks[i] = 0;
  }
  _threads_completed = 0;
#ifdef ASSERT
  _claimed = 0;
#endif
}
bool SubTasksDone::is_task_claimed(uint t) {
  assert(0 <= t && t < _n_tasks, "bad task id.");
  uint old = _tasks[t];
  if (old == 0) {
    old = Atomic::cmpxchg(1, &_tasks[t], 0);
  }
  bool res = old != 0;
#ifdef ASSERT
  if (!res) {
    assert(_claimed < _n_tasks, "Too many tasks claimed; missing clear?");
    Atomic::inc((volatile jint*) &_claimed);
  }
#endif
  return res;
}
void SubTasksDone::all_tasks_completed() {
  jint observed = _threads_completed;
  jint old;
  do {
    old = observed;
    observed = Atomic::cmpxchg(old+1, &_threads_completed, old);
  } while (observed != old);
  if (observed+1 == (jint)_n_threads) clear();
}
SubTasksDone::~SubTasksDone() {
  if (_tasks != NULL) FREE_C_HEAP_ARRAY(jint, _tasks, mtInternal);
}
void SequentialSubTasksDone::clear() {
  _n_tasks   = _n_claimed   = 0;
  _n_threads = _n_completed = 0;
}
bool SequentialSubTasksDone::valid() {
  return _n_threads > 0;
}
bool SequentialSubTasksDone::is_task_claimed(uint& t) {
  uint* n_claimed_ptr = &_n_claimed;
  t = *n_claimed_ptr;
  while (t < _n_tasks) {
    jint res = Atomic::cmpxchg(t+1, n_claimed_ptr, t);
    if (res == (jint)t) {
      return false;
    }
    t = *n_claimed_ptr;
  }
  return true;
}
bool SequentialSubTasksDone::all_tasks_completed() {
  uint* n_completed_ptr = &_n_completed;
  uint  complete        = *n_completed_ptr;
  while (true) {
    uint res = Atomic::cmpxchg(complete+1, n_completed_ptr, complete);
    if (res == complete) {
      break;
    }
    complete = res;
  }
  if (complete+1 == _n_threads) {
    clear();
    return true;
  }
  return false;
}
bool FreeIdSet::_stat_init = false;
FreeIdSet* FreeIdSet::_sets[NSets];
bool FreeIdSet::_safepoint;
FreeIdSet::FreeIdSet(int sz, Monitor* mon) :
  _sz(sz), _mon(mon), _hd(0), _waiters(0), _index(-1), _claimed(0)
{
  _ids = NEW_C_HEAP_ARRAY(int, sz, mtInternal);
  for (int i = 0; i < sz; i++) _ids[i] = i+1;
  _ids[sz-1] = end_of_list; // end of list.
  if (_stat_init) {
    for (int j = 0; j < NSets; j++) _sets[j] = NULL;
    _stat_init = true;
  }
  for (int j = 0; j < NSets; j++) {
    if (_sets[j] == NULL) {
      _sets[j] = this;
      _index = j;
      break;
    }
  }
  guarantee(_index != -1, "Too many FreeIdSets in use!");
}
FreeIdSet::~FreeIdSet() {
  _sets[_index] = NULL;
  FREE_C_HEAP_ARRAY(int, _ids, mtInternal);
}
void FreeIdSet::set_safepoint(bool b) {
  _safepoint = b;
  if (b) {
    for (int j = 0; j < NSets; j++) {
      if (_sets[j] != NULL && _sets[j]->_waiters > 0) {
        Monitor* mon = _sets[j]->_mon;
        mon->lock_without_safepoint_check();
        mon->notify_all();
        mon->unlock();
      }
    }
  }
}
#define FID_STATS 0
int FreeIdSet::claim_par_id() {
#if FID_STATS
  thread_t tslf = thr_self();
  tty->print("claim_par_id[%d]: sz = %d, claimed = %d\n", tslf, _sz, _claimed);
#endif
  MutexLockerEx x(_mon, Mutex::_no_safepoint_check_flag);
  while (!_safepoint && _hd == end_of_list) {
    _waiters++;
#if FID_STATS
    if (_waiters > 5) {
      tty->print("claim_par_id waiting[%d]: %d waiters, %d claimed.\n",
                 tslf, _waiters, _claimed);
    }
#endif
    _mon->wait(Mutex::_no_safepoint_check_flag);
    _waiters--;
  }
  if (_hd == end_of_list) {
#if FID_STATS
    tty->print("claim_par_id[%d]: returning EOL.\n", tslf);
#endif
    return -1;
  } else {
    int res = _hd;
    _hd = _ids[res];
    _ids[res] = claimed;  // For debugging.
    _claimed++;
#if FID_STATS
    tty->print("claim_par_id[%d]: returning %d, claimed = %d.\n",
               tslf, res, _claimed);
#endif
    return res;
  }
}
bool FreeIdSet::claim_perm_id(int i) {
  assert(0 <= i && i < _sz, "Out of range.");
  MutexLockerEx x(_mon, Mutex::_no_safepoint_check_flag);
  int prev = end_of_list;
  int cur = _hd;
  while (cur != end_of_list) {
    if (cur == i) {
      if (prev == end_of_list) {
        _hd = _ids[cur];
      } else {
        _ids[prev] = _ids[cur];
      }
      _ids[cur] = claimed;
      _claimed++;
      return true;
    } else {
      prev = cur;
      cur = _ids[cur];
    }
  }
  return false;
}
void FreeIdSet::release_par_id(int id) {
  MutexLockerEx x(_mon, Mutex::_no_safepoint_check_flag);
  assert(_ids[id] == claimed, "Precondition.");
  _ids[id] = _hd;
  _hd = id;
  _claimed--;
#if FID_STATS
  tty->print("[%d] release_par_id(%d), waiters =%d,  claimed = %d.\n",
             thr_self(), id, _waiters, _claimed);
#endif
  if (_waiters > 0)
    _mon->notify_all();
}
C:\hotspot-69087d08d473\src\share\vm/utilities/workgroup.hpp
#ifndef SHARE_VM_UTILITIES_WORKGROUP_HPP
#define SHARE_VM_UTILITIES_WORKGROUP_HPP
#include "runtime/thread.inline.hpp"
#include "utilities/taskqueue.hpp"
class WorkGang;
class GangWorker;
class YieldingFlexibleGangWorker;
class YieldingFlexibleGangTask;
class WorkData;
class AbstractWorkGang;
class AbstractGangTask VALUE_OBJ_CLASS_SPEC {
public:
  virtual void work(uint worker_id) = 0;
  virtual void set_for_termination(int active_workers) {};
  const char* name() const PRODUCT_RETURN_(return NULL;);
  int counter() { return _counter; }
  void set_counter(int value) { _counter = value; }
  int *address_of_counter() { return &_counter; }
  NOT_PRODUCT(virtual bool is_YieldingFlexibleGang_task() const {
    return false;
  })
private:
  NOT_PRODUCT(const char* _name;)
  int _counter;
protected:
  AbstractGangTask(const char* name)
  {
    NOT_PRODUCT(_name = name);
    _counter = 0;
  }
  ~AbstractGangTask() { }
public:
};
class AbstractGangTaskWOopQueues : public AbstractGangTask {
  OopTaskQueueSet*       _queues;
  ParallelTaskTerminator _terminator;
 public:
  AbstractGangTaskWOopQueues(const char* name, OopTaskQueueSet* queues) :
    AbstractGangTask(name), _queues(queues), _terminator(0, _queues) {}
  ParallelTaskTerminator* terminator() { return &_terminator; }
  virtual void set_for_termination(int active_workers) {
    terminator()->reset_for_reuse(active_workers);
  }
  OopTaskQueueSet* queues() { return _queues; }
};
class AbstractWorkGang: public CHeapObj<mtInternal> {
public:
  AbstractWorkGang(const char* name, bool are_GC_task_threads,
                   bool are_ConcurrentGC_threads);
  ~AbstractWorkGang();
  virtual void run_task(AbstractGangTask* task) = 0;
  virtual void stop();
  virtual bool needs_more_workers() const { return true; }
public:
  const char* name() const;
protected:
  const bool _are_GC_task_threads;
  const bool _are_ConcurrentGC_threads;
  const char* _name;
  Monitor*  _monitor;
  uint _total_workers;
  bool _terminate;
  GangWorker** _gang_workers;
  AbstractGangTask* _task;
  int _sequence_number;
  uint _started_workers;
  uint _finished_workers;
public:
  Monitor* monitor() const {
    return _monitor;
  }
  uint total_workers() const {
    return _total_workers;
  }
  virtual uint active_workers() const {
    return _total_workers;
  }
  bool terminate() const {
    return _terminate;
  }
  GangWorker** gang_workers() const {
    return _gang_workers;
  }
  AbstractGangTask* task() const {
    return _task;
  }
  int sequence_number() const {
    return _sequence_number;
  }
  uint started_workers() const {
    return _started_workers;
  }
  uint finished_workers() const {
    return _finished_workers;
  }
  bool are_GC_task_threads() const {
    return _are_GC_task_threads;
  }
  bool are_ConcurrentGC_threads() const {
    return _are_ConcurrentGC_threads;
  }
  bool is_idle() const {
    return (task() == NULL);
  }
  GangWorker* gang_worker(uint i) const;
  void threads_do(ThreadClosure* tc) const;
  void print_worker_threads_on(outputStream *st) const;
  void print_worker_threads() const {
    print_worker_threads_on(tty);
  }
protected:
  friend class GangWorker;
  friend class YieldingFlexibleGangWorker;
  void internal_worker_poll(WorkData* data) const;
  void internal_note_start();
  void internal_note_finish();
};
class WorkData: public StackObj {
private:
  bool              _terminate;
  AbstractGangTask* _task;
  int               _sequence_number;
public:
  WorkData() {
    _terminate       = false;
    _task            = NULL;
    _sequence_number = 0;
  }
  ~WorkData() {
  }
  bool terminate()                       const { return _terminate;  }
  void set_terminate(bool value)               { _terminate = value; }
  AbstractGangTask* task()               const { return _task; }
  void set_task(AbstractGangTask* value)       { _task = value; }
  int sequence_number()                  const { return _sequence_number; }
  void set_sequence_number(int value)          { _sequence_number = value; }
  YieldingFlexibleGangTask* yf_task()    const {
    return (YieldingFlexibleGangTask*)_task;
  }
};
class WorkGang: public AbstractWorkGang {
public:
  WorkGang(const char* name, uint workers,
           bool are_GC_task_threads, bool are_ConcurrentGC_threads);
  virtual void run_task(AbstractGangTask* task);
  void run_task(AbstractGangTask* task, uint no_of_parallel_workers);
  virtual GangWorker* allocate_worker(uint which);
  bool initialize_workers();
};
class GangWorker: public WorkerThread {
public:
  GangWorker(AbstractWorkGang* gang, uint id);
  virtual void run();
  virtual bool is_GC_task_thread() const;
  virtual bool is_ConcurrentGC_thread() const;
  void print_on(outputStream* st) const;
  virtual void print() const { print_on(tty); }
protected:
  AbstractWorkGang* _gang;
  virtual void initialize();
  virtual void loop();
public:
  AbstractWorkGang* gang() const { return _gang; }
};
class FlexibleWorkGang: public WorkGang {
 protected:
  uint _active_workers;
 public:
  FlexibleWorkGang(const char* name, uint workers,
                   bool are_GC_task_threads,
                   bool  are_ConcurrentGC_threads) :
    WorkGang(name, workers, are_GC_task_threads, are_ConcurrentGC_threads),
    _active_workers(UseDynamicNumberOfGCThreads ? 1U : ParallelGCThreads) {}
  virtual uint active_workers() const { return _active_workers; }
  void set_active_workers(uint v) {
    assert(v <= _total_workers,
           "Trying to set more workers active than there are");
    _active_workers = MIN2(v, _total_workers);
    assert(v != 0, "Trying to set active workers to 0");
    _active_workers = MAX2(1U, _active_workers);
    assert(UseDynamicNumberOfGCThreads || _active_workers == _total_workers,
           "Unless dynamic should use total workers");
  }
  virtual void run_task(AbstractGangTask* task);
  virtual bool needs_more_workers() const {
    return _started_workers < _active_workers;
  }
};
class WorkGangBarrierSync : public StackObj {
protected:
  Monitor _monitor;
  uint    _n_workers;
  uint    _n_completed;
  bool    _should_reset;
  bool    _aborted;
  Monitor* monitor()        { return &_monitor; }
  uint     n_workers()      { return _n_workers; }
  uint     n_completed()    { return _n_completed; }
  bool     should_reset()   { return _should_reset; }
  bool     aborted()        { return _aborted; }
  void     zero_completed() { _n_completed = 0; }
  void     inc_completed()  { _n_completed++; }
  void     set_aborted()    { _aborted = true; }
  void     set_should_reset(bool v) { _should_reset = v; }
public:
  WorkGangBarrierSync();
  WorkGangBarrierSync(uint n_workers, const char* name);
  void set_n_workers(uint n_workers);
  bool enter();
  void abort();
};
class SubTasksDone: public CHeapObj<mtInternal> {
  uint* _tasks;
  uint _n_tasks;
  uint _n_threads;
  uint _threads_completed;
#ifdef ASSERT
  volatile uint _claimed;
#endif
  void clear();
public:
  SubTasksDone(uint n);
  bool valid();
  uint n_threads() { return _n_threads; }
  void set_n_threads(uint t);
  bool is_task_claimed(uint t);
  void all_tasks_completed();
  ~SubTasksDone();
};
class SequentialSubTasksDone : public StackObj {
protected:
  uint _n_tasks;     // Total number of tasks available.
  uint _n_claimed;   // Number of tasks claimed.
  uint _n_threads;   // Total number of parallel threads.
  uint _n_completed; // Number of completed threads.
  void clear();
public:
  SequentialSubTasksDone() {
    clear();
  }
  ~SequentialSubTasksDone() {}
  bool valid();
  uint n_tasks() const { return _n_tasks; }
  uint n_threads() { return _n_threads; }
  void set_n_threads(uint t) { _n_threads = t; }
  void set_n_tasks(uint t) { _n_tasks = t; }
  bool is_task_claimed(uint& t);
  bool all_tasks_completed();
};
class FreeIdSet : public CHeapObj<mtInternal> {
  enum {
    end_of_list = -1,
    claimed = -2
  };
  int _sz;
  Monitor* _mon;
  int* _ids;
  int _hd;
  int _waiters;
  int _claimed;
  static bool _safepoint;
  typedef FreeIdSet* FreeIdSetPtr;
  static const int NSets = 10;
  static FreeIdSetPtr _sets[NSets];
  static bool _stat_init;
  int _index;
public:
  FreeIdSet(int sz, Monitor* mon);
  ~FreeIdSet();
  static void set_safepoint(bool b);
  bool claim_perm_id(int i);
  int claim_par_id();
  void release_par_id(int id);
};
#endif // SHARE_VM_UTILITIES_WORKGROUP_HPP
C:\hotspot-69087d08d473\src\share\vm/utilities/xmlstream.cpp
#include "precompiled.hpp"
#include "code/nmethod.hpp"
#include "memory/allocation.hpp"
#include "memory/allocation.inline.hpp"
#include "oops/methodData.hpp"
#include "oops/method.hpp"
#include "oops/oop.inline.hpp"
#include "runtime/deoptimization.hpp"
#include "runtime/vmThread.hpp"
#include "utilities/xmlstream.hpp"
void xmlStream::initialize(outputStream* out) {
  _out = out;
  _last_flush = 0;
  _markup_state = BODY;
  _text_init._outer_xmlStream = this;
  _text = &_text_init;
#ifdef ASSERT
  _element_depth = 0;
  int   init_len = 100;
  char* init_buf = NEW_C_HEAP_ARRAY(char, init_len, mtInternal);
  _element_close_stack_low  = init_buf;
  _element_close_stack_high = init_buf + init_len;
  _element_close_stack_ptr  = init_buf + init_len - 1;
  _element_close_stack_ptr[0] = '\0';
#endif
  if (is_open()) {
    _out->time_stamp().update_to(1);
  }
}
#ifdef ASSERT
xmlStream::~xmlStream() {
  FREE_C_HEAP_ARRAY(char, _element_close_stack_low, mtInternal);
}
#endif
void xmlStream::write(const char* s, size_t len) {
  if (!is_open())  return;
  out()->write(s, len);
  update_position(s, len);
}
void xmlStream::write_text(const char* s, size_t len) {
  if (!is_open())  return;
  size_t written = 0;
  for (size_t i = 0; i < len; i++) {
    char ch = s[i];
    const char* esc = NULL;
    switch (ch) {
    case '\'': esc = "&apos;"; break;
    case '"':  esc = "&quot;"; break;
    case '<':  esc = "&lt;";   break;
    case '&':  esc = "&amp;";  break;
    case '>':  esc = "&gt;";   break;
    }
    if (esc != NULL) {
      if (written < i) {
        out()->write(&s[written], i - written);
        written = i;
      }
      out()->print_raw(esc);
      written++;
    }
  }
  if (written < len) {
    out()->write(&s[written], len - written);
  }
}
void xmlStream::text(const char* format, ...) {
  va_list ap;
  va_start(ap, format);
  va_text(format, ap);
  va_end(ap);
}
#define BUFLEN 2*K   /* max size of output of individual print methods */
void xmlStream::va_tag(bool push, const char* format, va_list ap) {
  assert_if_no_error(!inside_attrs(), "cannot print tag inside attrs");
  char buffer[BUFLEN];
  size_t len;
  const char* kind = do_vsnprintf(buffer, BUFLEN, format, ap, false, len);
  see_tag(kind, push);
  print_raw("<");
  write(kind, len);
  _markup_state = (push ? HEAD : ELEM);
}
#ifdef ASSERT
void xmlStream::see_tag(const char* tag, bool push) {
  assert_if_no_error(!inside_attrs(), "cannot start new element inside attrs");
  if (!push)  return;
  const char* tag_end = strchr(tag, ' ');
  size_t tag_len = (tag_end == NULL) ? strlen(tag) : tag_end - tag;
  assert(tag_len > 0, "tag must not be empty");
  char* old_ptr  = _element_close_stack_ptr;
  char* old_low  = _element_close_stack_low;
  char* push_ptr = old_ptr - (tag_len+1);
  if (push_ptr < old_low) {
    int old_len = _element_close_stack_high - old_ptr;
    int new_len = old_len * 2;
    if (new_len < 100)  new_len = 100;
    char* new_low  = NEW_C_HEAP_ARRAY(char, new_len, mtInternal);
    char* new_high = new_low + new_len;
    char* new_ptr  = new_high - old_len;
    memcpy(new_ptr, old_ptr, old_len);
    _element_close_stack_high = new_high;
    _element_close_stack_low  = new_low;
    _element_close_stack_ptr  = new_ptr;
    FREE_C_HEAP_ARRAY(char, old_low, mtInternal);
    push_ptr = new_ptr - (tag_len+1);
  }
  assert(push_ptr >= _element_close_stack_low, "in range");
  memcpy(push_ptr, tag, tag_len);
  push_ptr[tag_len] = 0;
  _element_close_stack_ptr = push_ptr;
  _element_depth += 1;
}
void xmlStream::pop_tag(const char* tag) {
  assert_if_no_error(!inside_attrs(), "cannot close element inside attrs");
  assert(_element_depth > 0, "must be in an element to close");
  assert(*tag != 0, "tag must not be empty");
  char* cur_tag = _element_close_stack_ptr;
  bool  bad_tag = false;
  while (*cur_tag != 0 && strcmp(cur_tag, tag) != 0) {
    this->print_cr("</%s> <!-- missing closing tag -->", cur_tag);
    _element_close_stack_ptr = (cur_tag += strlen(cur_tag) + 1);
    _element_depth -= 1;
    bad_tag = true;
  }
  if (*cur_tag == 0) {
    bad_tag = true;
  } else {
    _element_close_stack_ptr = cur_tag + strlen(cur_tag) + 1;
    _element_depth -= 1;
  }
  if (bad_tag && !VMThread::should_terminate() && !VM_Exit::vm_exited() &&
      !is_error_reported())
  {
    assert(false, "bad tag in log");
  }
}
#endif
void xmlStream::elem(const char* format, ...) {
  va_list ap;
  va_start(ap, format);
  va_elem(format, ap);
  va_end(ap);
}
void xmlStream::va_elem(const char* format, va_list ap) {
  va_begin_elem(format, ap);
  end_elem();
}
void xmlStream::begin_elem(const char* format, ...) {
  va_list ap;
  va_start(ap, format);
  va_tag(false, format, ap);
  va_end(ap);
}
void xmlStream::va_begin_elem(const char* format, va_list ap) {
  va_tag(false, format, ap);
}
void xmlStream::end_elem() {
  assert(_markup_state == ELEM, "misplaced end_elem");
  print_raw("/>\n");
  _markup_state = BODY;
}
void xmlStream::end_elem(const char* format, ...) {
  va_list ap;
  va_start(ap, format);
  out()->vprint(format, ap);
  va_end(ap);
  end_elem();
}
void xmlStream::head(const char* format, ...) {
  va_list ap;
  va_start(ap, format);
  va_head(format, ap);
  va_end(ap);
}
void xmlStream::va_head(const char* format, va_list ap) {
  va_begin_head(format, ap);
  end_head();
}
void xmlStream::begin_head(const char* format, ...) {
  va_list ap;
  va_start(ap, format);
  va_tag(true, format, ap);
  va_end(ap);
}
void xmlStream::va_begin_head(const char* format, va_list ap) {
  va_tag(true, format, ap);
}
void xmlStream::end_head() {
  assert(_markup_state == HEAD, "misplaced end_head");
  print_raw(">\n");
  _markup_state = BODY;
}
void xmlStream::end_head(const char* format, ...) {
  va_list ap;
  va_start(ap, format);
  out()->vprint(format, ap);
  va_end(ap);
  end_head();
}
void xmlStream::tail(const char* kind) {
  pop_tag(kind);
  print_raw("</");
  print_raw(kind);
  print_raw(">\n");
}
void xmlStream::done(const char* format, ...) {
  va_list ap;
  va_start(ap, format);
  va_done(format, ap);
  va_end(ap);
}
void xmlStream::done_raw(const char* kind) {
  print_raw("<");
  print_raw(kind);
  print_raw("_done stamp='");
  out()->stamp();
  print_raw_cr("'/>");
  print_raw("</");
  print_raw(kind);
  print_raw_cr(">");
}
PRAGMA_DIAG_PUSH
PRAGMA_FORMAT_NONLITERAL_IGNORED
void xmlStream::va_done(const char* format, va_list ap) {
  char buffer[200];
  guarantee(strlen(format) + 10 < sizeof(buffer), "bigger format buffer");
  const char* kind = format;
  const char* kind_end = strchr(kind, ' ');
  size_t kind_len = (kind_end != NULL) ? (kind_end - kind) : strlen(kind);
  strncpy(buffer, kind, kind_len);
  strcpy(buffer + kind_len, "_done");
  strcat(buffer, format + kind_len);
  va_begin_elem(buffer, ap);
  stamp();
  end_elem();
  buffer[kind_len] = 0;
  tail(buffer);
}
PRAGMA_DIAG_POP
void xmlStream::stamp() {
  assert_if_no_error(inside_attrs(), "stamp must be an attribute");
  print_raw(" stamp='");
  out()->stamp();
  print_raw("'");
}
void xmlStream::method(methodHandle method) {
  assert_if_no_error(inside_attrs(), "printing attributes");
  if (method.is_null())  return;
  print_raw(" method='");
  method_text(method);
  print("' bytes='%d'", method->code_size());
  print(" count='%d'", method->invocation_count());
  int bec = method->backedge_count();
  if (bec != 0)  print(" backedge_count='%d'", bec);
  print(" iicount='%d'", method->interpreter_invocation_count());
  int throwouts = method->interpreter_throwout_count();
  if (throwouts != 0)  print(" throwouts='%d'", throwouts);
  MethodData* mdo = method->method_data();
  if (mdo != NULL) {
    uint cnt;
    cnt = mdo->decompile_count();
    if (cnt != 0)  print(" decompiles='%d'", cnt);
    for (uint reason = 0; reason < mdo->trap_reason_limit(); reason++) {
      cnt = mdo->trap_count(reason);
      if (cnt != 0)  print(" %s_traps='%d'", Deoptimization::trap_reason_name(reason), cnt);
    }
    cnt = mdo->overflow_trap_count();
    if (cnt != 0)  print(" overflow_traps='%d'", cnt);
    cnt = mdo->overflow_recompile_count();
    if (cnt != 0)  print(" overflow_recompiles='%d'", cnt);
  }
}
void xmlStream::method_text(methodHandle method) {
  assert_if_no_error(inside_attrs(), "printing attributes");
  if (method.is_null())  return;
  method->method_holder()->name()->print_symbol_on(text());
  print_raw(" ");  // " " is easier for tools to parse than "::"
  method->name()->print_symbol_on(text());
  print_raw(" ");  // separator
  method->signature()->print_symbol_on(text());
}
void xmlStream::klass(KlassHandle klass) {
  assert_if_no_error(inside_attrs(), "printing attributes");
  if (klass.is_null())  return;
  print_raw(" klass='");
  klass_text(klass);
  print_raw("'");
}
void xmlStream::klass_text(KlassHandle klass) {
  assert_if_no_error(inside_attrs(), "printing attributes");
  if (klass.is_null())  return;
  klass->name()->print_symbol_on(out());
}
void xmlStream::name(const Symbol* name) {
  assert_if_no_error(inside_attrs(), "printing attributes");
  if (name == NULL)  return;
  print_raw(" name='");
  name_text(name);
  print_raw("'");
}
void xmlStream::name_text(const Symbol* name) {
  assert_if_no_error(inside_attrs(), "printing attributes");
  if (name == NULL)  return;
  name->print_symbol_on(text());
}
void xmlStream::object(const char* attr, Handle x) {
  assert_if_no_error(inside_attrs(), "printing attributes");
  if (x == NULL)  return;
  print_raw(" ");
  print_raw(attr);
  print_raw("='");
  object_text(x);
  print_raw("'");
}
void xmlStream::object_text(Handle x) {
  assert_if_no_error(inside_attrs(), "printing attributes");
  if (x == NULL)  return;
  x->print_value_on(text());
}
void xmlStream::object(const char* attr, Metadata* x) {
  assert_if_no_error(inside_attrs(), "printing attributes");
  if (x == NULL)  return;
  print_raw(" ");
  print_raw(attr);
  print_raw("='");
  object_text(x);
  print_raw("'");
}
void xmlStream::object_text(Metadata* x) {
  assert_if_no_error(inside_attrs(), "printing attributes");
  if (x == NULL)  return;
  if (x->is_method())
    method_text((Method*)x);
  else if (x->is_klass())
    klass_text((Klass*)x);
  else
    ShouldNotReachHere(); // Add impl if this is reached.
}
void xmlStream::flush() {
  out()->flush();
  _last_flush = count();
}
void xmlTextStream::flush() {
  if (_outer_xmlStream == NULL)  return;
  _outer_xmlStream->flush();
}
void xmlTextStream::write(const char* str, size_t len) {
  if (_outer_xmlStream == NULL)  return;
  _outer_xmlStream->write_text(str, len);
  update_position(str, len);
}
C:\hotspot-69087d08d473\src\share\vm/utilities/xmlstream.hpp
#ifndef SHARE_VM_UTILITIES_XMLSTREAM_HPP
#define SHARE_VM_UTILITIES_XMLSTREAM_HPP
#include "runtime/handles.hpp"
#include "utilities/ostream.hpp"
class xmlStream;
class defaultStream;
class xmlTextStream : public outputStream {
  friend class xmlStream;
  friend class defaultStream; // tty
 private:
  xmlStream* _outer_xmlStream;
  xmlTextStream() { _outer_xmlStream = NULL; }
 public:
   virtual void flush(); // _outer.flush();
   virtual void write(const char* str, size_t len); // _outer->write_text()
};
class xmlStream : public outputStream {
  friend class defaultStream; // tty
 public:
  enum MarkupState { BODY,       // after end_head() call, in text
                     HEAD,       // after begin_head() call, in attrs
                     ELEM };     // after begin_elem() call, in attrs
 protected:
  outputStream* _out;            // file stream by which it goes
  julong        _last_flush;     // last position of flush
  MarkupState   _markup_state;   // where in the elem/head/tail dance
  outputStream* _text;           // text stream
  xmlTextStream _text_init;
  xmlStream() {}
  void initialize(outputStream* out);
  outputStream* out()                            { return _out; }
  void          va_tag(bool push, const char* format, va_list ap) ATTRIBUTE_PRINTF(3, 0);
  virtual void see_tag(const char* tag, bool push) NOT_DEBUG({});
  virtual void pop_tag(const char* tag) NOT_DEBUG({});
#ifdef ASSERT
  int   _element_depth;              // number of unfinished elements
  char* _element_close_stack_high;   // upper limit of down-growing stack
  char* _element_close_stack_low;    // upper limit of down-growing stack
  char* _element_close_stack_ptr;    // pointer of down-growing stack
#endif
 public:
  xmlStream(outputStream* out) { initialize(out); }
  DEBUG_ONLY(virtual ~xmlStream();)
  bool is_open() { return _out != NULL; }
  bool inside_attrs() { return _markup_state != BODY; }
  virtual void flush();  // flushes out, sets _last_flush = count()
  virtual void write(const char* s, size_t len);
  void    write_text(const char* s, size_t len);  // used by xmlTextStream
  int unflushed_count() { return (int)(out()->count() - _last_flush); }
  void          elem(const char* format, ...) ATTRIBUTE_PRINTF(2, 3);
  void    begin_elem(const char* format, ...) ATTRIBUTE_PRINTF(2, 3);
  void      end_elem(const char* format, ...) ATTRIBUTE_PRINTF(2, 3);
  void      end_elem();
  void          head(const char* format, ...) ATTRIBUTE_PRINTF(2, 3);
  void    begin_head(const char* format, ...) ATTRIBUTE_PRINTF(2, 3);
  void      end_head(const char* format, ...) ATTRIBUTE_PRINTF(2, 3);
  void      end_head();
  void          done(const char* format, ...) ATTRIBUTE_PRINTF(2, 3);  // xxx_done event, plus tail
  void          done_raw(const char * kind);
  void          tail(const char* kind);
  void       va_elem(const char* format, va_list ap) ATTRIBUTE_PRINTF(2, 0);
  void va_begin_elem(const char* format, va_list ap) ATTRIBUTE_PRINTF(2, 0);
  void       va_head(const char* format, va_list ap) ATTRIBUTE_PRINTF(2, 0);
  void va_begin_head(const char* format, va_list ap) ATTRIBUTE_PRINTF(2, 0);
  void       va_done(const char* format, va_list ap) ATTRIBUTE_PRINTF(2, 0);
  outputStream* text() { return _text; }
  void          text(const char* format, ...) ATTRIBUTE_PRINTF(2, 3);
  void       va_text(const char* format, va_list ap) ATTRIBUTE_PRINTF(2, 0) {
    text()->vprint(format, ap);
  }
  void          stamp();                 // stamp='1.234'
  void          method(methodHandle m);  // method='k n s' ...
  void          klass(KlassHandle k);    // klass='name'
  void          name(const Symbol* s);   // name='name'
  void          object(const char* attr, Metadata* val);
  void          object(const char* attr, Handle val);
  void          method_text(methodHandle m);
  void          klass_text(KlassHandle k);    // klass='name'
  void          name_text(const Symbol* s);   // name='name'
  void          object_text(Metadata* x);
  void          object_text(Handle x);
      elem("X Y='Z'");          <X Y='Z'/> \n
      begin_elem("X Y='Z'");    <X Y='Z'
      ...attrs...               ...attrs...
      end_elem();               />
      head("X Y='Z'");          <X Y='Z'> \n
      ...body...                ...body...
      tail("X");                </X> \n
      begin_head("X Y='Z'");    <X Y='Z'
      ...attrs...               ...attrs...
      end_head();               > \n
      ...body...                ...body...
      tail("X");                </X> \n
      elem("X Y='%s'", "Z");    <X Y='Z'/> \n
};
extern xmlStream* xtty;
#endif // SHARE_VM_UTILITIES_XMLSTREAM_HPP
C:\hotspot-69087d08d473\src\share\vm/utilities/yieldingWorkgroup.cpp
#include "precompiled.hpp"
#include "utilities/macros.hpp"
#include "utilities/yieldingWorkgroup.hpp"
class GangWorker;
class WorkData;
YieldingFlexibleWorkGang::YieldingFlexibleWorkGang(
  const char* name, uint workers, bool are_GC_task_threads) :
  FlexibleWorkGang(name, workers, are_GC_task_threads, false),
    _yielded_workers(0) {}
GangWorker* YieldingFlexibleWorkGang::allocate_worker(uint which) {
  YieldingFlexibleGangWorker* new_member =
      new YieldingFlexibleGangWorker(this, which);
  return (YieldingFlexibleGangWorker*) new_member;
}
Each gang is working on a task at a certain time.
Some subset of workers may have yielded and some may
have finished their quota of work. Until this task has
been completed, the workers are bound to that task.
Once the task has been completed, the gang unbounds
itself from the task.
The yielding work gang thus exports two invokation
interfaces: run_task() and continue_task(). The
first is used to initiate a new task and bind it
to the workers; the second is used to continue an
already bound task that has yielded. Upon completion
the binding is released and a new binding may be
created.
The shape of a yielding work gang is as follows:
Overseer invokes run_task(*task).
   Lock gang monitor
   Check that there is no existing binding for the gang
   If so, abort with an error
   Else, create a new binding of this gang to the given task
   Set number of active workers (as asked)
   Notify workers that work is ready to be done
     [the requisite # workers would then start up
      and do the task]
   Wait on the monitor until either
     all work is completed or the task has yielded
     -- this is normally done through
        yielded + completed == active
        [completed workers are rest to idle state by overseer?]
   return appropriate status to caller
Overseer invokes continue_task(*task),
   Lock gang monitor
   Check that task is the same as current binding
   If not, abort with an error
   Else, set the number of active workers as requested?
   Notify workers that they can continue from yield points
    New workers can also start up as required
      while satisfying the constraint that
         active + yielded does not exceed required number
   Wait (as above).
NOTE: In the above, for simplicity in a first iteration
  our gangs will be of fixed population and will not
  therefore be flexible work gangs, just yielding work
  gangs. Once this works well, we will in a second
  iteration.refinement introduce flexibility into
  the work gang.
NOTE: we can always create a new gang per each iteration
  in order to get the flexibility, but we will for now
  desist that simplified route.
void YieldingFlexibleWorkGang::start_task(YieldingFlexibleGangTask* new_task) {
  MutexLockerEx ml(monitor(), Mutex::_no_safepoint_check_flag);
  assert(task() == NULL, "Gang currently tied to a task");
  assert(new_task != NULL, "Null task");
  _task = new_task;
  new_task->set_gang(this);  // Establish 2-way binding to support yielding
  _sequence_number++;
  uint requested_size = new_task->requested_size();
  assert(requested_size >= 0, "Should be non-negative");
  if (requested_size != 0) {
    _active_workers = MIN2(requested_size, total_workers());
  } else {
    _active_workers = active_workers();
  }
  new_task->set_actual_size(_active_workers);
  new_task->set_for_termination(_active_workers);
  assert(_started_workers == 0, "Tabula rasa non");
  assert(_finished_workers == 0, "Tabula rasa non");
  assert(_yielded_workers == 0, "Tabula rasa non");
  yielding_task()->set_status(ACTIVE);
  monitor()->notify_all();
  wait_for_gang();
}
void YieldingFlexibleWorkGang::wait_for_gang() {
  assert(monitor()->owned_by_self(), "Data race");
  for (Status status = yielding_task()->status();
       status != COMPLETED && status != YIELDED && status != ABORTED;
       status = yielding_task()->status()) {
    assert(started_workers() <= active_workers(), "invariant");
    assert(finished_workers() <= active_workers(), "invariant");
    assert(yielded_workers() <= active_workers(), "invariant");
    monitor()->wait(Mutex::_no_safepoint_check_flag);
  }
  switch (yielding_task()->status()) {
    case COMPLETED:
    case ABORTED: {
      assert(finished_workers() == active_workers(), "Inconsistent status");
      assert(yielded_workers() == 0, "Invariant");
      reset();   // for next task; gang<->task binding released
      break;
    }
    case YIELDED: {
      assert(yielded_workers() > 0, "Invariant");
      assert(yielded_workers() + finished_workers() == active_workers(),
             "Inconsistent counts");
      break;
    }
    case ACTIVE:
    case INACTIVE:
    case COMPLETING:
    case YIELDING:
    case ABORTING:
    default:
      ShouldNotReachHere();
  }
}
void YieldingFlexibleWorkGang::continue_task(
  YieldingFlexibleGangTask* gang_task) {
  MutexLockerEx ml(monitor(), Mutex::_no_safepoint_check_flag);
  assert(task() != NULL && task() == gang_task, "Incorrect usage");
  assert(_started_workers == _active_workers, "Precondition");
  assert(_yielded_workers > 0 && yielding_task()->status() == YIELDED,
         "Else why are we calling continue_task()");
  yielding_task()->set_status(ACTIVE);
  monitor()->notify_all();
  wait_for_gang();
}
void YieldingFlexibleWorkGang::reset() {
  _started_workers  = 0;
  _finished_workers = 0;
  yielding_task()->set_gang(NULL);
  _task = NULL;    // unbind gang from task
}
void YieldingFlexibleWorkGang::yield() {
  assert(task() != NULL, "Inconsistency; should have task binding");
  MutexLockerEx ml(monitor(), Mutex::_no_safepoint_check_flag);
  assert(yielded_workers() < active_workers(), "Consistency check");
  if (yielding_task()->status() == ABORTING) {
    return;
  }
  if (++_yielded_workers + finished_workers() == active_workers()) {
    yielding_task()->set_status(YIELDED);
    monitor()->notify_all();
  } else {
    yielding_task()->set_status(YIELDING);
  }
  while (true) {
    switch (yielding_task()->status()) {
      case YIELDING:
      case YIELDED: {
        monitor()->wait(Mutex::_no_safepoint_check_flag);
        break;  // from switch
      }
      case ACTIVE:
      case ABORTING:
      case COMPLETING: {
        assert(_yielded_workers > 0, "Else why am i here?");
        _yielded_workers--;
        return;
      }
      case INACTIVE:
      case ABORTED:
      case COMPLETED:
      default: {
        ShouldNotReachHere();
      }
    }
  }
  ShouldNotReachHere();
}
void YieldingFlexibleWorkGang::abort() {
  assert(task() != NULL, "Inconsistency; should have task binding");
  MutexLockerEx ml(monitor(), Mutex::_no_safepoint_check_flag);
  assert(yielded_workers() < active_workers(), "Consistency check");
  #ifndef PRODUCT
    switch (yielding_task()->status()) {
      case ACTIVE:
      case ABORTING:
      case COMPLETING:
      case YIELDING:
        break;
      case INACTIVE:
      case ABORTED:
      case COMPLETED:
      case YIELDED:
      default:
        ShouldNotReachHere();
    }
  #endif // !PRODUCT
  Status prev_status = yielding_task()->status();
  yielding_task()->set_status(ABORTING);
  if (prev_status == YIELDING) {
    assert(yielded_workers() > 0, "Inconsistency");
    monitor()->notify_all();
  }
}
void YieldingFlexibleGangTask::yield() {
  assert(gang() != NULL, "No gang to signal");
  gang()->yield();
}
void YieldingFlexibleGangTask::abort() {
  assert(gang() != NULL, "No gang to signal");
  gang()->abort();
}
void YieldingFlexibleGangWorker::loop() {
  int previous_sequence_number = 0;
  Monitor* gang_monitor = gang()->monitor();
  MutexLockerEx ml(gang_monitor, Mutex::_no_safepoint_check_flag);
  WorkData data;
  int id;
  while (true) {
    gang()->internal_worker_poll(&data);
    if (data.terminate()) {
      assert(gang()->task() == NULL, "No task binding");
      return;
    } else if (data.task() != NULL &&
               data.sequence_number() != previous_sequence_number) {
      if (gang()->started_workers() == yf_gang()->active_workers()) {
      } else {
        assert(gang()->started_workers() < yf_gang()->active_workers(),
               "Unexpected state");
        id = gang()->started_workers();
        gang()->internal_note_start();
        {
          MutexUnlockerEx mul(gang_monitor, Mutex::_no_safepoint_check_flag);
          data.task()->work(id);   // This might include yielding
        }
        gang()->internal_note_finish();
        assert(data.task() == gang()->task(), "Confused task binding");
        if (gang()->finished_workers() == yf_gang()->active_workers()) {
          switch (data.yf_task()->status()) {
            case ABORTING: {
              data.yf_task()->set_status(ABORTED);
              break;
            }
            case ACTIVE:
            case COMPLETING: {
              data.yf_task()->set_status(COMPLETED);
              break;
            }
            default:
              ShouldNotReachHere();
          }
          gang_monitor->notify_all();  // Notify overseer
        } else { // at least one worker is still working or yielded
          assert(gang()->finished_workers() < yf_gang()->active_workers(),
                 "Counts inconsistent");
          switch (data.yf_task()->status()) {
            case ACTIVE: {
              data.yf_task()->set_status(COMPLETING);
              break;
            }
            case YIELDING: {
              if (gang()->finished_workers() + yf_gang()->yielded_workers()
                  == yf_gang()->active_workers()) {
                data.yf_task()->set_status(YIELDED);
                gang_monitor->notify_all();  // notify overseer
              }
              break;
            }
            case ABORTING:
            case COMPLETING: {
              break; // nothing to do
            }
            default: // everything else: INACTIVE, YIELDED, ABORTED, COMPLETED
              ShouldNotReachHere();
          }
        }
      }
    }
    previous_sequence_number = data.sequence_number();
    gang_monitor->wait(Mutex::_no_safepoint_check_flag);
  }
}
C:\hotspot-69087d08d473\src\share\vm/utilities/yieldingWorkgroup.hpp
#ifndef SHARE_VM_UTILITIES_YIELDINGWORKGROUP_HPP
#define SHARE_VM_UTILITIES_YIELDINGWORKGROUP_HPP
#include "utilities/macros.hpp"
#include "utilities/workgroup.hpp"
class YieldingFlexibleWorkGang;
enum Status {
    INACTIVE,
    ACTIVE,
    YIELDING,
    YIELDED,
    ABORTING,
    ABORTED,
    COMPLETING,
    COMPLETED
};
class YieldingFlexibleGangWorker: public GangWorker {
public:
  YieldingFlexibleGangWorker(AbstractWorkGang* gang, int id) :
    GangWorker(gang, id) { }
public:
  YieldingFlexibleWorkGang* yf_gang() const
    { return (YieldingFlexibleWorkGang*)gang(); }
protected: // Override from parent class
  virtual void loop();
};
class FlexibleGangTask: public AbstractGangTask {
  int _actual_size;                      // size of gang obtained
protected:
  int _requested_size;                   // size of gang requested
public:
 FlexibleGangTask(const char* name): AbstractGangTask(name),
    _requested_size(0) {}
  virtual void work(uint worker_id) = 0;
  int requested_size() const { return _requested_size; }
  int actual_size()    const { return _actual_size; }
  void set_requested_size(int sz) { _requested_size = sz; }
  void set_actual_size(int sz)    { _actual_size    = sz; }
};
class YieldingFlexibleGangTask: public FlexibleGangTask {
  Status _status;
  YieldingFlexibleWorkGang* _gang;
protected:
  YieldingFlexibleGangTask(const char* name): FlexibleGangTask(name),
    _status(INACTIVE),
    _gang(NULL) { }
  ~YieldingFlexibleGangTask() { }
  friend class YieldingFlexibleWorkGang;
  friend class YieldingFlexibleGangWorker;
  NOT_PRODUCT(virtual bool is_YieldingFlexibleGang_task() const {
    return true;
  })
  void set_status(Status s) {
    _status = s;
  }
  YieldingFlexibleWorkGang* gang() {
    return _gang;
  }
  void set_gang(YieldingFlexibleWorkGang* gang) {
    assert(_gang == NULL || gang == NULL, "Clobber without intermediate reset?");
    _gang = gang;
  }
public:
  virtual void work(uint worker_id) = 0;
  virtual void yield();
  virtual void coordinator_yield() = 0;
  virtual void abort();
  Status status()  const { return _status; }
  bool yielding()  const { return _status == YIELDING; }
  bool yielded()   const { return _status == YIELDED; }
  bool completed() const { return _status == COMPLETED; }
  bool aborted()   const { return _status == ABORTED; }
  bool active()    const { return _status == ACTIVE; }
};
class YieldingFlexibleWorkGang: public FlexibleWorkGang {
public:
  YieldingFlexibleWorkGang(const char* name, uint workers,
                           bool are_GC_task_threads);
  YieldingFlexibleGangTask* yielding_task() const {
    assert(task() == NULL || task()->is_YieldingFlexibleGang_task(),
           "Incorrect cast");
    return (YieldingFlexibleGangTask*)task();
  }
  GangWorker* allocate_worker(uint which);
  void run_task(AbstractGangTask* task) {
    guarantee(false, "Use start_task instead");
  }
  void start_task(YieldingFlexibleGangTask* new_task);
  void continue_task(YieldingFlexibleGangTask* gang_task);
  void abort_task();
  void yield();
  void abort();
private:
  uint _yielded_workers;
  void wait_for_gang();
public:
  uint yielded_workers() const {
    return _yielded_workers;
  }
private:
  friend class YieldingFlexibleGangWorker;
  void reset(); // NYI
};
#endif // SHARE_VM_UTILITIES_YIELDINGWORKGROUP_HPP

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值