sssssssss22


class external_word_Relocation : public DataRelocation {
  relocInfo::relocType type() { return relocInfo::external_word_type; }
 public:
  static RelocationHolder spec(address target) {
    assert(target != NULL, "must not be null");
    RelocationHolder rh = newHolder();
    new(rh) external_word_Relocation(target);
    return rh;
  }
  static RelocationHolder spec_for_immediate() {
    RelocationHolder rh = newHolder();
    new(rh) external_word_Relocation(NULL);
    return rh;
  }
  static bool can_be_relocated(address target) {
    return target != NULL && !is_reloc_index((intptr_t)target);
  }
 private:
  address _target;                  // address in runtime
  external_word_Relocation(address target) {
    _target = target;
  }
  friend class RelocIterator;
  external_word_Relocation() { }
 public:
  void pack_data_to(CodeSection* dest);
  void unpack_data();
  void fix_relocation_after_move(const CodeBuffer* src, CodeBuffer* dest);
  address  target();        // if _target==NULL, fetch addr from code stream
  address  value()          { return target(); }
};
class internal_word_Relocation : public DataRelocation {
  relocInfo::relocType type() { return relocInfo::internal_word_type; }
 public:
  static RelocationHolder spec(address target) {
    assert(target != NULL, "must not be null");
    RelocationHolder rh = newHolder();
    new(rh) internal_word_Relocation(target);
    return rh;
  }
  static RelocationHolder spec_for_immediate() {
    RelocationHolder rh = newHolder();
    new(rh) internal_word_Relocation(NULL);
    return rh;
  }
  internal_word_Relocation(address target) {
    _target  = target;
    _section = -1;  // self-relative
  }
 protected:
  address _target;                  // address in CodeBlob
  int     _section;                 // section providing base address, if any
  friend class RelocIterator;
  internal_word_Relocation() { }
  enum { section_width = 2 }; // must equal CodeBuffer::sect_bits
 public:
  void pack_data_to(CodeSection* dest);
  void unpack_data();
  void fix_relocation_after_move(const CodeBuffer* src, CodeBuffer* dest);
  address  target();        // if _target==NULL, fetch addr from code stream
  int      section()        { return _section;   }
  address  value()          { return target();   }
};
class section_word_Relocation : public internal_word_Relocation {
  relocInfo::relocType type() { return relocInfo::section_word_type; }
 public:
  static RelocationHolder spec(address target, int section) {
    RelocationHolder rh = newHolder();
    new(rh) section_word_Relocation(target, section);
    return rh;
  }
  section_word_Relocation(address target, int section) {
    assert(target != NULL, "must not be null");
    assert(section >= 0, "must be a valid section");
    _target  = target;
    _section = section;
  }
  void unpack_data();
 private:
  friend class RelocIterator;
  section_word_Relocation() { }
};
class poll_Relocation : public Relocation {
  bool          is_data()                      { return true; }
  relocInfo::relocType type() { return relocInfo::poll_type; }
  void     fix_relocation_after_move(const CodeBuffer* src, CodeBuffer* dest);
};
class poll_return_Relocation : public Relocation {
  bool          is_data()                      { return true; }
  relocInfo::relocType type() { return relocInfo::poll_return_type; }
  void     fix_relocation_after_move(const CodeBuffer* src, CodeBuffer* dest);
};
#define EACH_CASE(name)                                         \
inline name##_Relocation* RelocIterator::name##_reloc() {       \
  assert(type() == relocInfo::name##_type, "type must agree");  \
  name##_Relocation* r = new(_rh) name##_Relocation();          \
  r->set_binding(this);                                         \
  r->name##_Relocation::unpack_data();                          \
  return r;                                                     \
}
APPLY_TO_RELOCATIONS(EACH_CASE);
#undef EACH_CASE
inline RelocIterator::RelocIterator(nmethod* nm, address begin, address limit) {
  initialize(nm, begin, limit);
}
#endif // SHARE_VM_CODE_RELOCINFO_HPP
C:\hotspot-69087d08d473\src\share\vm/code/scopeDesc.cpp
#include "precompiled.hpp"
#include "code/debugInfoRec.hpp"
#include "code/pcDesc.hpp"
#include "code/scopeDesc.hpp"
#include "memory/resourceArea.hpp"
#include "oops/oop.inline.hpp"
#include "runtime/handles.inline.hpp"
PRAGMA_FORMAT_MUTE_WARNINGS_FOR_GCC
ScopeDesc::ScopeDesc(const nmethod* code, int decode_offset, int obj_decode_offset, bool reexecute, bool return_oop) {
  _code          = code;
  _decode_offset = decode_offset;
  _objects       = decode_object_values(obj_decode_offset);
  _reexecute     = reexecute;
  _return_oop    = return_oop;
  decode_body();
}
ScopeDesc::ScopeDesc(const nmethod* code, int decode_offset, bool reexecute, bool return_oop) {
  _code          = code;
  _decode_offset = decode_offset;
  _objects       = decode_object_values(DebugInformationRecorder::serialized_null);
  _reexecute     = reexecute;
  _return_oop    = return_oop;
  decode_body();
}
ScopeDesc::ScopeDesc(const ScopeDesc* parent) {
  _code          = parent->_code;
  _decode_offset = parent->_sender_decode_offset;
  _objects       = parent->_objects;
  _reexecute     = false; //reexecute only applies to the first scope
  _return_oop    = false;
  decode_body();
}
void ScopeDesc::decode_body() {
  if (decode_offset() == DebugInformationRecorder::serialized_null) {
    _sender_decode_offset = DebugInformationRecorder::serialized_null;
    _method = _code->method();
    _bci = InvocationEntryBci;
    _locals_decode_offset = DebugInformationRecorder::serialized_null;
    _expressions_decode_offset = DebugInformationRecorder::serialized_null;
    _monitors_decode_offset = DebugInformationRecorder::serialized_null;
  } else {
    DebugInfoReadStream* stream  = stream_at(decode_offset());
    _sender_decode_offset = stream->read_int();
    _method = stream->read_method();
    _bci    = stream->read_bci();
    _locals_decode_offset      = stream->read_int();
    _expressions_decode_offset = stream->read_int();
    _monitors_decode_offset    = stream->read_int();
  }
}
GrowableArray<ScopeValue*>* ScopeDesc::decode_scope_values(int decode_offset) {
  if (decode_offset == DebugInformationRecorder::serialized_null) return NULL;
  DebugInfoReadStream* stream = stream_at(decode_offset);
  int length = stream->read_int();
  GrowableArray<ScopeValue*>* result = new GrowableArray<ScopeValue*> (length);
  for (int index = 0; index < length; index++) {
    result->push(ScopeValue::read_from(stream));
  }
  return result;
}
GrowableArray<ScopeValue*>* ScopeDesc::decode_object_values(int decode_offset) {
  if (decode_offset == DebugInformationRecorder::serialized_null) return NULL;
  GrowableArray<ScopeValue*>* result = new GrowableArray<ScopeValue*>();
  DebugInfoReadStream* stream = new DebugInfoReadStream(_code, decode_offset, result);
  int length = stream->read_int();
  for (int index = 0; index < length; index++) {
    (void)ScopeValue::read_from(stream);
  }
  assert(result->length() == length, "inconsistent debug information");
  return result;
}
GrowableArray<MonitorValue*>* ScopeDesc::decode_monitor_values(int decode_offset) {
  if (decode_offset == DebugInformationRecorder::serialized_null) return NULL;
  DebugInfoReadStream* stream  = stream_at(decode_offset);
  int length = stream->read_int();
  GrowableArray<MonitorValue*>* result = new GrowableArray<MonitorValue*> (length);
  for (int index = 0; index < length; index++) {
    result->push(new MonitorValue(stream));
  }
  return result;
}
DebugInfoReadStream* ScopeDesc::stream_at(int decode_offset) const {
  return new DebugInfoReadStream(_code, decode_offset, _objects);
}
GrowableArray<ScopeValue*>* ScopeDesc::locals() {
  return decode_scope_values(_locals_decode_offset);
}
GrowableArray<ScopeValue*>* ScopeDesc::expressions() {
  return decode_scope_values(_expressions_decode_offset);
}
GrowableArray<MonitorValue*>* ScopeDesc::monitors() {
  return decode_monitor_values(_monitors_decode_offset);
}
GrowableArray<ScopeValue*>* ScopeDesc::objects() {
  return _objects;
}
bool ScopeDesc::is_top() const {
 return _sender_decode_offset == DebugInformationRecorder::serialized_null;
}
ScopeDesc* ScopeDesc::sender() const {
  if (is_top()) return NULL;
  return new ScopeDesc(this);
}
#ifndef PRODUCT
void ScopeDesc::print_value_on(outputStream* st) const {
  tty->print("   ");
  method()->print_short_name(st);
  int lineno = method()->line_number_from_bci(bci());
  if (lineno != -1) {
    st->print_cr("@%d (line %d)", bci(), lineno);
  } else {
    st->print_cr("@%d", bci());
  }
}
void ScopeDesc::print_on(outputStream* st) const {
  print_on(st, NULL);
}
void ScopeDesc::print_on(outputStream* st, PcDesc* pd) const {
  if (pd != NULL) {
    tty->print_cr("ScopeDesc(pc=" PTR_FORMAT " offset=%x):", pd->real_pc(_code), pd->pc_offset());
  }
  print_value_on(st);
  if (WizardMode) {
    st->print("ScopeDesc[%d]@" PTR_FORMAT " ", _decode_offset, _code->content_begin());
    st->print_cr(" offset:     %d",    _decode_offset);
    st->print_cr(" bci:        %d",    bci());
    st->print_cr(" reexecute:  %s",    should_reexecute() ? "true" : "false");
    st->print_cr(" locals:     %d",    _locals_decode_offset);
    st->print_cr(" stack:      %d",    _expressions_decode_offset);
    st->print_cr(" monitor:    %d",    _monitors_decode_offset);
    st->print_cr(" sender:     %d",    _sender_decode_offset);
  }
  { GrowableArray<ScopeValue*>* l = ((ScopeDesc*) this)->locals();
    if (l != NULL) {
      tty->print_cr("   Locals");
      for (int index = 0; index < l->length(); index++) {
        st->print("    - l%d: ", index);
        l->at(index)->print_on(st);
        st->cr();
      }
    }
  }
  { GrowableArray<ScopeValue*>* l = ((ScopeDesc*) this)->expressions();
    if (l != NULL) {
      st->print_cr("   Expression stack");
      for (int index = 0; index < l->length(); index++) {
        st->print("   - @%d: ", index);
        l->at(index)->print_on(st);
        st->cr();
      }
    }
  }
  { GrowableArray<MonitorValue*>* l = ((ScopeDesc*) this)->monitors();
    if (l != NULL) {
      st->print_cr("   Monitor stack");
      for (int index = 0; index < l->length(); index++) {
        st->print("    - @%d: ", index);
        l->at(index)->print_on(st);
        st->cr();
      }
    }
  }
#ifdef COMPILER2
  if (DoEscapeAnalysis && is_top() && _objects != NULL) {
    tty->print_cr("Objects");
    for (int i = 0; i < _objects->length(); i++) {
      ObjectValue* sv = (ObjectValue*) _objects->at(i);
      tty->print(" - %d: ", sv->id());
      sv->print_fields_on(tty);
      tty->cr();
    }
  }
#endif // COMPILER2
}
#endif
void ScopeDesc::verify() {
  ResourceMark rm;
  guarantee(method()->is_method(), "type check");
  { GrowableArray<ScopeValue*>* l = expressions();
    if (l != NULL) {
      for (int index = 0; index < l->length(); index++) {
      }
    }
  }
}
C:\hotspot-69087d08d473\src\share\vm/code/scopeDesc.hpp
#ifndef SHARE_VM_CODE_SCOPEDESC_HPP
#define SHARE_VM_CODE_SCOPEDESC_HPP
#include "code/debugInfo.hpp"
#include "code/pcDesc.hpp"
#include "oops/method.hpp"
#include "utilities/growableArray.hpp"
class SimpleScopeDesc : public StackObj {
 private:
  Method* _method;
  int _bci;
 public:
  SimpleScopeDesc(nmethod* code,address pc) {
    PcDesc* pc_desc = code->pc_desc_at(pc);
    assert(pc_desc != NULL, "Must be able to find matching PcDesc");
    DebugInfoReadStream buffer(code, pc_desc->scope_decode_offset());
    int ignore_sender = buffer.read_int();
    _method           = buffer.read_method();
    _bci              = buffer.read_bci();
  }
  Method* method() { return _method; }
  int bci() { return _bci; }
};
class ScopeDesc : public ResourceObj {
 public:
  ScopeDesc(const nmethod* code, int decode_offset, int obj_decode_offset, bool reexecute, bool return_oop);
  ScopeDesc(const nmethod* code, int decode_offset, bool reexecute, bool return_oop);
  Method* method()      const { return _method; }
  int          bci()      const { return _bci;    }
  bool should_reexecute() const { return _reexecute; }
  bool return_oop()       const { return _return_oop; }
  GrowableArray<ScopeValue*>*   locals();
  GrowableArray<ScopeValue*>*   expressions();
  GrowableArray<MonitorValue*>* monitors();
  GrowableArray<ScopeValue*>*   objects();
  ScopeDesc* sender() const;
  int decode_offset() const { return _decode_offset; }
  bool is_top() const;
  bool is_equal(ScopeDesc* sd) const;
 private:
  ScopeDesc(const ScopeDesc* parent);
  Method*       _method;
  int           _bci;
  bool          _reexecute;
  bool          _return_oop;
  int _decode_offset;
  int _sender_decode_offset;
  int _locals_decode_offset;
  int _expressions_decode_offset;
  int _monitors_decode_offset;
  GrowableArray<ScopeValue*>* _objects;
  const nmethod* _code;
  void decode_body();
  GrowableArray<ScopeValue*>* decode_scope_values(int decode_offset);
  GrowableArray<MonitorValue*>* decode_monitor_values(int decode_offset);
  GrowableArray<ScopeValue*>* decode_object_values(int decode_offset);
  DebugInfoReadStream* stream_at(int decode_offset) const;
 public:
  void verify();
#ifndef PRODUCT
 public:
  void print_on(outputStream* st) const;
  void print_on(outputStream* st, PcDesc* pd) const;
  void print_value_on(outputStream* st) const;
#endif
};
#endif // SHARE_VM_CODE_SCOPEDESC_HPP
C:\hotspot-69087d08d473\src\share\vm/code/stubs.cpp
#include "precompiled.hpp"
#include "code/codeBlob.hpp"
#include "code/stubs.hpp"
#include "memory/allocation.inline.hpp"
#include "oops/oop.inline.hpp"
#include "runtime/mutexLocker.hpp"
StubQueue::StubQueue(StubInterface* stub_interface, int buffer_size,
                     Mutex* lock, const char* name) : _mutex(lock) {
  intptr_t size = round_to(buffer_size, 2*BytesPerWord);
  BufferBlob* blob = BufferBlob::create(name, size);
  if( blob == NULL) {
    vm_exit_out_of_memory(size, OOM_MALLOC_ERROR, err_msg("CodeCache: no room for %s", name));
  }
  _stub_interface  = stub_interface;
  _buffer_size     = blob->content_size();
  _buffer_limit    = blob->content_size();
  _stub_buffer     = blob->content_begin();
  _queue_begin     = 0;
  _queue_end       = 0;
  _number_of_stubs = 0;
  register_queue(this);
}
StubQueue::~StubQueue() {
  Unimplemented();
}
Stub* StubQueue::stub_containing(address pc) const {
  if (contains(pc)) {
    for (Stub* s = first(); s != NULL; s = next(s)) {
      if (stub_contains(s, pc)) return s;
    }
  }
  return NULL;
}
Stub* StubQueue::request_committed(int code_size) {
  Stub* s = request(code_size);
  CodeStrings strings;
  if (s != NULL) commit(code_size, strings);
  return s;
}
Stub* StubQueue::request(int requested_code_size) {
  assert(requested_code_size > 0, "requested_code_size must be > 0");
  if (_mutex != NULL) _mutex->lock();
  Stub* s = current_stub();
  int requested_size = round_to(stub_code_size_to_size(requested_code_size), CodeEntryAlignment);
  if (requested_size <= available_space()) {
    if (is_contiguous()) {
      assert(_buffer_limit == _buffer_size, "buffer must be fully usable");
      if (_queue_end + requested_size <= _buffer_size) {
        CodeStrings strings;
        stub_initialize(s, requested_size, strings);
        return s;
      } else {
        assert(!is_empty(), "just checkin'");
        _buffer_limit = _queue_end;
        _queue_end = 0;
      }
    }
  }
  if (requested_size <= available_space()) {
    assert(!is_contiguous(), "just checkin'");
    assert(_buffer_limit <= _buffer_size, "queue invariant broken");
    s = current_stub();
    CodeStrings strings;
    stub_initialize(s, requested_size, strings);
    return s;
  }
  if (_mutex != NULL) _mutex->unlock();
  return NULL;
}
void StubQueue::commit(int committed_code_size, CodeStrings& strings) {
  assert(committed_code_size > 0, "committed_code_size must be > 0");
  int committed_size = round_to(stub_code_size_to_size(committed_code_size), CodeEntryAlignment);
  Stub* s = current_stub();
  assert(committed_size <= stub_size(s), "committed size must not exceed requested size");
  stub_initialize(s, committed_size, strings);
  _queue_end += committed_size;
  _number_of_stubs++;
  if (_mutex != NULL) _mutex->unlock();
  debug_only(stub_verify(s);)
}
void StubQueue::remove_first() {
  if (number_of_stubs() == 0) return;
  Stub* s = first();
  debug_only(stub_verify(s);)
  stub_finalize(s);
  _queue_begin += stub_size(s);
  assert(_queue_begin <= _buffer_limit, "sanity check");
  if (_queue_begin == _queue_end) {
    _queue_begin  = 0;
    _queue_end    = 0;
    _buffer_limit = _buffer_size;
  } else if (_queue_begin == _buffer_limit) {
    _buffer_limit = _buffer_size;
    _queue_begin = 0;
  }
  _number_of_stubs--;
}
void StubQueue::remove_first(int n) {
  int i = MIN2(n, number_of_stubs());
  while (i-- > 0) remove_first();
}
void StubQueue::remove_all(){
  debug_only(verify();)
  remove_first(number_of_stubs());
  assert(number_of_stubs() == 0, "sanity check");
}
enum { StubQueueLimit = 10 };  // there are only a few in the world
static StubQueue* registered_stub_queues[StubQueueLimit];
void StubQueue::register_queue(StubQueue* sq) {
  for (int i = 0; i < StubQueueLimit; i++) {
    if (registered_stub_queues[i] == NULL) {
      registered_stub_queues[i] = sq;
      return;
    }
  }
  ShouldNotReachHere();
}
void StubQueue::queues_do(void f(StubQueue* sq)) {
  for (int i = 0; i < StubQueueLimit; i++) {
    if (registered_stub_queues[i] != NULL) {
      f(registered_stub_queues[i]);
    }
  }
}
void StubQueue::stubs_do(void f(Stub* s)) {
  debug_only(verify();)
  MutexLockerEx lock(_mutex);
  for (Stub* s = first(); s != NULL; s = next(s)) f(s);
}
void StubQueue::verify() {
  if (_stub_buffer == NULL) return;
  MutexLockerEx lock(_mutex);
  guarantee(0 <= _buffer_size, "buffer size must be positive");
  guarantee(0 <= _buffer_limit && _buffer_limit <= _buffer_size , "_buffer_limit out of bounds");
  guarantee(0 <= _queue_begin  && _queue_begin  <  _buffer_limit, "_queue_begin out of bounds");
  guarantee(0 <= _queue_end    && _queue_end    <= _buffer_limit, "_queue_end   out of bounds");
  guarantee(_buffer_size  % CodeEntryAlignment == 0, "_buffer_size  not aligned");
  guarantee(_buffer_limit % CodeEntryAlignment == 0, "_buffer_limit not aligned");
  guarantee(_queue_begin  % CodeEntryAlignment == 0, "_queue_begin  not aligned");
  guarantee(_queue_end    % CodeEntryAlignment == 0, "_queue_end    not aligned");
  if (is_contiguous()) {
    guarantee(_buffer_limit == _buffer_size, "_buffer_limit must equal _buffer_size");
  }
  int n = 0;
  for (Stub* s = first(); s != NULL; s = next(s)) {
    stub_verify(s);
    n++;
  }
  guarantee(n == number_of_stubs(), "number of stubs inconsistent");
  guarantee(_queue_begin != _queue_end || n == 0, "buffer indices must be the same");
}
void StubQueue::print() {
  MutexLockerEx lock(_mutex);
  for (Stub* s = first(); s != NULL; s = next(s)) {
    stub_print(s);
  }
}
C:\hotspot-69087d08d473\src\share\vm/code/stubs.hpp
#ifndef SHARE_VM_CODE_STUBS_HPP
#define SHARE_VM_CODE_STUBS_HPP
#include "asm/codeBuffer.hpp"
#include "memory/allocation.hpp"
#ifdef TARGET_OS_FAMILY_linux
# include "os_linux.inline.hpp"
#endif
#ifdef TARGET_OS_FAMILY_solaris
# include "os_solaris.inline.hpp"
#endif
#ifdef TARGET_OS_FAMILY_windows
# include "os_windows.inline.hpp"
#endif
#ifdef TARGET_OS_FAMILY_aix
# include "os_aix.inline.hpp"
#endif
#ifdef TARGET_OS_FAMILY_bsd
# include "os_bsd.inline.hpp"
#endif
class Stub VALUE_OBJ_CLASS_SPEC {
 public:
  void    initialize(int size,
                     CodeStrings& strings)       { ShouldNotCallThis(); }                // called to initialize/specify the stub's size
  void    finalize()                             { ShouldNotCallThis(); }                // called before the stub is deallocated
  int     size() const                           { ShouldNotCallThis(); return 0; }      // must return the size provided by initialize
  static  int code_size_to_size(int code_size)   { ShouldNotCallThis(); return 0; }      // computes the size given the code size
  address code_begin() const                     { ShouldNotCallThis(); return NULL; }   // points to the first byte of    the code
  address code_end() const                       { ShouldNotCallThis(); return NULL; }   // points to the first byte after the code
  void    verify()                               { ShouldNotCallThis(); }                // verifies the Stub
  void    print()                                { ShouldNotCallThis(); }                // prints some information about the stub
};
class StubInterface: public CHeapObj<mtCode> {
 public:
  virtual void    initialize(Stub* self, int size,
                             CodeStrings& strings)         = 0; // called after creation (called twice if allocated via (request, commit))
  virtual void    finalize(Stub* self)                     = 0; // called before deallocation
  virtual int     size(Stub* self) const                   = 0; // the total size of the stub in bytes (must be a multiple of CodeEntryAlignment)
  virtual int     code_size_to_size(int code_size) const   = 0; // computes the total stub size in bytes given the code size in bytes
  virtual address code_begin(Stub* self) const             = 0; // points to the first code byte
  virtual address code_end(Stub* self) const               = 0; // points to the first byte after the code
  virtual void    verify(Stub* self)                       = 0; // verifies the stub
  virtual void    print(Stub* self)                        = 0; // prints information about the stub
};
#define DEF_STUB_INTERFACE(stub)                           \
  class stub##Interface: public StubInterface {            \
   private:                                                \
    static stub*    cast(Stub* self)                       { return (stub*)self; }                 \
                                                           \
   public:                                                 \
    virtual void    initialize(Stub* self, int size,       \
                               CodeStrings& strings)       { cast(self)->initialize(size, strings); } \
    virtual void    finalize(Stub* self)                   { cast(self)->finalize(); }             \
                                                           \
    virtual int     size(Stub* self) const                 { return cast(self)->size(); }          \
    virtual int     code_size_to_size(int code_size) const { return stub::code_size_to_size(code_size); } \
                                                           \
    virtual address code_begin(Stub* self) const           { return cast(self)->code_begin(); }    \
    virtual address code_end(Stub* self) const             { return cast(self)->code_end(); }      \
                                                           \
    virtual void    verify(Stub* self)                     { cast(self)->verify(); }               \
    virtual void    print(Stub* self)                      { cast(self)->print(); }                \
  };
class StubQueue: public CHeapObj<mtCode> {
  friend class VMStructs;
 private:
  StubInterface* _stub_interface;                // the interface prototype
  address        _stub_buffer;                   // where all stubs are stored
  int            _buffer_size;                   // the buffer size in bytes
  int            _buffer_limit;                  // the (byte) index of the actual buffer limit (_buffer_limit <= _buffer_size)
  int            _queue_begin;                   // the (byte) index of the first queue entry (word-aligned)
  int            _queue_end;                     // the (byte) index of the first entry after the queue (word-aligned)
  int            _number_of_stubs;               // the number of buffered stubs
  Mutex* const   _mutex;                         // the lock used for a (request, commit) transaction
  void  check_index(int i) const                 { assert(0 <= i && i < _buffer_limit && i % CodeEntryAlignment == 0, "illegal index"); }
  bool  is_contiguous() const                    { return _queue_begin <= _queue_end; }
  int   index_of(Stub* s) const                  { int i = (address)s - _stub_buffer; check_index(i); return i; }
  Stub* stub_at(int i) const                     { check_index(i); return (Stub*)(_stub_buffer + i); }
  Stub* current_stub() const                     { return stub_at(_queue_end); }
  void  stub_initialize(Stub* s, int size,
                        CodeStrings& strings)    { assert(size % CodeEntryAlignment == 0, "size not aligned"); _stub_interface->initialize(s, size, strings); }
  void  stub_finalize(Stub* s)                   { _stub_interface->finalize(s); }
  int   stub_size(Stub* s) const                 { return _stub_interface->size(s); }
  bool  stub_contains(Stub* s, address pc) const { return _stub_interface->code_begin(s) <= pc && pc < _stub_interface->code_end(s); }
  int   stub_code_size_to_size(int code_size) const { return _stub_interface->code_size_to_size(code_size); }
  void  stub_verify(Stub* s)                     { _stub_interface->verify(s); }
  void  stub_print(Stub* s)                      { _stub_interface->print(s); }
  static void register_queue(StubQueue*);
 public:
  StubQueue(StubInterface* stub_interface, int buffer_size, Mutex* lock,
            const char* name);
  ~StubQueue();
  bool  is_empty() const                         { return _queue_begin == _queue_end; }
  int   total_space() const                      { return _buffer_size - 1; }
  int   available_space() const                  { int d = _queue_begin - _queue_end - 1; return d < 0 ? d + _buffer_size : d; }
  int   used_space() const                       { return total_space() - available_space(); }
  int   number_of_stubs() const                  { return _number_of_stubs; }
  bool  contains(address pc) const               { return _stub_buffer <= pc && pc < _stub_buffer + _buffer_limit; }
  Stub* stub_containing(address pc) const;
  address code_start() const                     { return _stub_buffer; }
  address code_end() const                       { return _stub_buffer + _buffer_limit; }
  Stub* request_committed(int code_size);        // request a stub that provides exactly code_size space for code
  Stub* request(int requested_code_size);        // request a stub with a (maximum) code space - locks the queue
  void  commit (int committed_code_size,
                CodeStrings& strings);           // commit the previously requested stub - unlocks the queue
  void  remove_first();                          // remove the first stub in the queue
  void  remove_first(int n);                     // remove the first n stubs in the queue
  void  remove_all();                            // remove all stubs in the queue
  static void queues_do(void f(StubQueue* s));   // call f with each StubQueue
  void  stubs_do(void f(Stub* s));               // call f with all stubs
  Stub* first() const                            { return number_of_stubs() > 0 ? stub_at(_queue_begin) : NULL; }
  Stub* next(Stub* s) const                      { int i = index_of(s) + stub_size(s);
                                                   if (i == _buffer_limit) i = 0;
                                                   return (i == _queue_end) ? NULL : stub_at(i);
                                                 }
  address stub_code_begin(Stub* s) const         { return _stub_interface->code_begin(s); }
  address stub_code_end(Stub* s) const           { return _stub_interface->code_end(s);   }
  void  verify();                                // verifies the stub queue
  void  print();                                 // prints information about the stub queue
};
#endif // SHARE_VM_CODE_STUBS_HPP
C:\hotspot-69087d08d473\src\share\vm/code/vmreg.cpp
#include "precompiled.hpp"
#include "asm/assembler.hpp"
#include "code/vmreg.hpp"
VMReg VMRegImpl::stack0 = (VMReg)(intptr_t)((ConcreteRegisterImpl::number_of_registers + 7) & ~7);
const int VMRegImpl::stack_slot_size = 4;
const int VMRegImpl::slots_per_word = wordSize / stack_slot_size;
const int VMRegImpl::register_count = ConcreteRegisterImpl::number_of_registers;
const char *VMRegImpl::regName[ConcreteRegisterImpl::number_of_registers];
void VMRegImpl::print_on(outputStream* st) const {
  if( is_reg() ) {
    assert( VMRegImpl::regName[value()], "" );
    st->print("%s",VMRegImpl::regName[value()]);
  } else if (is_stack()) {
    int stk = value() - stack0->value();
    st->print("[%d]", stk*4);
  } else {
    st->print("BAD!");
  }
}
C:\hotspot-69087d08d473\src\share\vm/code/vmreg.hpp
#ifndef SHARE_VM_CODE_VMREG_HPP
#define SHARE_VM_CODE_VMREG_HPP
#include "memory/allocation.hpp"
#include "utilities/globalDefinitions.hpp"
#include "asm/register.hpp"
#ifdef COMPILER2
#include "opto/adlcVMDeps.hpp"
#include "utilities/ostream.hpp"
#if defined ADGLOBALS_MD_HPP
# include ADGLOBALS_MD_HPP
#elif defined TARGET_ARCH_MODEL_x86_32
# include "adfiles/adGlobals_x86_32.hpp"
#elif defined TARGET_ARCH_MODEL_x86_64
# include "adfiles/adGlobals_x86_64.hpp"
#elif defined TARGET_ARCH_MODEL_aarch64
# include "adfiles/adGlobals_aarch64.hpp"
#elif defined TARGET_ARCH_MODEL_sparc
# include "adfiles/adGlobals_sparc.hpp"
#elif defined TARGET_ARCH_MODEL_zero
# include "adfiles/adGlobals_zero.hpp"
#elif defined TARGET_ARCH_MODEL_ppc_64
# include "adfiles/adGlobals_ppc_64.hpp"
#endif
#endif
class VMRegImpl;
typedef VMRegImpl* VMReg;
class VMRegImpl {
friend class VMStructs;
friend class OptoReg;
private:
  enum {
    BAD_REG = -1
  };
  static VMReg stack0;
  static const char *regName[];
  static const int register_count;
public:
  static VMReg  as_VMReg(int val, bool bad_ok = false) { assert(val > BAD_REG || bad_ok, "invalid"); return (VMReg) (intptr_t) val; }
  const char*  name() {
    if (is_reg()) {
      return regName[value()];
    } else if (!is_valid()) {
      return "BAD";
    } else {
      return "STACKED REG";
    }
  }
  static VMReg Bad() { return (VMReg) (intptr_t) BAD_REG; }
  bool is_valid() const { return ((intptr_t) this) != BAD_REG; }
  bool is_stack() const { return (intptr_t) this >= (intptr_t) stack0; }
  bool is_reg()   const { return is_valid() && !is_stack(); }
  bool is_concrete();
  static const int stack_slot_size;
  static const int slots_per_word;
  VMReg next() {
    assert((is_reg() && value() < stack0->value() - 1) || is_stack(), "must be");
    return (VMReg)(intptr_t)(value() + 1);
  }
  VMReg next(int i) {
    assert((is_reg() && value() < stack0->value() - i) || is_stack(), "must be");
    return (VMReg)(intptr_t)(value() + i);
  }
  VMReg prev() {
    assert((is_stack() && value() > stack0->value()) || (is_reg() && value() != 0), "must be");
    return (VMReg)(intptr_t)(value() - 1);
  }
  intptr_t value() const         {return (intptr_t) this; }
  void print_on(outputStream* st) const;
  void print() const { print_on(tty); }
  VMReg bias(int offset) {
    assert(is_stack(), "must be");
    VMReg res = stack2reg(reg2stack() + offset);
    assert(res->is_stack(), "must be");
    return res;
  }
  static VMReg stack2reg( int idx ) {
    return (VMReg) (intptr_t) (stack0->value() + idx);
  }
  uintptr_t reg2stack() {
    assert( is_stack(), "Not a stack-based register" );
    return value() - stack0->value();
  }
  static void set_regName();
#ifdef TARGET_ARCH_x86
# include "vmreg_x86.hpp"
#endif
#ifdef TARGET_ARCH_aarch64
# include "vmreg_aarch64.hpp"
#endif
#ifdef TARGET_ARCH_sparc
# include "vmreg_sparc.hpp"
#endif
#ifdef TARGET_ARCH_zero
# include "vmreg_zero.hpp"
#endif
#ifdef TARGET_ARCH_arm
# include "vmreg_arm.hpp"
#endif
#ifdef TARGET_ARCH_ppc
# include "vmreg_ppc.hpp"
#endif
};
class VMRegPair {
private:
  VMReg _second;
  VMReg _first;
public:
  void set_bad (                   ) { _second=VMRegImpl::Bad(); _first=VMRegImpl::Bad(); }
  void set1    (         VMReg v  ) { _second=VMRegImpl::Bad(); _first=v; }
  void set2    (         VMReg v  ) { _second=v->next();  _first=v; }
  void set_pair( VMReg second, VMReg first    ) { _second= second;    _first= first; }
  void set_ptr ( VMReg ptr ) {
#ifdef _LP64
    _second = ptr->next();
#else
    _second = VMRegImpl::Bad();
#endif
    _first = ptr;
  }
  bool is_single_reg() const {
    return (_first->is_valid()) && (_first->value() + 1 == _second->value());
  }
  bool is_adjacent_on_stack(int alignment) const {
    return (_first->is_stack() && (_first->value() + 1 == _second->value()) && ((_first->value() & (alignment-1)) == 0));
  }
  bool is_adjacent_aligned_on_stack(int alignment) const {
    return (_first->is_stack() && (_first->value() + 1 == _second->value()) && ((_first->value() & (alignment-1)) == 0));
  }
  bool is_single_phys_reg() const {
    return (_first->is_reg() && (_first->value() + 1 == _second->value()));
  }
  VMReg second() const { return _second; }
  VMReg first()  const { return _first; }
  VMRegPair(VMReg s, VMReg f) {  _second = s; _first = f; }
  VMRegPair(VMReg f) { _second = VMRegImpl::Bad(); _first = f; }
  VMRegPair() { _second = VMRegImpl::Bad(); _first = VMRegImpl::Bad(); }
};
#endif // SHARE_VM_CODE_VMREG_HPP
C:\hotspot-69087d08d473\src\share\vm/code/vtableStubs.cpp
#include "precompiled.hpp"
#include "code/vtableStubs.hpp"
#include "compiler/disassembler.hpp"
#include "memory/allocation.inline.hpp"
#include "memory/resourceArea.hpp"
#include "oops/instanceKlass.hpp"
#include "oops/klassVtable.hpp"
#include "oops/oop.inline.hpp"
#include "prims/forte.hpp"
#include "prims/jvmtiExport.hpp"
#include "runtime/handles.inline.hpp"
#include "runtime/mutexLocker.hpp"
#include "runtime/sharedRuntime.hpp"
#ifdef COMPILER2
#include "opto/matcher.hpp"
#endif
PRAGMA_FORMAT_MUTE_WARNINGS_FOR_GCC
address VtableStub::_chunk             = NULL;
address VtableStub::_chunk_end         = NULL;
VMReg   VtableStub::_receiver_location = VMRegImpl::Bad();
void* VtableStub::operator new(size_t size, int code_size) throw() {
  assert(size == sizeof(VtableStub), "mismatched size");
  const int real_size = round_to(code_size + sizeof(VtableStub), wordSize);
  const int chunk_factor = 32;
  if (_chunk == NULL || _chunk + real_size > _chunk_end) {
    const int bytes = chunk_factor * real_size + pd_code_alignment();
    VtableBlob* blob = VtableBlob::create("vtable chunks", bytes);
    if (blob == NULL) {
      return NULL;
    }
    _chunk = blob->content_begin();
    _chunk_end = _chunk + bytes;
    Forte::register_stub("vtable stub", _chunk, _chunk_end);
    align_chunk();
  }
  assert(_chunk + real_size <= _chunk_end, "bad allocation");
  void* res = _chunk;
  _chunk += real_size;
  align_chunk();
 return res;
}
void VtableStub::print_on(outputStream* st) const {
  st->print("vtable stub (index = %d, receiver_location = %d, code = [" INTPTR_FORMAT ", " INTPTR_FORMAT "[)",
             index(), receiver_location(), code_begin(), code_end());
}
VtableStub* VtableStubs::_table[VtableStubs::N];
int VtableStubs::_number_of_vtable_stubs = 0;
void VtableStubs::initialize() {
  VtableStub::_receiver_location = SharedRuntime::name_for_receiver();
  {
    MutexLocker ml(VtableStubs_lock);
    assert(_number_of_vtable_stubs == 0, "potential performance bug: VtableStubs initialized more than once");
    assert(is_power_of_2(N), "N must be a power of 2");
    for (int i = 0; i < N; i++) {
      _table[i] = NULL;
    }
  }
}
address VtableStubs::find_stub(bool is_vtable_stub, int vtable_index) {
  assert(vtable_index >= 0, "must be positive");
  VtableStub* s = lookup(is_vtable_stub, vtable_index);
  if (s == NULL) {
    if (is_vtable_stub) {
      s = create_vtable_stub(vtable_index);
    } else {
      s = create_itable_stub(vtable_index);
    }
    if (s == NULL) {
      return NULL;
    }
    enter(is_vtable_stub, vtable_index, s);
    if (PrintAdapterHandlers) {
      tty->print_cr("Decoding VtableStub %s[%d]@%d",
                    is_vtable_stub? "vtbl": "itbl", vtable_index, VtableStub::receiver_location());
      Disassembler::decode(s->code_begin(), s->code_end());
    }
    if (JvmtiExport::should_post_dynamic_code_generated()) {
      JvmtiExport::post_dynamic_code_generated_while_holding_locks(is_vtable_stub? "vtable stub": "itable stub",
                                                                   s->code_begin(), s->code_end());
    }
  }
  return s->entry_point();
}
inline uint VtableStubs::hash(bool is_vtable_stub, int vtable_index){
  int hash = ((vtable_index << 2) ^ VtableStub::receiver_location()->value()) + vtable_index;
  return (is_vtable_stub ? ~hash : hash)  & mask;
}
VtableStub* VtableStubs::lookup(bool is_vtable_stub, int vtable_index) {
  MutexLocker ml(VtableStubs_lock);
  unsigned hash = VtableStubs::hash(is_vtable_stub, vtable_index);
  VtableStub* s = _table[hash];
  while( s && !s->matches(is_vtable_stub, vtable_index)) s = s->next();
  return s;
}
void VtableStubs::enter(bool is_vtable_stub, int vtable_index, VtableStub* s) {
  MutexLocker ml(VtableStubs_lock);
  assert(s->matches(is_vtable_stub, vtable_index), "bad vtable stub");
  unsigned int h = VtableStubs::hash(is_vtable_stub, vtable_index);
  s->set_next(_table[h]);
  _table[h] = s;
  _number_of_vtable_stubs++;
}
VtableStub* VtableStubs::entry_point(address pc) {
  MutexLocker ml(VtableStubs_lock);
  VtableStub* stub = (VtableStub*)(pc - VtableStub::entry_offset());
  uint hash = VtableStubs::hash(stub->is_vtable_stub(), stub->index());
  VtableStub* s;
  for (s = _table[hash]; s != NULL && s != stub; s = s->next()) {}
  if (s == stub) {
    return s;
  }
  return NULL;
}
bool VtableStubs::contains(address pc) {
  return stub_containing(pc) != NULL;
}
VtableStub* VtableStubs::stub_containing(address pc) {
  for (int i = 0; i < N; i++) {
    for (VtableStub* s = _table[i]; s != NULL; s = s->next()) {
      if (s->contains(pc)) return s;
    }
  }
  return NULL;
}
void vtableStubs_init() {
  VtableStubs::initialize();
}
void VtableStubs::vtable_stub_do(void f(VtableStub*)) {
    for (int i = 0; i < N; i++) {
        for (VtableStub* s = _table[i]; s != NULL; s = s->next()) {
            f(s);
        }
    }
}
#ifndef PRODUCT
extern "C" void bad_compiled_vtable_index(JavaThread* thread, oop receiver, int index) {
  ResourceMark rm;
  HandleMark hm;
  Klass* klass = receiver->klass();
  InstanceKlass* ik = InstanceKlass::cast(klass);
  klassVtable* vt = ik->vtable();
  ik->print();
  fatal(err_msg("bad compiled vtable dispatch: receiver " INTPTR_FORMAT ", "
                "index %d (vtable length %d)",
                (address)receiver, index, vt->length()));
}
#endif // Product
C:\hotspot-69087d08d473\src\share\vm/code/vtableStubs.hpp
#ifndef SHARE_VM_CODE_VTABLESTUBS_HPP
#define SHARE_VM_CODE_VTABLESTUBS_HPP
#include "code/vmreg.hpp"
#include "memory/allocation.hpp"
class VtableStub {
 private:
  friend class VtableStubs;
  static address _chunk;             // For allocation
  static address _chunk_end;         // For allocation
  static VMReg   _receiver_location; // Where to find receiver
  VtableStub*    _next;              // Pointer to next entry in hash table
  const short    _index;             // vtable index
  short          _ame_offset;        // Where an AbstractMethodError might occur
  short          _npe_offset;        // Where a NullPointerException might occur
  bool           _is_vtable_stub;    // True if vtable stub, false, is itable stub
  void* operator new(size_t size, int code_size) throw();
  VtableStub(bool is_vtable_stub, int index)
        : _next(NULL), _is_vtable_stub(is_vtable_stub),
          _index(index), _ame_offset(-1), _npe_offset(-1) {}
  VtableStub* next() const                       { return _next; }
  int index() const                              { return _index; }
  static VMReg receiver_location()               { return _receiver_location; }
  void set_next(VtableStub* n)                   { _next = n; }
 public:
  address code_begin() const                     { return (address)(this + 1); }
  address code_end() const                       { return code_begin() + pd_code_size_limit(_is_vtable_stub); }
  address entry_point() const                    { return code_begin(); }
  static int entry_offset()                      { return sizeof(class VtableStub); }
  bool matches(bool is_vtable_stub, int index) const {
    return _index == index && _is_vtable_stub == is_vtable_stub;
  }
  bool contains(address pc) const                { return code_begin() <= pc && pc < code_end(); }
 private:
  void set_exception_points(address npe_addr, address ame_addr) {
    _npe_offset = npe_addr - code_begin();
    _ame_offset = ame_addr - code_begin();
    assert(is_abstract_method_error(ame_addr),   "offset must be correct");
    assert(is_null_pointer_exception(npe_addr),  "offset must be correct");
    assert(!is_abstract_method_error(npe_addr),  "offset must be correct");
    assert(!is_null_pointer_exception(ame_addr), "offset must be correct");
  }
  static int  pd_code_size_limit(bool is_vtable_stub);
  static int  pd_code_alignment();
  static void align_chunk() {
    uintptr_t off = (uintptr_t)( _chunk + sizeof(VtableStub) ) % pd_code_alignment();
    if (off != 0)  _chunk += pd_code_alignment() - off;
  }
 public:
  bool is_itable_stub()                          { return !_is_vtable_stub; }
  bool is_vtable_stub()                          { return  _is_vtable_stub; }
  bool is_abstract_method_error(address epc)     { return epc == code_begin()+_ame_offset; }
  bool is_null_pointer_exception(address epc)    { return epc == code_begin()+_npe_offset; }
  void print_on(outputStream* st) const;
  void print() const                             { print_on(tty); }
};
class VtableStubs : AllStatic {
 public:                                         // N must be public (some compilers need this for _table)
  enum {
    N    = 256,                                  // size of stub table; must be power of two
    mask = N - 1
  };
 private:
  static VtableStub* _table[N];                  // table of existing stubs
  static int         _number_of_vtable_stubs;    // number of stubs created so far (for statistics)
  static VtableStub* create_vtable_stub(int vtable_index);
  static VtableStub* create_itable_stub(int vtable_index);
  static VtableStub* lookup            (bool is_vtable_stub, int vtable_index);
  static void        enter             (bool is_vtable_stub, int vtable_index, VtableStub* s);
  static inline uint hash              (bool is_vtable_stub, int vtable_index);
  static address     find_stub         (bool is_vtable_stub, int vtable_index);
 public:
  static address     find_vtable_stub(int vtable_index) { return find_stub(true,  vtable_index); }
  static address     find_itable_stub(int itable_index) { return find_stub(false, itable_index); }
  static VtableStub* entry_point(address pc);                        // vtable stub entry point for a pc
  static bool        contains(address pc);                           // is pc within any stub?
  static VtableStub* stub_containing(address pc);                    // stub containing pc or NULL
  static int         number_of_vtable_stubs() { return _number_of_vtable_stubs; }
  static void        initialize();
  static void        vtable_stub_do(void f(VtableStub*));            // iterates over all vtable stubs
};
#endif // SHARE_VM_CODE_VTABLESTUBS_HPP
C:\hotspot-69087d08d473\src\share\vm/compiler/abstractCompiler.cpp
#include "precompiled.hpp"
#include "compiler/abstractCompiler.hpp"
#include "compiler/compileBroker.hpp"
#include "runtime/mutexLocker.hpp"
bool AbstractCompiler::should_perform_init() {
  if (_compiler_state != initialized) {
    MutexLocker only_one(CompileThread_lock);
    if (_compiler_state == uninitialized) {
      _compiler_state = initializing;
      return true;
    } else {
      while (_compiler_state == initializing) {
        CompileThread_lock->wait();
      }
    }
  }
  return false;
}
bool AbstractCompiler::should_perform_shutdown() {
  MutexLocker only_one(CompileThread_lock);
  _num_compiler_threads--;
  assert (CompileBroker::is_compilation_disabled_forever(), "Must be set, otherwise thread waits forever");
  if (_num_compiler_threads == 0) {
    return true;
  }
  return false;
}
void AbstractCompiler::set_state(int state) {
  MutexLocker only_one(CompileThread_lock);
  _compiler_state =  state;
  CompileThread_lock->notify_all();
}
C:\hotspot-69087d08d473\src\share\vm/compiler/abstractCompiler.hpp
#ifndef SHARE_VM_COMPILER_ABSTRACTCOMPILER_HPP
#define SHARE_VM_COMPILER_ABSTRACTCOMPILER_HPP
#include "ci/compilerInterface.hpp"
class AbstractCompiler : public CHeapObj<mtCompiler> {
 private:
  volatile int _num_compiler_threads;
 protected:
  volatile int _compiler_state;
  enum { uninitialized, initializing, initialized, failed, shut_down };
  bool should_perform_init();
 public:
  AbstractCompiler() : _compiler_state(uninitialized), _num_compiler_threads(0) {}
  bool should_perform_shutdown();
  virtual const char* name() = 0;
  virtual bool supports_native()                 { return true; }
  virtual bool supports_osr   ()                 { return true; }
  virtual bool can_compile_method(methodHandle method)  { return true; }
#if defined(TIERED) || ( !defined(COMPILER1) && !defined(COMPILER2) && !defined(SHARK))
  virtual bool is_c1   ()                        { return false; }
  virtual bool is_c2   ()                        { return false; }
  virtual bool is_shark()                        { return false; }
#else
#ifdef COMPILER1
  bool is_c1   ()                                { return true; }
  bool is_c2   ()                                { return false; }
  bool is_shark()                                { return false; }
#endif // COMPILER1
#ifdef COMPILER2
  bool is_c1   ()                                { return false; }
  bool is_c2   ()                                { return true; }
  bool is_shark()                                { return false; }
#endif // COMPILER2
#ifdef SHARK
  bool is_c1   ()                                { return false; }
  bool is_c2   ()                                { return false; }
  bool is_shark()                                { return true; }
#endif // SHARK
#endif // TIERED
  virtual void initialize () = 0;
  void set_num_compiler_threads(int num) { _num_compiler_threads = num;  }
  int num_compiler_threads()             { return _num_compiler_threads; }
  bool is_initialized()           { return _compiler_state == initialized; }
  bool is_failed     ()           { return _compiler_state == failed;}
  void set_state     (int state);
  void set_shut_down ()           { set_state(shut_down); }
  virtual void compile_method(ciEnv* env, ciMethod* target, int entry_bci) {
    ShouldNotReachHere();
  }
  virtual void print_timers() {
    ShouldNotReachHere();
  }
};
#endif // SHARE_VM_COMPILER_ABSTRACTCOMPILER_HPP
C:\hotspot-69087d08d473\src\share\vm/compiler/compileBroker.cpp
#include "precompiled.hpp"
#include "classfile/systemDictionary.hpp"
#include "classfile/vmSymbols.hpp"
#include "code/codeCache.hpp"
#include "compiler/compileBroker.hpp"
#include "compiler/compileLog.hpp"
#include "compiler/compilerOracle.hpp"
#include "interpreter/linkResolver.hpp"
#include "jfr/jfrEvents.hpp"
#include "memory/allocation.inline.hpp"
#include "oops/methodData.hpp"
#include "oops/method.hpp"
#include "oops/oop.inline.hpp"
#include "prims/nativeLookup.hpp"
#include "runtime/arguments.hpp"
#include "runtime/compilationPolicy.hpp"
#include "runtime/init.hpp"
#include "runtime/interfaceSupport.hpp"
#include "runtime/javaCalls.hpp"
#include "runtime/os.hpp"
#include "runtime/sharedRuntime.hpp"
#include "runtime/sweeper.hpp"
#include "utilities/dtrace.hpp"
#include "utilities/events.hpp"
#ifdef COMPILER1
#include "c1/c1_Compiler.hpp"
#endif
#ifdef COMPILER2
#include "opto/c2compiler.hpp"
#endif
#ifdef SHARK
#include "shark/sharkCompiler.hpp"
#endif
#ifdef DTRACE_ENABLED
#ifndef USDT2
HS_DTRACE_PROBE_DECL8(hotspot, method__compile__begin,
  char*, intptr_t, char*, intptr_t, char*, intptr_t, char*, intptr_t);
HS_DTRACE_PROBE_DECL9(hotspot, method__compile__end,
  char*, intptr_t, char*, intptr_t, char*, intptr_t, char*, intptr_t, bool);
#define DTRACE_METHOD_COMPILE_BEGIN_PROBE(method, comp_name)             \
  {                                                                      \
    Symbol* klass_name = (method)->klass_name();                         \
    Symbol* name = (method)->name();                                     \
    Symbol* signature = (method)->signature();                           \
    HS_DTRACE_PROBE8(hotspot, method__compile__begin,                    \
      comp_name, strlen(comp_name),                                      \
      klass_name->bytes(), klass_name->utf8_length(),                    \
      name->bytes(), name->utf8_length(),                                \
      signature->bytes(), signature->utf8_length());                     \
  }
#define DTRACE_METHOD_COMPILE_END_PROBE(method, comp_name, success)      \
  {                                                                      \
    Symbol* klass_name = (method)->klass_name();                         \
    Symbol* name = (method)->name();                                     \
    Symbol* signature = (method)->signature();                           \
    HS_DTRACE_PROBE9(hotspot, method__compile__end,                      \
      comp_name, strlen(comp_name),                                      \
      klass_name->bytes(), klass_name->utf8_length(),                    \
      name->bytes(), name->utf8_length(),                                \
      signature->bytes(), signature->utf8_length(), (success));          \
  }
#else /* USDT2 */
#define DTRACE_METHOD_COMPILE_BEGIN_PROBE(method, comp_name)             \
  {                                                                      \
    Symbol* klass_name = (method)->klass_name();                         \
    Symbol* name = (method)->name();                                     \
    Symbol* signature = (method)->signature();                           \
    HOTSPOT_METHOD_COMPILE_BEGIN(                                        \
      comp_name, strlen(comp_name),                                      \
      (char *) klass_name->bytes(), klass_name->utf8_length(),           \
      (char *) name->bytes(), name->utf8_length(),                       \
      (char *) signature->bytes(), signature->utf8_length());            \
  }
#define DTRACE_METHOD_COMPILE_END_PROBE(method, comp_name, success)      \
  {                                                                      \
    Symbol* klass_name = (method)->klass_name();                         \
    Symbol* name = (method)->name();                                     \
    Symbol* signature = (method)->signature();                           \
    HOTSPOT_METHOD_COMPILE_END(                                          \
      comp_name, strlen(comp_name),                                      \
      (char *) klass_name->bytes(), klass_name->utf8_length(),           \
      (char *) name->bytes(), name->utf8_length(),                       \
      (char *) signature->bytes(), signature->utf8_length(), (success)); \
  }
#endif /* USDT2 */
#else //  ndef DTRACE_ENABLED
#define DTRACE_METHOD_COMPILE_BEGIN_PROBE(method, comp_name)
#define DTRACE_METHOD_COMPILE_END_PROBE(method, comp_name, success)
#endif // ndef DTRACE_ENABLED
bool CompileBroker::_initialized = false;
volatile bool CompileBroker::_should_block = false;
volatile jint CompileBroker::_print_compilation_warning = 0;
volatile jint CompileBroker::_should_compile_new_jobs = run_compilation;
AbstractCompiler* CompileBroker::_compilers[2];
volatile jint CompileBroker::_compilation_id     = 0;
volatile jint CompileBroker::_osr_compilation_id = 0;
int  CompileBroker::_last_compile_type     = no_compile;
int  CompileBroker::_last_compile_level    = CompLevel_none;
char CompileBroker::_last_method_compiled[CompileBroker::name_buffer_length];
PerfCounter* CompileBroker::_perf_total_compilation = NULL;
PerfCounter* CompileBroker::_perf_osr_compilation = NULL;
PerfCounter* CompileBroker::_perf_standard_compilation = NULL;
PerfCounter* CompileBroker::_perf_total_bailout_count = NULL;
PerfCounter* CompileBroker::_perf_total_invalidated_count = NULL;
PerfCounter* CompileBroker::_perf_total_compile_count = NULL;
PerfCounter* CompileBroker::_perf_total_osr_compile_count = NULL;
PerfCounter* CompileBroker::_perf_total_standard_compile_count = NULL;
PerfCounter* CompileBroker::_perf_sum_osr_bytes_compiled = NULL;
PerfCounter* CompileBroker::_perf_sum_standard_bytes_compiled = NULL;
PerfCounter* CompileBroker::_perf_sum_nmethod_size = NULL;
PerfCounter* CompileBroker::_perf_sum_nmethod_code_size = NULL;
PerfStringVariable* CompileBroker::_perf_last_method = NULL;
PerfStringVariable* CompileBroker::_perf_last_failed_method = NULL;
PerfStringVariable* CompileBroker::_perf_last_invalidated_method = NULL;
PerfVariable*       CompileBroker::_perf_last_compile_type = NULL;
PerfVariable*       CompileBroker::_perf_last_compile_size = NULL;
PerfVariable*       CompileBroker::_perf_last_failed_type = NULL;
PerfVariable*       CompileBroker::_perf_last_invalidated_type = NULL;
elapsedTimer CompileBroker::_t_total_compilation;
elapsedTimer CompileBroker::_t_osr_compilation;
elapsedTimer CompileBroker::_t_standard_compilation;
int CompileBroker::_total_bailout_count          = 0;
int CompileBroker::_total_invalidated_count      = 0;
int CompileBroker::_total_compile_count          = 0;
int CompileBroker::_total_osr_compile_count      = 0;
int CompileBroker::_total_standard_compile_count = 0;
int CompileBroker::_sum_osr_bytes_compiled       = 0;
int CompileBroker::_sum_standard_bytes_compiled  = 0;
int CompileBroker::_sum_nmethod_size             = 0;
int CompileBroker::_sum_nmethod_code_size        = 0;
long CompileBroker::_peak_compilation_time       = 0;
CompileQueue* CompileBroker::_c2_compile_queue   = NULL;
CompileQueue* CompileBroker::_c1_compile_queue   = NULL;
GrowableArray<CompilerThread*>* CompileBroker::_compiler_threads = NULL;
class CompilationLog : public StringEventLog {
 public:
  CompilationLog() : StringEventLog("Compilation events") {
  }
  void log_compile(JavaThread* thread, CompileTask* task) {
    StringLogMessage lm;
    stringStream sstr = lm.stream();
    task->print_compilation(&sstr, NULL, true);
    log(thread, "%s", (const char*)lm);
  }
  void log_nmethod(JavaThread* thread, nmethod* nm) {
    log(thread, "nmethod %d%s " INTPTR_FORMAT " code [" INTPTR_FORMAT ", " INTPTR_FORMAT "]",
        nm->compile_id(), nm->is_osr_method() ? "%" : "",
        p2i(nm), p2i(nm->code_begin()), p2i(nm->code_end()));
  }
  void log_failure(JavaThread* thread, CompileTask* task, const char* reason, const char* retry_message) {
    StringLogMessage lm;
    lm.print("%4d   COMPILE SKIPPED: %s", task->compile_id(), reason);
    if (retry_message != NULL) {
      lm.append(" (%s)", retry_message);
    }
    lm.print("\n");
    log(thread, "%s", (const char*)lm);
  }
};
static CompilationLog* _compilation_log = NULL;
void compileBroker_init() {
  if (LogEvents) {
    _compilation_log = new CompilationLog();
  }
}
CompileTaskWrapper::CompileTaskWrapper(CompileTask* task) {
  CompilerThread* thread = CompilerThread::current();
  thread->set_task(task);
  CompileLog*     log  = thread->log();
  if (log != NULL)  task->log_task_start(log);
}
CompileTaskWrapper::~CompileTaskWrapper() {
  CompilerThread* thread = CompilerThread::current();
  CompileTask* task = thread->task();
  CompileLog*  log  = thread->log();
  if (log != NULL)  task->log_task_done(log);
  thread->set_task(NULL);
  task->set_code_handle(NULL);
  thread->set_env(NULL);
  if (task->is_blocking()) {
    MutexLocker notifier(task->lock(), thread);
    task->mark_complete();
    task->lock()->notify_all();
  } else {
    task->mark_complete();
    CompileTask::free(task);
  }
}
CompileTask*  CompileTask::_task_free_list = NULL;
#ifdef ASSERT
int CompileTask::_num_allocated_tasks = 0;
#endif
CompileTask* CompileTask::allocate() {
  MutexLocker locker(CompileTaskAlloc_lock);
  CompileTask* task = NULL;
  if (_task_free_list != NULL) {
    task = _task_free_list;
    _task_free_list = task->next();
    task->set_next(NULL);
  } else {
    task = new CompileTask();
    DEBUG_ONLY(_num_allocated_tasks++;)
    assert (_num_allocated_tasks < 10000, "Leaking compilation tasks?");
    task->set_next(NULL);
    task->set_is_free(true);
  }
  assert(task->is_free(), "Task must be free.");
  task->set_is_free(false);
  return task;
}
void CompileTask::free(CompileTask* task) {
  MutexLocker locker(CompileTaskAlloc_lock);
  if (!task->is_free()) {
    task->set_code(NULL);
    assert(!task->lock()->is_locked(), "Should not be locked when freed");
    JNIHandles::destroy_global(task->_method_holder);
    JNIHandles::destroy_global(task->_hot_method_holder);
    task->set_is_free(true);
    task->set_next(_task_free_list);
    _task_free_list = task;
  }
}
void CompileTask::initialize(int compile_id,
                             methodHandle method,
                             int osr_bci,
                             int comp_level,
                             methodHandle hot_method,
                             int hot_count,
                             const char* comment,
                             bool is_blocking) {
  assert(!_lock->is_locked(), "bad locking");
  _compile_id = compile_id;
  _method = method();
  _method_holder = JNIHandles::make_global(method->method_holder()->klass_holder());
  _osr_bci = osr_bci;
  _is_blocking = is_blocking;
  _comp_level = comp_level;
  _num_inlined_bytecodes = 0;
  _is_complete = false;
  _is_success = false;
  _code_handle = NULL;
  _hot_method = NULL;
  _hot_method_holder = NULL;
  _hot_count = hot_count;
  _time_queued = 0;  // tidy
  _comment = comment;
  _failure_reason = NULL;
  if (LogCompilation) {
    _time_queued = os::elapsed_counter();
    if (hot_method.not_null()) {
      if (hot_method == method) {
        _hot_method = _method;
      } else {
        _hot_method = hot_method();
        _hot_method_holder = JNIHandles::make_global(hot_method->method_holder()->klass_holder());
      }
    }
  }
  _next = NULL;
}
nmethod* CompileTask::code() const {
  if (_code_handle == NULL)  return NULL;
  return _code_handle->code();
}
void CompileTask::set_code(nmethod* nm) {
  if (_code_handle == NULL && nm == NULL)  return;
  guarantee(_code_handle != NULL, "");
  _code_handle->set_code(nm);
  if (nm == NULL)  _code_handle = NULL;  // drop the handle also
}
void CompileTask::mark_on_stack() {
  _method->set_on_stack(true);
  if (_hot_method != NULL) {
    _hot_method->set_on_stack(true);
  }
}
void CompileTask::print() {
  tty->print("<CompileTask compile_id=%d ", _compile_id);
  tty->print("method=");
  _method->print_name(tty);
  tty->print_cr(" osr_bci=%d is_blocking=%s is_complete=%s is_success=%s>",
             _osr_bci, bool_to_str(_is_blocking),
             bool_to_str(_is_complete), bool_to_str(_is_success));
}
void CompileTask::print_line_on_error(outputStream* st, char* buf, int buflen) {
  st->print("%s:", CompileBroker::compiler_name(comp_level()));
  print_compilation(st);
}
void CompileTask::print_line() {
  ttyLocker ttyl;  // keep the following output all in one block
  if (CIPrintCompilerName) tty->print("%s:", CompileBroker::compiler_name(comp_level()));
  print_compilation();
}
void CompileTask::print_compilation_impl(outputStream* st, Method* method, int compile_id, int comp_level,
                                         bool is_osr_method, int osr_bci, bool is_blocking,
                                         const char* msg, bool short_form) {
  if (!short_form) {
    st->print("%7d ", (int) st->time_stamp().milliseconds());  // print timestamp
  }
  st->print("%4d ", compile_id);    // print compilation number
  bool is_synchronized = false;
  bool has_exception_handler = false;
  bool is_native = false;
  if (method != NULL) {
    is_synchronized       = method->is_synchronized();
    has_exception_handler = method->has_exception_handler();
    is_native             = method->is_native();
  }
  const char compile_type   = is_osr_method                   ? '%' : ' ';
  const char sync_char      = is_synchronized                 ? 's' : ' ';
  const char exception_char = has_exception_handler           ? '!' : ' ';
  const char blocking_char  = is_blocking                     ? 'b' : ' ';
  const char native_char    = is_native                       ? 'n' : ' ';
  st->print("%c%c%c%c%c ", compile_type, sync_char, exception_char, blocking_char, native_char);
  if (TieredCompilation) {
    if (comp_level != -1)  st->print("%d ", comp_level);
    else                   st->print("- ");
  }
  st->print("     ");  // more indent
  if (method == NULL) {
    st->print("(method)");
  } else {
    method->print_short_name(st);
    if (is_osr_method) {
      st->print(" @ %d", osr_bci);
    }
    if (method->is_native())
      st->print(" (native)");
    else
      st->print(" (%d bytes)", method->code_size());
  }
  if (msg != NULL) {
    st->print("   %s", msg);
  }
  if (!short_form) {
    st->cr();
  }
}
void CompileTask::print_inlining(outputStream* st, ciMethod* method, int inline_level, int bci, const char* msg) {
  st->print("        ");     // print timestamp
  st->print("     ");        // print compilation number
  if (method->is_loaded()) {
    const char sync_char      = method->is_synchronized()        ? 's' : ' ';
    const char exception_char = method->has_exception_handlers() ? '!' : ' ';
    const char monitors_char  = method->has_monitor_bytecodes()  ? 'm' : ' ';
    st->print(" %c%c%c  ", sync_char, exception_char, monitors_char);
  } else {
    st->print("      ");     // print method attributes
  }
  if (TieredCompilation) {
    st->print("  ");
  }
  st->print("     ");        // more indent
  st->print("    ");         // initial inlining indent
  for (int i = 0; i < inline_level; i++)  st->print("  ");
  st->print("@ %d  ", bci);  // print bci
  method->print_short_name(st);
  if (method->is_loaded())
    st->print(" (%d bytes)", method->code_size());
  else
    st->print(" (not loaded)");
  if (msg != NULL) {
    st->print("   %s", msg);
  }
  st->cr();
}
void CompileTask::print_inline_indent(int inline_level, outputStream* st) {
  st->print("        ");     // print timestamp
  st->print("     ");        // print compilation number
  st->print("      ");       // print method attributes
  if (TieredCompilation) {
    st->print("  ");
  }
  st->print("     ");        // more indent
  st->print("    ");         // initial inlining indent
  for (int i = 0; i < inline_level; i++)  st->print("  ");
}
void CompileTask::print_compilation(outputStream* st, const char* msg, bool short_form) {
  bool is_osr_method = osr_bci() != InvocationEntryBci;
  print_compilation_impl(st, method(), compile_id(), comp_level(), is_osr_method, osr_bci(), is_blocking(), msg, short_form);
}
void CompileTask::log_task(xmlStream* log) {
  Thread* thread = Thread::current();
  methodHandle method(thread, this->method());
  ResourceMark rm(thread);
  log->print(" compile_id='%d'", _compile_id);
  if (_osr_bci != CompileBroker::standard_entry_bci) {
    log->print(" compile_kind='osr'");  // same as nmethod::compile_kind
  } // else compile_kind='c2c'
  if (!method.is_null())  log->method(method);
  if (_osr_bci != CompileBroker::standard_entry_bci) {
    log->print(" osr_bci='%d'", _osr_bci);
  }
  if (_comp_level != CompLevel_highest_tier) {
    log->print(" level='%d'", _comp_level);
  }
  if (_is_blocking) {
    log->print(" blocking='1'");
  }
  log->stamp();
}
void CompileTask::log_task_queued() {
  Thread* thread = Thread::current();
  ttyLocker ttyl;
  ResourceMark rm(thread);
  xtty->begin_elem("task_queued");
  log_task(xtty);
  if (_comment != NULL) {
    xtty->print(" comment='%s'", _comment);
  }
  if (_hot_method != NULL) {
    methodHandle hot(thread, _hot_method);
    methodHandle method(thread, _method);
    if (hot() != method()) {
      xtty->method(hot);
    }
  }
  if (_hot_count != 0) {
    xtty->print(" hot_count='%d'", _hot_count);
  }
  xtty->end_elem();
}
void CompileTask::log_task_start(CompileLog* log)   {
  log->begin_head("task");
  log_task(log);
  log->end_head();
}
void CompileTask::log_task_done(CompileLog* log) {
  Thread* thread = Thread::current();
  methodHandle method(thread, this->method());
  ResourceMark rm(thread);
  if (!_is_success) {
    const char* reason = _failure_reason != NULL ? _failure_reason : "unknown";
    log->elem("failure reason='%s'", reason);
  }
  nmethod* nm = code();
  log->begin_elem("task_done success='%d' nmsize='%d' count='%d'",
                  _is_success, nm == NULL ? 0 : nm->content_size(),
                  method->invocation_count());
  int bec = method->backedge_count();
  if (bec != 0)  log->print(" backedge_count='%d'", bec);
  if (_num_inlined_bytecodes != 0) {
    log->print(" inlined_bytes='%d'", _num_inlined_bytecodes);
  }
  log->stamp();
  log->end_elem();
  log->tail("task");
  log->clear_identities();   // next task will have different CI
  if (log->unflushed_count() > 2000) {
    log->flush();
  }
  log->mark_file_end();
}
void CompileQueue::add(CompileTask* task) {
  assert(lock()->owned_by_self(), "must own lock");
  assert(!CompileBroker::is_compilation_disabled_forever(), "Do not add task if compilation is turned off forever");
  task->set_next(NULL);
  task->set_prev(NULL);
  if (_last == NULL) {
    assert(_first == NULL, "queue is empty");
    _first = task;
    _last = task;
  } else {
    assert(_last->next() == NULL, "not last");
    _last->set_next(task);
    task->set_prev(_last);
    _last = task;
  }
  ++_size;
  task->method()->set_queued_for_compilation();
  NOT_PRODUCT(print();)
  if (LogCompilation && xtty != NULL) {
    task->log_task_queued();
  }
  lock()->notify_all();
}
void CompileQueue::free_all() {
  MutexLocker mu(lock());
  CompileTask* next = _first;
  while (next != NULL) {
    CompileTask* current = next;
    next = current->next();
    {
      MutexLocker ct_lock(current->lock());
      current->lock()->notify();
    }
    CompileTask::free(current);
  }
  _first = NULL;
  lock()->notify_all();
}
CompileTask* CompileQueue::get() {
  NMethodSweeper::possibly_sweep();
  MutexLocker locker(lock());
  while (_first == NULL) {
    if (CompileBroker::is_compilation_disabled_forever()) {
      return NULL;
    }
    if (UseCodeCacheFlushing && !CompileBroker::should_compile_new_jobs()) {
      long wait_time = NmethodSweepCheckInterval * 1000;
      if (FLAG_IS_DEFAULT(NmethodSweepCheckInterval)) {
        wait_time = 100 * CICompilerCount;
      }
      bool timeout = lock()->wait(!Mutex::_no_safepoint_check_flag, wait_time);
      if (timeout) {
        MutexUnlocker ul(lock());
        NMethodSweeper::possibly_sweep();
      }
    } else {
      lock()->wait(!Mutex::_no_safepoint_check_flag, 5*1000);
    }
  }
  if (CompileBroker::is_compilation_disabled_forever()) {
    return NULL;
  }
  CompileTask* task;
  {
    No_Safepoint_Verifier nsv;
    task = CompilationPolicy::policy()->select_task(this);
  }
  if (task != NULL) {
    remove(task);
  }
  purge_stale_tasks(); // may temporarily release MCQ lock
  return task;
}
void CompileQueue::purge_stale_tasks() {
  assert(lock()->owned_by_self(), "must own lock");
  if (_first_stale != NULL) {
    CompileTask* head = _first_stale;
    _first_stale = NULL;
    {
      MutexUnlocker ul(lock());
      for (CompileTask* task = head; task != NULL; ) {
        CompileTask* next_task = task->next();
        CompileTaskWrapper ctw(task); // Frees the task
        task->set_failure_reason("stale task");
        task = next_task;
      }
    }
  }
}
void CompileQueue::remove(CompileTask* task) {
   assert(lock()->owned_by_self(), "must own lock");
  if (task->prev() != NULL) {
    task->prev()->set_next(task->next());
  } else {
    assert(task == _first, "Sanity");
    _first = task->next();
  }
  if (task->next() != NULL) {
    task->next()->set_prev(task->prev());
  } else {
    assert(task == _last, "Sanity");
    _last = task->prev();
  }
  --_size;
}
void CompileQueue::remove_and_mark_stale(CompileTask* task) {
  assert(lock()->owned_by_self(), "must own lock");
  remove(task);
  task->set_next(_first_stale);
  task->set_prev(NULL);
  _first_stale = task;
}
void CompileQueue::mark_on_stack() {
  CompileTask* task = _first;
  while (task != NULL) {
    task->mark_on_stack();
    task = task->next();
  }
}
#ifndef PRODUCT
void CompileQueue::print() {
  if (CIPrintCompileQueue) {
    ttyLocker ttyl;
    tty->print_cr("Contents of %s", name());
    tty->print_cr("----------------------");
    CompileTask* task = _first;
    while (task != NULL) {
      task->print_line();
      task = task->next();
    }
    tty->print_cr("----------------------");
  }
}
#endif // PRODUCT
CompilerCounters::CompilerCounters(const char* thread_name, int instance, TRAPS) {
  _current_method[0] = '\0';
  _compile_type = CompileBroker::no_compile;
  if (UsePerfData) {
    ResourceMark rm;
    const char* thread_i = (instance == -1) ? thread_name :
                      PerfDataManager::name_space(thread_name, instance);
    char* name = PerfDataManager::counter_name(thread_i, "method");
    _perf_current_method =
               PerfDataManager::create_string_variable(SUN_CI, name,
                                                       cmname_buffer_length,
                                                       _current_method, CHECK);
    name = PerfDataManager::counter_name(thread_i, "type");
    _perf_compile_type = PerfDataManager::create_variable(SUN_CI, name,
                                                          PerfData::U_None,
                                                         (jlong)_compile_type,
                                                          CHECK);
    name = PerfDataManager::counter_name(thread_i, "time");
    _perf_time = PerfDataManager::create_counter(SUN_CI, name,
                                                 PerfData::U_Ticks, CHECK);
    name = PerfDataManager::counter_name(thread_i, "compiles");
    _perf_compiles = PerfDataManager::create_counter(SUN_CI, name,
                                                     PerfData::U_Events, CHECK);
  }
}
void CompileBroker::compilation_init() {
  _last_method_compiled[0] = '\0';
  if (!UseCompiler) {
    return;
  }
#ifndef SHARK
  int c1_count = CompilationPolicy::policy()->compiler_count(CompLevel_simple);
  int c2_count = CompilationPolicy::policy()->compiler_count(CompLevel_full_optimization);
#ifdef COMPILER1
  if (c1_count > 0) {
    _compilers[0] = new Compiler();
  }
#endif // COMPILER1
#ifdef COMPILER2
  if (c2_count > 0) {
    _compilers[1] = new C2Compiler();
  }
#endif // COMPILER2
#else // SHARK
  int c1_count = 0;
  int c2_count = 1;
  _compilers[1] = new SharkCompiler();
#endif // SHARK
  init_compiler_threads(c1_count, c2_count);
  {
    EXCEPTION_MARK;
    _perf_total_compilation =
                 PerfDataManager::create_counter(JAVA_CI, "totalTime",
                                                 PerfData::U_Ticks, CHECK);
  }
  if (UsePerfData) {
    EXCEPTION_MARK;
    _perf_osr_compilation =
                 PerfDataManager::create_counter(SUN_CI, "osrTime",
                                                 PerfData::U_Ticks, CHECK);
    _perf_standard_compilation =
                 PerfDataManager::create_counter(SUN_CI, "standardTime",
                                                 PerfData::U_Ticks, CHECK);
    _perf_total_bailout_count =
                 PerfDataManager::create_counter(SUN_CI, "totalBailouts",
                                                 PerfData::U_Events, CHECK);
    _perf_total_invalidated_count =
                 PerfDataManager::create_counter(SUN_CI, "totalInvalidates",
                                                 PerfData::U_Events, CHECK);
    _perf_total_compile_count =
                 PerfDataManager::create_counter(SUN_CI, "totalCompiles",
                                                 PerfData::U_Events, CHECK);
    _perf_total_osr_compile_count =
                 PerfDataManager::create_counter(SUN_CI, "osrCompiles",
                                                 PerfData::U_Events, CHECK);
    _perf_total_standard_compile_count =
                 PerfDataManager::create_counter(SUN_CI, "standardCompiles",
                                                 PerfData::U_Events, CHECK);
    _perf_sum_osr_bytes_compiled =
                 PerfDataManager::create_counter(SUN_CI, "osrBytes",
                                                 PerfData::U_Bytes, CHECK);
    _perf_sum_standard_bytes_compiled =
                 PerfDataManager::create_counter(SUN_CI, "standardBytes",
                                                 PerfData::U_Bytes, CHECK);
    _perf_sum_nmethod_size =
                 PerfDataManager::create_counter(SUN_CI, "nmethodSize",
                                                 PerfData::U_Bytes, CHECK);
    _perf_sum_nmethod_code_size =
                 PerfDataManager::create_counter(SUN_CI, "nmethodCodeSize",
                                                 PerfData::U_Bytes, CHECK);
    _perf_last_method =
                 PerfDataManager::create_string_variable(SUN_CI, "lastMethod",
                                       CompilerCounters::cmname_buffer_length,
                                       "", CHECK);
    _perf_last_failed_method =
            PerfDataManager::create_string_variable(SUN_CI, "lastFailedMethod",
                                       CompilerCounters::cmname_buffer_length,
                                       "", CHECK);
    _perf_last_invalidated_method =
        PerfDataManager::create_string_variable(SUN_CI, "lastInvalidatedMethod",
                                     CompilerCounters::cmname_buffer_length,
                                     "", CHECK);
    _perf_last_compile_type =
             PerfDataManager::create_variable(SUN_CI, "lastType",
                                              PerfData::U_None,
                                              (jlong)CompileBroker::no_compile,
                                              CHECK);
    _perf_last_compile_size =
             PerfDataManager::create_variable(SUN_CI, "lastSize",
                                              PerfData::U_Bytes,
                                              (jlong)CompileBroker::no_compile,
                                              CHECK);
    _perf_last_failed_type =
             PerfDataManager::create_variable(SUN_CI, "lastFailedType",
                                              PerfData::U_None,
                                              (jlong)CompileBroker::no_compile,
                                              CHECK);
    _perf_last_invalidated_type =
         PerfDataManager::create_variable(SUN_CI, "lastInvalidatedType",
                                          PerfData::U_None,
                                          (jlong)CompileBroker::no_compile,
                                          CHECK);
  }
  _initialized = true;
}
CompilerThread* CompileBroker::make_compiler_thread(const char* name, CompileQueue* queue, CompilerCounters* counters,
                                                    AbstractCompiler* comp, TRAPS) {
  CompilerThread* compiler_thread = NULL;
  Klass* k =
    SystemDictionary::resolve_or_fail(vmSymbols::java_lang_Thread(),
                                      true, CHECK_0);
  instanceKlassHandle klass (THREAD, k);
  instanceHandle thread_oop = klass->allocate_instance_handle(CHECK_0);
  Handle string = java_lang_String::create_from_str(name, CHECK_0);
  Handle thread_group (THREAD,  Universe::system_thread_group());
  JavaValue result(T_VOID);
  JavaCalls::call_special(&result, thread_oop,
                       klass,
                       vmSymbols::object_initializer_name(),
                       vmSymbols::threadgroup_string_void_signature(),
                       thread_group,
                       string,
                       CHECK_0);
  {
    MutexLocker mu(Threads_lock, THREAD);
    compiler_thread = new CompilerThread(queue, counters);
    if (compiler_thread == NULL || compiler_thread->osthread() == NULL){
      vm_exit_during_initialization("java.lang.OutOfMemoryError",
                                    "unable to create new native thread");
    }
    java_lang_Thread::set_thread(thread_oop(), compiler_thread);
    java_lang_Thread::set_priority(thread_oop(), NearMaxPriority);
    int native_prio = CompilerThreadPriority;
    if (native_prio == -1) {
      if (UseCriticalCompilerThreadPriority) {
        native_prio = os::java_to_os_priority[CriticalPriority];
      } else {
        native_prio = os::java_to_os_priority[NearMaxPriority];
      }
    }
    os::set_native_priority(compiler_thread, native_prio);
    java_lang_Thread::set_daemon(thread_oop());
    compiler_thread->set_threadObj(thread_oop());
    compiler_thread->set_compiler(comp);
    Threads::add(compiler_thread);
    Thread::start(compiler_thread);
  }
  os::yield(); // make sure that the compiler thread is started early (especially helpful on SOLARIS)
  return compiler_thread;
}
void CompileBroker::init_compiler_threads(int c1_compiler_count, int c2_compiler_count) {
  EXCEPTION_MARK;
#if !defined(ZERO) && !defined(SHARK)
  assert(c2_compiler_count > 0 || c1_compiler_count > 0, "No compilers?");
#endif // !ZERO && !SHARK
  if (c2_compiler_count > 0) {
    _c2_compile_queue  = new CompileQueue("C2 CompileQueue",  MethodCompileQueue_lock);
    _compilers[1]->set_num_compiler_threads(c2_compiler_count);
  }
  if (c1_compiler_count > 0) {
    _c1_compile_queue  = new CompileQueue("C1 CompileQueue",  MethodCompileQueue_lock);
    _compilers[0]->set_num_compiler_threads(c1_compiler_count);
  }
  int compiler_count = c1_compiler_count + c2_compiler_count;
  _compiler_threads =
    new (ResourceObj::C_HEAP, mtCompiler) GrowableArray<CompilerThread*>(compiler_count, true);
  char name_buffer[256];
  for (int i = 0; i < c2_compiler_count; i++) {
    sprintf(name_buffer, "C2 CompilerThread%d", i);
    CompilerCounters* counters = new CompilerCounters("compilerThread", i, CHECK);
    CompilerThread* new_thread = make_compiler_thread(name_buffer, _c2_compile_queue, counters, _compilers[1], CHECK);
    _compiler_threads->append(new_thread);
  }
  for (int i = c2_compiler_count; i < compiler_count; i++) {
    sprintf(name_buffer, "C1 CompilerThread%d", i);
    CompilerCounters* counters = new CompilerCounters("compilerThread", i, CHECK);
    CompilerThread* new_thread = make_compiler_thread(name_buffer, _c1_compile_queue, counters, _compilers[0], CHECK);
    _compiler_threads->append(new_thread);
  }
  if (UsePerfData) {
    PerfDataManager::create_constant(SUN_CI, "threads", PerfData::U_Bytes, compiler_count, CHECK);
  }
}
void CompileBroker::mark_on_stack() {
  assert(SafepointSynchronize::is_at_safepoint(), "sanity check");
  if (_c2_compile_queue != NULL) {
    _c2_compile_queue->mark_on_stack();
  }
  if (_c1_compile_queue != NULL) {
    _c1_compile_queue->mark_on_stack();
  }
}
void CompileBroker::compile_method_base(methodHandle method,
                                        int osr_bci,
                                        int comp_level,
                                        methodHandle hot_method,
                                        int hot_count,
                                        const char* comment,
                                        Thread* thread) {
  if (!_initialized) {
    return;
  }
  guarantee(!method->is_abstract(), "cannot compile abstract methods");
  assert(method->method_holder()->oop_is_instance(),
         "sanity check");
  assert(!method->method_holder()->is_not_initialized(),
         "method holder must be initialized");
  assert(!method->is_method_handle_intrinsic(), "do not enqueue these guys");
  if (CIPrintRequests) {
    tty->print("request: ");
    method->print_short_name(tty);
    if (osr_bci != InvocationEntryBci) {
      tty->print(" osr_bci: %d", osr_bci);
    }
    tty->print(" comment: %s count: %d", comment, hot_count);
    if (!hot_method.is_null()) {
      tty->print(" hot: ");
      if (hot_method() != method()) {
          hot_method->print_short_name(tty);
      } else {
        tty->print("yes");
      }
    }
    tty->cr();
  }
  if (compilation_is_complete(method, osr_bci, comp_level)) {
    return;
  }
#ifndef PRODUCT
  if (osr_bci != -1 && !FLAG_IS_DEFAULT(OSROnlyBCI)) {
    if ((OSROnlyBCI > 0) ? (OSROnlyBCI != osr_bci) : (-OSROnlyBCI == osr_bci)) {
      return;
    }
  }
#endif
  if (compilation_is_in_queue(method)) {
    return;
  }
  if (InstanceRefKlass::owns_pending_list_lock(JavaThread::current())) {
    return;
  }
  if (TieredCompilation) {
    method->get_method_counters(thread);
  }
  CompileTask* task     = NULL;
  bool         blocking = false;
  CompileQueue* queue  = compile_queue(comp_level);
  {
    MutexLocker locker(queue->lock(), thread);
    if (compilation_is_in_queue(method)) {
      return;
    }
    if (compilation_is_complete(method, osr_bci, comp_level)) {
      return;
    }
    int compile_id = assign_compile_id(method, osr_bci);
    if (compile_id == 0) {
      return;
    }
    blocking = is_compile_blocking();
    task = create_compile_task(queue,
                               compile_id, method,
                               osr_bci, comp_level,
                               hot_method, hot_count, comment,
                               blocking);
  }
  if (blocking) {
    wait_for_completion(task);
  }
}
nmethod* CompileBroker::compile_method(methodHandle method, int osr_bci,
                                       int comp_level,
                                       methodHandle hot_method, int hot_count,
                                       const char* comment, Thread* THREAD) {
  assert(method->method_holder()->oop_is_instance(), "not an instance method");
  assert(osr_bci == InvocationEntryBci || (0 <= osr_bci && osr_bci < method->code_size()), "bci out of range");
  assert(!method->is_abstract() && (osr_bci == InvocationEntryBci || !method->is_native()), "cannot compile abstract/native methods");
  assert(!method->method_holder()->is_not_initialized(), "method holder must be initialized");
  assert(WhiteBoxAPI || TieredCompilation || comp_level == CompLevel_highest_tier, "only CompLevel_highest_tier must be used in non-tiered");
  AbstractCompiler *comp = CompileBroker::compiler(comp_level);
  if (comp == NULL || !comp->can_compile_method(method) ||
      compilation_is_prohibited(method, osr_bci, comp_level)) {
    return NULL;
  }
  if (osr_bci == InvocationEntryBci) {
    nmethod* method_code = method->code();
    if (method_code != NULL) {
      if (compilation_is_complete(method, osr_bci, comp_level)) {
        return method_code;
      }
    }
    if (method->is_not_compilable(comp_level)) {
      return NULL;
    }
  } else {
#ifndef TIERED
    assert(comp_level == CompLevel_highest_tier,
           "all OSR compiles are assumed to be at a single compilation lavel");
#endif // TIERED
    nmethod* nm = method->lookup_osr_nmethod_for(osr_bci, comp_level, false);
    if (nm != NULL) return nm;
    if (method->is_not_osr_compilable(comp_level)) return NULL;
  }
  assert(!HAS_PENDING_EXCEPTION, "No exception should be present");
  if (comp->is_c2() || comp->is_shark()) {
    method->constants()->resolve_string_constants(CHECK_AND_CLEAR_NULL);
    Method::load_signature_classes(method, CHECK_AND_CLEAR_NULL);
  }
  if (method->is_native() && !method->is_method_handle_intrinsic()) {
    bool in_base_library;
    address adr = NativeLookup::lookup(method, in_base_library, THREAD);
    if (HAS_PENDING_EXCEPTION) {
      method->set_not_compilable(); // implies is_not_osr_compilable()
      CLEAR_PENDING_EXCEPTION;
      return NULL;
    }
    assert(method->has_native_function(), "must have native code by now");
  }
  if (method->is_old()) {
    return NULL;
  }
  if (JvmtiExport::should_post_compiled_method_load()) {
    method->jmethod_id();
  }
  if (method->is_native()) {
    if (!PreferInterpreterNativeStubs || method->is_method_handle_intrinsic()) {
      AdapterHandlerLibrary::create_native_wrapper(method);
    } else {
      return NULL;
    }
  } else {
    if (!should_compile_new_jobs()) {
      CompilationPolicy::policy()->delay_compilation(method());
      return NULL;
    }
    compile_method_base(method, osr_bci, comp_level, hot_method, hot_count, comment, THREAD);
  }
  return osr_bci  == InvocationEntryBci ? method->code() : method->lookup_osr_nmethod_for(osr_bci, comp_level, false);
}
bool CompileBroker::compilation_is_complete(methodHandle method,
                                            int          osr_bci,
                                            int          comp_level) {
  bool is_osr = (osr_bci != standard_entry_bci);
  if (is_osr) {
    if (method->is_not_osr_compilable(comp_level)) {
      return true;
    } else {
      nmethod* result = method->lookup_osr_nmethod_for(osr_bci, comp_level, true);
      return (result != NULL);
    }
  } else {
    if (method->is_not_compilable(comp_level)) {
      return true;
    } else {
      nmethod* result = method->code();
      if (result == NULL) return false;
      return comp_level == result->comp_level();
    }
  }
}
bool CompileBroker::compilation_is_in_queue(methodHandle method) {
  return method->queued_for_compilation();
}
bool CompileBroker::compilation_is_prohibited(methodHandle method, int osr_bci, int comp_level) {
  bool is_native = method->is_native();
  AbstractCompiler *comp = compiler(comp_level);
  if (is_native &&
      (!CICompileNatives || comp == NULL || !comp->supports_native())) {
    method->set_not_compilable_quietly(comp_level);
    return true;
  }
  bool is_osr = (osr_bci != standard_entry_bci);
  if (is_osr &&
      (!CICompileOSR || comp == NULL || !comp->supports_osr())) {
    method->set_not_osr_compilable(comp_level);
    return true;
  }
  bool quietly;
  if (CompilerOracle::should_exclude(method, quietly)) {
    if (!quietly) {
      ResourceMark rm;
      tty->print("### Excluding %s:%s",
                 method->is_native() ? "generation of native wrapper" : "compile",
                 (method->is_static() ? " static" : ""));
      method->print_short_name(tty);
      tty->cr();
    }
    method->set_not_compilable(CompLevel_all, !quietly, "excluded by CompilerOracle");
  }
  return false;
}
int CompileBroker::assign_compile_id(methodHandle method, int osr_bci) {
#ifdef ASSERT
  bool is_osr = (osr_bci != standard_entry_bci);
  int id;
  if (method->is_native()) {
    assert(!is_osr, "can't be osr");
    return Atomic::add(1, &_compilation_id);
  } else if (CICountOSR && is_osr) {
    id = Atomic::add(1, &_osr_compilation_id);
    if (CIStartOSR <= id && id < CIStopOSR) {
      return id;
    }
  } else {
    id = Atomic::add(1, &_compilation_id);
    if (CIStart <= id && id < CIStop) {
      return id;
    }
  }
  method->set_not_compilable_quietly();
  return 0;
#else
  return Atomic::add(1, &_compilation_id);
#endif
}
bool CompileBroker::is_compile_blocking() {
  assert(!InstanceRefKlass::owns_pending_list_lock(JavaThread::current()), "possible deadlock");
  return !BackgroundCompilation;
}
void CompileBroker::preload_classes(methodHandle method, TRAPS) {
  ShouldNotReachHere();
}
CompileTask* CompileBroker::create_compile_task(CompileQueue* queue,
                                              int           compile_id,
                                              methodHandle  method,
                                              int           osr_bci,
                                              int           comp_level,
                                              methodHandle  hot_method,
                                              int           hot_count,
                                              const char*   comment,
                                              bool          blocking) {
  CompileTask* new_task = CompileTask::allocate();
  new_task->initialize(compile_id, method, osr_bci, comp_level,
                       hot_method, hot_count, comment,
                       blocking);
  queue->add(new_task);
  return new_task;
}
void CompileBroker::wait_for_completion(CompileTask* task) {
  if (CIPrintCompileQueue) {
    ttyLocker ttyl;
    tty->print_cr("BLOCKING FOR COMPILE");
  }
  assert(task->is_blocking(), "can only wait on blocking task");
  JavaThread* thread = JavaThread::current();
  thread->set_blocked_on_compilation(true);
  methodHandle method(thread, task->method());
  {
    MutexLocker waiter(task->lock(), thread);
    while (!task->is_complete() && !is_compilation_disabled_forever()) {
      task->lock()->wait();
    }
  }
  thread->set_blocked_on_compilation(false);
  if (is_compilation_disabled_forever()) {
    CompileTask::free(task);
    return;
  }
  assert(task->is_complete(), "Compilation should have completed");
  assert(task->code_handle() == NULL, "must be reset");
  CompileTask::free(task);
}
bool CompileBroker::init_compiler_runtime() {
  CompilerThread* thread = CompilerThread::current();
  AbstractCompiler* comp = thread->compiler();
  guarantee(comp != NULL, "Compiler object must exist");
  int system_dictionary_modification_counter;
  {
    MutexLocker locker(Compile_lock, thread);
    system_dictionary_modification_counter = SystemDictionary::number_of_modifications();
  }
  {
    ThreadToNativeFromVM ttn(thread);
    ciEnv ci_env(NULL, system_dictionary_modification_counter);
    ci_env.cache_jvmti_state();
    ci_env.cache_dtrace_flags();
    ThreadInVMfromNative tv(thread);
    ResetNoHandleMark rnhm;
    if (!comp->is_shark()) {
      comp->initialize();
    }
  }
  if (comp->is_failed()) {
    disable_compilation_forever();
    shutdown_compiler_runtime(comp, thread);
    return false;
  }
  if (comp->is_c1() && (thread->get_buffer_blob() == NULL)) {
    warning("Initialization of %s thread failed (no space to run compilers)", thread->name());
    return false;
  }
  return true;
}
void CompileBroker::shutdown_compiler_runtime(AbstractCompiler* comp, CompilerThread* thread) {
  if (thread->get_buffer_blob() != NULL) {
    MutexLockerEx mu(CodeCache_lock, Mutex::_no_safepoint_check_flag);
    CodeCache::free(thread->get_buffer_blob());
  }
  if (comp->should_perform_shutdown()) {
    warning("%s initialization failed. Shutting down all compilers", comp->name());
    comp->set_shut_down();
    if (_c1_compile_queue != NULL) {
      _c1_compile_queue->free_all();
    }
    if (_c2_compile_queue != NULL) {
      _c2_compile_queue->free_all();
    }
    UseCompiler    = false;
    UseInterpreter = true;
  }
}
void CompileBroker::compiler_thread_loop() {
  CompilerThread* thread = CompilerThread::current();
  CompileQueue* queue = thread->queue();
  ResourceMark rm;
  if (!ciObjectFactory::is_initialized()) {
    ASSERT_IN_VM;
    MutexLocker only_one (CompileThread_lock, thread);
    if (!ciObjectFactory::is_initialized()) {
      ciObjectFactory::initialize();
    }
  }
  if (LogCompilation) {
    init_compiler_thread_log();
  }
  CompileLog* log = thread->log();
  if (log != NULL) {
    log->begin_elem("start_compile_thread name='%s' thread='" UINTX_FORMAT "' process='%d'",
                    thread->name(),
                    os::current_thread_id(),
                    os::current_process_id());
    log->stamp();
    log->end_elem();
  }
  if (!init_compiler_runtime()) {
    return;
  }
  while (!is_compilation_disabled_forever()) {
    HandleMark hm(thread);
    if (CodeCache::unallocated_capacity() < CodeCacheMinimumFreeSpace) {
      handle_full_code_cache();
    }
    CompileTask* task = queue->get();
    if (task == NULL) {
      continue;
    }
    if( CompilerThreadHintNoPreempt )
      os::hint_no_preempt();
    CompilerCounters* counters = ((CompilerThread*)thread)->counters();
    PerfTraceTimedEvent(counters->time_counter(), counters->compile_counter());
    CompileTaskWrapper ctw(task);
    nmethodLocker result_handle;  // (handle for the nmethod produced by this task)
    task->set_code_handle(&result_handle);
    methodHandle method(thread, task->method());
    if (method()->number_of_breakpoints() == 0) {
      if ((UseCompiler || AlwaysCompileLoopMethods) && CompileBroker::should_compile_new_jobs()) {
        invoke_compiler_on_method(task);
      } else {
        method->clear_queued_for_compilation();
        task->set_failure_reason("compilation is disabled");
      }
    }
  }
  shutdown_compiler_runtime(thread->compiler(), thread);
}
void CompileBroker::init_compiler_thread_log() {
    CompilerThread* thread = CompilerThread::current();
    char  file_name[4*K];
    FILE* fp = NULL;
    intx thread_id = os::current_thread_id();
    for (int try_temp_dir = 1; try_temp_dir >= 0; try_temp_dir--) {
      const char* dir = (try_temp_dir ? os::get_temp_directory() : NULL);
      if (dir == NULL) {
        jio_snprintf(file_name, sizeof(file_name), "hs_c" UINTX_FORMAT "_pid%u.log",
                     thread_id, os::current_process_id());
      } else {
        jio_snprintf(file_name, sizeof(file_name),
                     "%s%shs_c" UINTX_FORMAT "_pid%u.log", dir,
                     os::file_separator(), thread_id, os::current_process_id());
      }
      fp = fopen(file_name, "wt");
      if (fp != NULL) {
        if (LogCompilation && Verbose) {
          tty->print_cr("Opening compilation log %s", file_name);
        }
        CompileLog* log = new(ResourceObj::C_HEAP, mtCompiler) CompileLog(file_name, fp, thread_id);
        if (log == NULL) {
          fclose(fp);
          return;
        }
        thread->init_log(log);
        if (xtty != NULL) {
          ttyLocker ttyl;
          xtty->elem("thread_logfile thread='" INTX_FORMAT "' filename='%s'", thread_id, file_name);
        }
        return;
      }
    }
    warning("Cannot open log file: %s", file_name);
}
void CompileBroker::set_should_block() {
  assert(Threads_lock->owner() == Thread::current(), "must have threads lock");
  assert(SafepointSynchronize::is_at_safepoint(), "must be at a safepoint already");
#ifndef PRODUCT
  if (PrintCompilation && (Verbose || WizardMode))
    tty->print_cr("notifying compiler thread pool to block");
#endif
  _should_block = true;
}
void CompileBroker::maybe_block() {
  if (_should_block) {
#ifndef PRODUCT
    if (PrintCompilation && (Verbose || WizardMode))
      tty->print_cr("compiler thread " INTPTR_FORMAT " poll detects block request", p2i(Thread::current()));
#endif
    ThreadInVMfromNative tivfn(JavaThread::current());
  }
}
static void codecache_print(bool detailed)
{
  ResourceMark rm;
  stringStream s;
  {
    MutexLockerEx mu(CodeCache_lock, Mutex::_no_safepoint_check_flag);
    CodeCache::print_summary(&s, detailed);
  }
  ttyLocker ttyl;
  tty->print("%s", s.as_string());
}
static void post_compilation_event(EventCompilation* event, CompileTask* task) {
  assert(event != NULL, "invariant");
  assert(event->should_commit(), "invariant");
  event->set_method(task->method());
  event->set_compileId(task->compile_id());
  event->set_compileLevel(task->comp_level());
  event->set_succeded(task->is_success());
  event->set_isOsr(task->osr_bci() != CompileBroker::standard_entry_bci);
  event->set_codeSize((task->code() == NULL) ? 0 : task->code()->total_size());
  event->set_inlinedBytes(task->num_inlined_bytecodes());
  event->commit();
}
void CompileBroker::invoke_compiler_on_method(CompileTask* task) {
  if (PrintCompilation) {
    ResourceMark rm;
    task->print_line();
  }
  elapsedTimer time;
  CompilerThread* thread = CompilerThread::current();
  ResourceMark rm(thread);
  if (LogEvents) {
    _compilation_log->log_compile(thread, task);
  }
  uint compile_id = task->compile_id();
  int osr_bci = task->osr_bci();
  bool is_osr = (osr_bci != standard_entry_bci);
  bool should_log = (thread->log() != NULL);
  bool should_break = false;
  int task_level = task->comp_level();
  {
    methodHandle method(thread, task->method());
    should_break = check_break_at(method, compile_id, is_osr);
    if (should_log && !CompilerOracle::should_log(method)) {
      should_log = false;
    }
    assert(!method->is_native(), "no longer compile natives");
    set_last_compile(thread, method, is_osr, task_level);
    DTRACE_METHOD_COMPILE_BEGIN_PROBE(method, compiler_name(task_level));
  }
  push_jni_handle_block();
  Method* target_handle = task->method();
  int compilable = ciEnv::MethodCompilable;
  {
    int system_dictionary_modification_counter;
    {
      MutexLocker locker(Compile_lock, thread);
      system_dictionary_modification_counter = SystemDictionary::number_of_modifications();
    }
    NoHandleMark  nhm;
    ThreadToNativeFromVM ttn(thread);
    ciEnv ci_env(task, system_dictionary_modification_counter);
    if (should_break) {
      ci_env.set_break_at_compile(true);
    }
    if (should_log) {
      ci_env.set_log(thread->log());
    }
    assert(thread->env() == &ci_env, "set by ci_env");
    ci_env.cache_jvmti_state();
    ci_env.cache_dtrace_flags();
    ciMethod* target = ci_env.get_method_from_handle(target_handle);
    TraceTime t1("compilation", &time);
    EventCompilation event;
    AbstractCompiler *comp = compiler(task_level);
    if (comp == NULL) {
      ci_env.record_method_not_compilable("no compiler", !TieredCompilation);
    } else {
      comp->compile_method(&ci_env, target, osr_bci);
    }
    if (!ci_env.failing() && task->code() == NULL) {
      ci_env.record_method_not_compilable("compile failed", !TieredCompilation);
    }
    compilable = ci_env.compilable();
    if (ci_env.failing()) {
      const char* failure_reason = ci_env.failure_reason();
      const char* retry_message = ci_env.retry_message();
      task->set_failure_reason(failure_reason);
      if (_compilation_log != NULL) {
        _compilation_log->log_failure(thread, task, ci_env.failure_reason(), retry_message);
      }
      if (PrintCompilation) {
        FormatBufferResource msg = retry_message != NULL ?
            err_msg_res("COMPILE SKIPPED: %s (%s)", ci_env.failure_reason(), retry_message) :
            err_msg_res("COMPILE SKIPPED: %s",      ci_env.failure_reason());
        task->print_compilation(tty, msg);
      }
      EventCompilationFailure event;
      if (event.should_commit()) {
        event.set_compileId(compile_id);
        event.set_failureMessage(failure_reason);
        event.commit();
      }
      if (AbortVMOnCompilationFailure) {
        if (compilable == ciEnv::MethodCompilable_not_at_tier) {
          fatal(err_msg("Not compilable at tier %d: %s", task_level, failure_reason));
        }
        if (compilable == ciEnv::MethodCompilable_never) {
          fatal(err_msg("Never compilable: %s", failure_reason));
        }
      }
    } else {
      task->mark_success();
      task->set_num_inlined_bytecodes(ci_env.num_inlined_bytecodes());
      if (_compilation_log != NULL) {
        nmethod* code = task->code();
        if (code != NULL) {
          _compilation_log->log_nmethod(thread, code);
        }
      }
    }
    assert(task->compile_id() != CICrashAt, "just as planned");
    if (event.should_commit()) {
      post_compilation_event(&event, task);
    }
  }
  pop_jni_handle_block();
  methodHandle method(thread, task->method());
  DTRACE_METHOD_COMPILE_END_PROBE(method, compiler_name(task_level), task->is_success());
  collect_statistics(thread, time, task);
  if (PrintCompilation && PrintCompilation2) {
    tty->print("%7d ", (int) tty->time_stamp().milliseconds());  // print timestamp
    tty->print("%4d ", compile_id);    // print compilation number
    tty->print("%s ", (is_osr ? "%" : " "));
    if (task->code() != NULL) {
      tty->print("size: %d(%d) ", task->code()->total_size(), task->code()->insts_size());
    }
    tty->print_cr("time: %d inlined: %d bytes", (int)time.milliseconds(), task->num_inlined_bytecodes());
  }
  if (PrintCodeCacheOnCompilation)
    codecache_print(/* detailed= */ false);
  switch (compilable) {
  case ciEnv::MethodCompilable_never:
    if (is_osr)
      method->set_not_osr_compilable_quietly();
    else
      method->set_not_compilable_quietly();
    break;
  case ciEnv::MethodCompilable_not_at_tier:
    if (is_osr)
      method->set_not_osr_compilable_quietly(task_level);
    else
      method->set_not_compilable_quietly(task_level);
    break;
  }
  method->clear_queued_for_compilation();
#ifdef ASSERT
  if (CollectedHeap::fired_fake_oom()) {
    tty->print_cr("*** Shutting down VM after successful fake OOM");
    vm_exit(0);
  }
#endif
}
void CompileBroker::handle_full_code_cache() {
  UseInterpreter = true;
  if (UseCompiler || AlwaysCompileLoopMethods ) {
    if (xtty != NULL) {
      ResourceMark rm;
      stringStream s;
      CodeCache::log_state(&s);
      ttyLocker ttyl;
      xtty->begin_elem("code_cache_full");
      xtty->print("%s", s.as_string());
      xtty->stamp();
      xtty->end_elem();
    }
    CodeCache::report_codemem_full();
#ifndef PRODUCT
    if (CompileTheWorld || ExitOnFullCodeCache) {
      codecache_print(/* detailed= */ true);
      before_exit(JavaThread::current());
      exit_globals(); // will delete tty
      vm_direct_exit(CompileTheWorld ? 0 : 1);
    }
#endif
    if (UseCodeCacheFlushing) {
      if (CompileBroker::set_should_compile_new_jobs(CompileBroker::stop_compilation)) {
        NMethodSweeper::log_sweep("disable_compiler");
      }
      ThreadInVMfromUnknown in_vm;
      NMethodSweeper::possibly_sweep();
    } else {
      disable_compilation_forever();
    }
    if (should_print_compiler_warning()) {
      warning("CodeCache is full. Compiler has been disabled.");
      warning("Try increasing the code cache size using -XX:ReservedCodeCacheSize=");
      codecache_print(/* detailed= */ true);
    }
  }
}
void CompileBroker::set_last_compile(CompilerThread* thread, methodHandle method, bool is_osr, int comp_level) {
  ResourceMark rm;
  char* method_name = method->name()->as_C_string();
  strncpy(_last_method_compiled, method_name, CompileBroker::name_buffer_length);
  _last_method_compiled[CompileBroker::name_buffer_length - 1] = '\0'; // ensure null terminated
  char current_method[CompilerCounters::cmname_buffer_length];
  size_t maxLen = CompilerCounters::cmname_buffer_length;
  if (UsePerfData) {
    const char* class_name = method->method_holder()->name()->as_C_string();
    size_t s1len = strlen(class_name);
    size_t s2len = strlen(method_name);
    if (s1len + s2len + 2 > maxLen) {
      if (s2len + 2 > maxLen) {
        class_name += s1len; // null string
      }
      else {
        class_name += ((s1len + s2len + 2) - maxLen);
      }
    }
    jio_snprintf(current_method, maxLen, "%s %s", class_name, method_name);
  }
  if (CICountOSR && is_osr) {
    _last_compile_type = osr_compile;
  } else {
    _last_compile_type = normal_compile;
  }
  _last_compile_level = comp_level;
  if (UsePerfData) {
    CompilerCounters* counters = thread->counters();
    counters->set_current_method(current_method);
    counters->set_compile_type((jlong)_last_compile_type);
  }
}
void CompileBroker::push_jni_handle_block() {
  JavaThread* thread = JavaThread::current();
  JNIHandleBlock* java_handles = thread->active_handles();
  JNIHandleBlock* compile_handles = JNIHandleBlock::allocate_block(thread);
  assert(compile_handles != NULL && java_handles != NULL, "should not be NULL");
  compile_handles->set_pop_frame_link(java_handles);  // make sure java handles get gc'd.
  thread->set_active_handles(compile_handles);
}
void CompileBroker::pop_jni_handle_block() {
  JavaThread* thread = JavaThread::current();
  JNIHandleBlock* compile_handles = thread->active_handles();
  JNIHandleBlock* java_handles = compile_handles->pop_frame_link();
  thread->set_active_handles(java_handles);
  compile_handles->set_pop_frame_link(NULL);
  JNIHandleBlock::release_block(compile_handles, thread); // may block
}
bool CompileBroker::check_break_at(methodHandle method, int compile_id, bool is_osr) {
  if (CICountOSR && is_osr && (compile_id == CIBreakAtOSR)) {
    return true;
  } else if( CompilerOracle::should_break_at(method) ) { // break when compiling
    return true;
  } else {
    return (compile_id == CIBreakAt);
  }
}
void CompileBroker::collect_statistics(CompilerThread* thread, elapsedTimer time, CompileTask* task) {
  bool success = task->is_success();
  methodHandle method (thread, task->method());
  uint compile_id = task->compile_id();
  bool is_osr = (task->osr_bci() != standard_entry_bci);
  nmethod* code = task->code();
  CompilerCounters* counters = thread->counters();
  assert(code == NULL || code->is_locked_by_vm(), "will survive the MutexLocker");
  MutexLocker locker(CompileStatistics_lock);
  if (!success) {
    _total_bailout_count++;
    if (UsePerfData) {
      _perf_last_failed_method->set_value(counters->current_method());
      _perf_last_failed_type->set_value(counters->compile_type());
      _perf_total_bailout_count->inc();
    }
  } else if (code == NULL) {
    if (UsePerfData) {
      _perf_last_invalidated_method->set_value(counters->current_method());
      _perf_last_invalidated_type->set_value(counters->compile_type());
      _perf_total_invalidated_count->inc();
    }
    _total_invalidated_count++;
  } else {
    _perf_total_compilation->inc(time.ticks());
    _t_total_compilation.add(time);
    _peak_compilation_time = time.milliseconds() > _peak_compilation_time ? time.milliseconds() : _peak_compilation_time;
    if (CITime) {
      if (is_osr) {
        _t_osr_compilation.add(time);
        _sum_osr_bytes_compiled += method->code_size() + task->num_inlined_bytecodes();
      } else {
        _t_standard_compilation.add(time);
        _sum_standard_bytes_compiled += method->code_size() + task->num_inlined_bytecodes();
      }
    }
    if (UsePerfData) {
      _perf_last_method->set_value(counters->current_method());
      _perf_last_compile_type->set_value(counters->compile_type());
      _perf_last_compile_size->set_value(method->code_size() +
                                         task->num_inlined_bytecodes());
      if (is_osr) {
        _perf_osr_compilation->inc(time.ticks());
        _perf_sum_osr_bytes_compiled->inc(method->code_size() + task->num_inlined_bytecodes());
      } else {
        _perf_standard_compilation->inc(time.ticks());
        _perf_sum_standard_bytes_compiled->inc(method->code_size() + task->num_inlined_bytecodes());
      }
    }
    if (CITimeEach) {
      float bytes_per_sec = 1.0 * (method->code_size() + task->num_inlined_bytecodes()) / time.seconds();
      tty->print_cr("%3d   seconds: %f bytes/sec : %f (bytes %d + %d inlined)",
                    compile_id, time.seconds(), bytes_per_sec, method->code_size(), task->num_inlined_bytecodes());
    }
    _sum_nmethod_size      += code->total_size();
    _sum_nmethod_code_size += code->insts_size();
    _total_compile_count++;
    if (UsePerfData) {
      _perf_sum_nmethod_size->inc(     code->total_size());
      _perf_sum_nmethod_code_size->inc(code->insts_size());
      _perf_total_compile_count->inc();
    }
    if (is_osr) {
      if (UsePerfData) _perf_total_osr_compile_count->inc();
      _total_osr_compile_count++;
    } else {
      if (UsePerfData) _perf_total_standard_compile_count->inc();
      _total_standard_compile_count++;
    }
  }
  if (UsePerfData) counters->set_current_method("");
}
const char* CompileBroker::compiler_name(int comp_level) {
  AbstractCompiler *comp = CompileBroker::compiler(comp_level);
  if (comp == NULL) {
    return "no compiler";
  } else {
    return (comp->name());
  }
}
void CompileBroker::print_times() {
  tty->cr();
  tty->print_cr("Accumulated compiler times (for compiled methods only)");
  tty->print_cr("------------------------------------------------");
  tty->print_cr("  Total compilation time   : %6.3f s", CompileBroker::_t_total_compilation.seconds());
  tty->print_cr("    Standard compilation   : %6.3f s, Average : %2.3f",
                CompileBroker::_t_standard_compilation.seconds(),
                CompileBroker::_t_standard_compilation.seconds() / CompileBroker::_total_standard_compile_count);
  tty->print_cr("    On stack replacement   : %6.3f s, Average : %2.3f", CompileBroker::_t_osr_compilation.seconds(), CompileBroker::_t_osr_compilation.seconds() / CompileBroker::_total_osr_compile_count);
  AbstractCompiler *comp = compiler(CompLevel_simple);
  if (comp != NULL) {
    comp->print_timers();
  }
  comp = compiler(CompLevel_full_optimization);
  if (comp != NULL) {
    comp->print_timers();
  }
  tty->cr();
  tty->print_cr("  Total compiled methods   : %6d methods", CompileBroker::_total_compile_count);
  tty->print_cr("    Standard compilation   : %6d methods", CompileBroker::_total_standard_compile_count);
  tty->print_cr("    On stack replacement   : %6d methods", CompileBroker::_total_osr_compile_count);
  int tcb = CompileBroker::_sum_osr_bytes_compiled + CompileBroker::_sum_standard_bytes_compiled;
  tty->print_cr("  Total compiled bytecodes : %6d bytes", tcb);
  tty->print_cr("    Standard compilation   : %6d bytes", CompileBroker::_sum_standard_bytes_compiled);
  tty->print_cr("    On stack replacement   : %6d bytes", CompileBroker::_sum_osr_bytes_compiled);
  int bps = (int)(tcb / CompileBroker::_t_total_compilation.seconds());
  tty->print_cr("  Average compilation speed: %6d bytes/s", bps);
  tty->cr();
  tty->print_cr("  nmethod code size        : %6d bytes", CompileBroker::_sum_nmethod_code_size);
  tty->print_cr("  nmethod total size       : %6d bytes", CompileBroker::_sum_nmethod_size);
}
void CompileBroker::print_last_compile() {
  if ( _last_compile_level != CompLevel_none &&
       compiler(_last_compile_level) != NULL &&
       _last_method_compiled != NULL &&
       _last_compile_type != no_compile) {
    if (_last_compile_type == osr_compile) {
      tty->print_cr("Last parse:  [osr]%d+++(%d) %s",
                    _osr_compilation_id, _last_compile_level, _last_method_compiled);
    } else {
      tty->print_cr("Last parse:  %d+++(%d) %s",
                    _compilation_id, _last_compile_level, _last_method_compiled);
    }
  }
}
void CompileBroker::print_compiler_threads_on(outputStream* st) {
#ifndef PRODUCT
  st->print_cr("Compiler thread printing unimplemented.");
  st->cr();
#endif
}
C:\hotspot-69087d08d473\src\share\vm/compiler/compileBroker.hpp
#ifndef SHARE_VM_COMPILER_COMPILEBROKER_HPP
#define SHARE_VM_COMPILER_COMPILEBROKER_HPP
#include "ci/compilerInterface.hpp"
#include "compiler/abstractCompiler.hpp"
#include "runtime/perfData.hpp"
class nmethod;
class nmethodLocker;
class CompileTask : public CHeapObj<mtCompiler> {
  friend class VMStructs;
 private:
  static CompileTask* _task_free_list;
#ifdef ASSERT
  static int          _num_allocated_tasks;
#endif
  Monitor*     _lock;
  uint         _compile_id;
  Method*      _method;
  jobject      _method_holder;
  int          _osr_bci;
  bool         _is_complete;
  bool         _is_success;
  bool         _is_blocking;
  int          _comp_level;
  int          _num_inlined_bytecodes;
  nmethodLocker* _code_handle;  // holder of eventual result
  CompileTask* _next, *_prev;
  bool         _is_free;
  jlong        _time_queued;  // in units of os::elapsed_counter()
  Method*      _hot_method;   // which method actually triggered this task
  jobject      _hot_method_holder;
  int          _hot_count;    // information about its invocation counter
  const char*  _comment;      // more info about the task
  const char*  _failure_reason;
 public:
  CompileTask() {
    _lock = new Monitor(Mutex::nonleaf+2, "CompileTaskLock");
  }
  void initialize(int compile_id, methodHandle method, int osr_bci, int comp_level,
                  methodHandle hot_method, int hot_count, const char* comment,
                  bool is_blocking);
  static CompileTask* allocate();
  static void         free(CompileTask* task);
  int          compile_id() const                { return _compile_id; }
  Method*      method() const                    { return _method; }
  int          osr_bci() const                   { return _osr_bci; }
  bool         is_complete() const               { return _is_complete; }
  bool         is_blocking() const               { return _is_blocking; }
  bool         is_success() const                { return _is_success; }
  nmethodLocker* code_handle() const             { return _code_handle; }
  void         set_code_handle(nmethodLocker* l) { _code_handle = l; }
  nmethod*     code() const;                     // _code_handle->code()
  void         set_code(nmethod* nm);            // _code_handle->set_code(nm)
  Monitor*     lock() const                      { return _lock; }
  void         mark_complete()                   { _is_complete = true; }
  void         mark_success()                    { _is_success = true; }
  int          comp_level()                      { return _comp_level;}
  void         set_comp_level(int comp_level)    { _comp_level = comp_level;}
  int          num_inlined_bytecodes() const     { return _num_inlined_bytecodes; }
  void         set_num_inlined_bytecodes(int n)  { _num_inlined_bytecodes = n; }
  CompileTask* next() const                      { return _next; }
  void         set_next(CompileTask* next)       { _next = next; }
  CompileTask* prev() const                      { return _prev; }
  void         set_prev(CompileTask* prev)       { _prev = prev; }
  bool         is_free() const                   { return _is_free; }
  void         set_is_free(bool val)             { _is_free = val; }
private:
  static void  print_compilation_impl(outputStream* st, Method* method, int compile_id, int comp_level,
                                      bool is_osr_method = false, int osr_bci = -1, bool is_blocking = false,
                                      const char* msg = NULL, bool short_form = false);
public:
  void         print_compilation(outputStream* st = tty, const char* msg = NULL, bool short_form = false);
  static void  print_compilation(outputStream* st, const nmethod* nm, const char* msg = NULL, bool short_form = false) {
    print_compilation_impl(st, nm->method(), nm->compile_id(), nm->comp_level(),
                           nm->is_osr_method(), nm->is_osr_method() ? nm->osr_entry_bci() : -1, /*is_blocking*/ false,
                           msg, short_form);
  }
  static void  print_inlining(outputStream* st, ciMethod* method, int inline_level, int bci, const char* msg = NULL);
  static void  print_inlining(ciMethod* method, int inline_level, int bci, const char* msg = NULL) {
    print_inlining(tty, method, inline_level, bci, msg);
  }
  void mark_on_stack();
  static void  print_inline_indent(int inline_level, outputStream* st = tty);
  void         print();
  void         print_line();
  void         print_line_on_error(outputStream* st, char* buf, int buflen);
  void         log_task(xmlStream* log);
  void         log_task_queued();
  void         log_task_start(CompileLog* log);
  void         log_task_done(CompileLog* log);
  void         set_failure_reason(const char* reason) {
    _failure_reason = reason;
  }
};
class CompilerCounters : public CHeapObj<mtCompiler> {
  public:
    enum {
      cmname_buffer_length = 160
    };
  private:
    char _current_method[cmname_buffer_length];
    PerfStringVariable* _perf_current_method;
    int  _compile_type;
    PerfVariable* _perf_compile_type;
    PerfCounter* _perf_time;
    PerfCounter* _perf_compiles;
  public:
    CompilerCounters(const char* name, int instance, TRAPS);
    void set_current_method(const char* method) {
      strncpy(_current_method, method, (size_t)cmname_buffer_length-1);
      _current_method[cmname_buffer_length-1] = '\0';
      if (UsePerfData) _perf_current_method->set_value(method);
    }
    char* current_method()                  { return _current_method; }
    void set_compile_type(int compile_type) {
      _compile_type = compile_type;
      if (UsePerfData) _perf_compile_type->set_value((jlong)compile_type);
    }
    int compile_type()                       { return _compile_type; }
    PerfCounter* time_counter()              { return _perf_time; }
    PerfCounter* compile_counter()           { return _perf_compiles; }
};
class CompileQueue : public CHeapObj<mtCompiler> {
 private:
  const char* _name;
  Monitor*    _lock;
  CompileTask* _first;
  CompileTask* _last;
  CompileTask* _first_stale;
  int _size;
  void purge_stale_tasks();
 public:
  CompileQueue(const char* name, Monitor* lock) {
    _name = name;
    _lock = lock;
    _first = NULL;
    _last = NULL;
    _size = 0;
    _first_stale = NULL;
  }
  const char*  name() const                      { return _name; }
  Monitor*     lock() const                      { return _lock; }
  void         add(CompileTask* task);
  void         remove(CompileTask* task);
  void         remove_and_mark_stale(CompileTask* task);
  CompileTask* first()                           { return _first; }
  CompileTask* last()                            { return _last;  }
  CompileTask* get();
  bool         is_empty() const                  { return _first == NULL; }
  int          size()     const                  { return _size;          }
  void mark_on_stack();
  void free_all();
  NOT_PRODUCT (void print();)
  ~CompileQueue() {
    assert (is_empty(), " Compile Queue must be empty");
  }
};
class CompileTaskWrapper : StackObj {
public:
  CompileTaskWrapper(CompileTask* task);
  ~CompileTaskWrapper();
};
class CompileBroker: AllStatic {
 friend class Threads;
  friend class CompileTaskWrapper;
 public:
  enum {
    name_buffer_length = 100
  };
  enum { no_compile, normal_compile, osr_compile, native_compile };
  static int assign_compile_id (methodHandle method, int osr_bci);
 private:
  static bool _initialized;
  static volatile bool _should_block;
  static volatile jint _should_compile_new_jobs;
  static AbstractCompiler* _compilers[2];
  static volatile jint _compilation_id;
  static volatile jint _osr_compilation_id;
  static int  _last_compile_type;
  static int  _last_compile_level;
  static char _last_method_compiled[name_buffer_length];
  static CompileQueue* _c2_compile_queue;
  static CompileQueue* _c1_compile_queue;
  static GrowableArray<CompilerThread*>* _compiler_threads;
  static PerfCounter* _perf_total_compilation;
  static PerfCounter* _perf_native_compilation;
  static PerfCounter* _perf_osr_compilation;
  static PerfCounter* _perf_standard_compilation;
  static PerfCounter* _perf_total_bailout_count;
  static PerfCounter* _perf_total_invalidated_count;
  static PerfCounter* _perf_total_compile_count;
  static PerfCounter* _perf_total_native_compile_count;
  static PerfCounter* _perf_total_osr_compile_count;
  static PerfCounter* _perf_total_standard_compile_count;
  static PerfCounter* _perf_sum_osr_bytes_compiled;
  static PerfCounter* _perf_sum_standard_bytes_compiled;
  static PerfCounter* _perf_sum_nmethod_size;
  static PerfCounter* _perf_sum_nmethod_code_size;
  static PerfStringVariable* _perf_last_method;
  static PerfStringVariable* _perf_last_failed_method;
  static PerfStringVariable* _perf_last_invalidated_method;
  static PerfVariable*       _perf_last_compile_type;
  static PerfVariable*       _perf_last_compile_size;
  static PerfVariable*       _perf_last_failed_type;
  static PerfVariable*       _perf_last_invalidated_type;
  static elapsedTimer _t_total_compilation;
  static elapsedTimer _t_osr_compilation;
  static elapsedTimer _t_standard_compilation;
  static int _total_compile_count;
  static int _total_bailout_count;
  static int _total_invalidated_count;
  static int _total_native_compile_count;
  static int _total_osr_compile_count;
  static int _total_standard_compile_count;
  static int _sum_osr_bytes_compiled;
  static int _sum_standard_bytes_compiled;
  static int _sum_nmethod_size;
  static int _sum_nmethod_code_size;
  static long _peak_compilation_time;
  static volatile jint _print_compilation_warning;
  static CompilerThread* make_compiler_thread(const char* name, CompileQueue* queue, CompilerCounters* counters, AbstractCompiler* comp, TRAPS);
  static void init_compiler_threads(int c1_compiler_count, int c2_compiler_count);
  static bool compilation_is_prohibited(methodHandle method, int osr_bci, int comp_level);
  static bool is_compile_blocking      ();
  static void preload_classes          (methodHandle method, TRAPS);
  static CompileTask* create_compile_task(CompileQueue* queue,
                                          int           compile_id,
                                          methodHandle  method,
                                          int           osr_bci,
                                          int           comp_level,
                                          methodHandle  hot_method,
                                          int           hot_count,
                                          const char*   comment,
                                          bool          blocking);
  static void wait_for_completion(CompileTask* task);
  static void invoke_compiler_on_method(CompileTask* task);
  static void set_last_compile(CompilerThread *thread, methodHandle method, bool is_osr, int comp_level);
  static void push_jni_handle_block();
  static void pop_jni_handle_block();
  static bool check_break_at(methodHandle method, int compile_id, bool is_osr);
  static void collect_statistics(CompilerThread* thread, elapsedTimer time, CompileTask* task);
  static void compile_method_base(methodHandle method,
                                  int osr_bci,
                                  int comp_level,
                                  methodHandle hot_method,
                                  int hot_count,
                                  const char* comment,
                                  Thread* thread);
  static CompileQueue* compile_queue(int comp_level) {
    if (is_c2_compile(comp_level)) return _c2_compile_queue;
    if (is_c1_compile(comp_level)) return _c1_compile_queue;
    return NULL;
  }
  static bool init_compiler_runtime();
  static void shutdown_compiler_runtime(AbstractCompiler* comp, CompilerThread* thread);
 public:
  enum {
    standard_entry_bci = InvocationEntryBci
  };
  static AbstractCompiler* compiler(int comp_level) {
    if (is_c2_compile(comp_level)) return _compilers[1]; // C2
    if (is_c1_compile(comp_level)) return _compilers[0]; // C1
    return NULL;
  }
  static bool compilation_is_complete(methodHandle method, int osr_bci, int comp_level);
  static bool compilation_is_in_queue(methodHandle method);
  static int queue_size(int comp_level) {
    CompileQueue *q = compile_queue(comp_level);
    return q != NULL ? q->size() : 0;
  }
  static void compilation_init();
  static void init_compiler_thread_log();
  static nmethod* compile_method(methodHandle method,
                                 int osr_bci,
                                 int comp_level,
                                 methodHandle hot_method,
                                 int hot_count,
                                 const char* comment, Thread* thread);
  static void compiler_thread_loop();
  static uint get_compilation_id() { return _compilation_id; }
  static void set_should_block();
  static void maybe_block();
  enum {
    stop_compilation    = 0,
    run_compilation     = 1,
    shutdown_compilaton = 2
  };
  static bool should_compile_new_jobs() { return UseCompiler && (_should_compile_new_jobs == run_compilation); }
  static bool set_should_compile_new_jobs(jint new_state) {
    jint old = Atomic::cmpxchg(new_state, &_should_compile_new_jobs, 1-new_state);
    return (old == (1-new_state));
  }
  static void disable_compilation_forever() {
    UseCompiler               = false;
    AlwaysCompileLoopMethods  = false;
    Atomic::xchg(shutdown_compilaton, &_should_compile_new_jobs);
  }
  static bool is_compilation_disabled_forever() {
    return _should_compile_new_jobs == shutdown_compilaton;
  }
  static void handle_full_code_cache();
  static bool should_print_compiler_warning() {
    jint old = Atomic::cmpxchg(1, &_print_compilation_warning, 0);
    return old == 0;
  }
  static jlong total_compilation_ticks() {
    return _perf_total_compilation != NULL ? _perf_total_compilation->get_value() : 0;
  }
  static void mark_on_stack();
  static void print_times();
  static void print_last_compile();
  static void print_compiler_threads_on(outputStream* st);
  static const char* compiler_name(int comp_level);
  static int get_total_compile_count() {          return _total_compile_count; }
  static int get_total_bailout_count() {          return _total_bailout_count; }
  static int get_total_invalidated_count() {      return _total_invalidated_count; }
  static int get_total_native_compile_count() {   return _total_native_compile_count; }
  static int get_total_osr_compile_count() {      return _total_osr_compile_count; }
  static int get_total_standard_compile_count() { return _total_standard_compile_count; }
  static int get_sum_osr_bytes_compiled() {       return _sum_osr_bytes_compiled; }
  static int get_sum_standard_bytes_compiled() {  return _sum_standard_bytes_compiled; }
  static int get_sum_nmethod_size() {             return _sum_nmethod_size;}
  static int get_sum_nmethod_code_size() {        return _sum_nmethod_code_size; }
  static long get_peak_compilation_time() {       return _peak_compilation_time; }
  static long get_total_compilation_time() {      return _t_total_compilation.milliseconds(); }
};
#endif // SHARE_VM_COMPILER_COMPILEBROKER_HPP
C:\hotspot-69087d08d473\src\share\vm/compiler/compileLog.cpp
#include "precompiled.hpp"
#include "ci/ciMethod.hpp"
#include "compiler/compileLog.hpp"
#include "memory/allocation.inline.hpp"
#include "oops/method.hpp"
#include "runtime/mutexLocker.hpp"
#include "runtime/os.hpp"
CompileLog* CompileLog::_first = NULL;
CompileLog::CompileLog(const char* file_name, FILE* fp, intx thread_id)
  : _context(_context_buffer, sizeof(_context_buffer))
{
  initialize(new(ResourceObj::C_HEAP, mtCompiler) fileStream(fp, true));
  _file_end = 0;
  _thread_id = thread_id;
  _identities_limit = 0;
  _identities_capacity = 400;
  _identities = NEW_C_HEAP_ARRAY(char, _identities_capacity, mtCompiler);
  _file = NEW_C_HEAP_ARRAY(char, strlen(file_name)+1, mtCompiler);
   strcpy((char*)_file, file_name);
  { MutexLocker locker(CompileTaskAlloc_lock);
    _next = _first;
    _first = this;
  }
}
CompileLog::~CompileLog() {
  delete _out; // Close fd in fileStream::~fileStream()
  _out = NULL;
  unlink(_file);
  FREE_C_HEAP_ARRAY(char, _identities, mtCompiler);
  FREE_C_HEAP_ARRAY(char, _file, mtCompiler);
}
void CompileLog::see_tag(const char* tag, bool push) {
  if (_context.size() > 0 && _out != NULL) {
    _out->write(_context.base(), _context.size());
    _context.reset();
  }
  xmlStream::see_tag(tag, push);
}
void CompileLog::pop_tag(const char* tag) {
  _context.reset();  // toss any context info.
  xmlStream::pop_tag(tag);
}
int CompileLog::identify(ciBaseObject* obj) {
  if (obj == NULL)  return 0;
  int id = obj->ident();
  if (id < 0)  return id;
  if (id < _identities_limit && _identities[id] != 0)  return id;
  if (id >= _identities_capacity) {
    int new_cap = _identities_capacity * 2;
    if (new_cap <= id)  new_cap = id + 100;
    _identities = REALLOC_C_HEAP_ARRAY(char, _identities, new_cap, mtCompiler);
    _identities_capacity = new_cap;
  }
  while (id >= _identities_limit) {
    _identities[_identities_limit++] = 0;
  }
  assert(id < _identities_limit, "oob");
  _identities[id] = 1;  // mark
  if (obj->is_metadata()) {
    ciMetadata* mobj = obj->as_metadata();
    if (mobj->is_klass()) {
      ciKlass* klass = mobj->as_klass();
      begin_elem("klass id='%d'", id);
      name(klass->name());
      if (!klass->is_loaded()) {
        print(" unloaded='1'");
      } else {
        print(" flags='%d'", klass->modifier_flags());
      }
      end_elem();
    } else if (mobj->is_method()) {
      ciMethod* method = mobj->as_method();
      ciSignature* sig = method->signature();
      identify(sig->return_type());
      for (int i = 0; i < sig->count(); i++) {
        identify(sig->type_at(i));
      }
      begin_elem("method id='%d' holder='%d'",
          id, identify(method->holder()));
      name(method->name());
      print(" return='%d'", identify(sig->return_type()));
      if (sig->count() > 0) {
        print(" arguments='");
        for (int i = 0; i < sig->count(); i++) {
          print((i == 0) ? "%d" : " %d", identify(sig->type_at(i)));
        }
        print("'");
      }
      if (!method->is_loaded()) {
        print(" unloaded='1'");
      } else {
        print(" flags='%d'", (jchar) method->flags().as_int());
        print(" bytes='%d'", method->code_size());
        method->log_nmethod_identity(this);
        print(" iicount='%d'", method->interpreter_invocation_count());
      }
      end_elem();
    } else if (mobj->is_type()) {
      BasicType type = mobj->as_type()->basic_type();
      elem("type id='%d' name='%s'", id, type2name(type));
    } else {
      elem("unknown id='%d'", id);
      ShouldNotReachHere();
    }
  } else if (obj->is_symbol()) {
    begin_elem("symbol id='%d'", id);
    name(obj->as_symbol());
    end_elem();
  } else {
    elem("unknown id='%d'", id);
  }
  return id;
}
void CompileLog::name(ciSymbol* name) {
  if (name == NULL)  return;
  print(" name='");
  name->print_symbol_on(text());  // handles quoting conventions
  print("'");
}
void CompileLog::clear_identities() {
  _identities_limit = 0;
}
void CompileLog::finish_log_on_error(outputStream* file, char* buf, int buflen) {
  static bool called_exit = false;
  if (called_exit)  return;
  called_exit = true;
  CompileLog* log = _first;
  while (log != NULL) {
    log->flush();
    const char* partial_file = log->file();
    int partial_fd = open(partial_file, O_RDONLY);
    if (partial_fd != -1) {
      file->print_raw("<compilation_log thread='");
      jio_snprintf(buf, buflen, UINTX_FORMAT, log->thread_id());
      file->print_raw(buf);
      file->print_raw_cr("'>");
      size_t nr; // number read into buf from partial log
      julong to_read = log->_file_end;
      while (to_read > 0) {
        if (to_read < (julong)buflen)
              nr = (size_t)to_read;
        else  nr = buflen;
        nr = read(partial_fd, buf, (int)nr);
        if (nr <= 0)  break;
        to_read -= (julong)nr;
        file->write(buf, nr);
      }
      bool saw_slop = false;
      int end_cdata = 0;  // state machine [0..2] watching for too many "]]"
      while ((nr = read(partial_fd, buf, buflen)) > 0) {
        if (!saw_slop) {
          file->print_raw_cr("<fragment>");
          file->print_raw_cr("<![CDATA[");
          saw_slop = true;
        }
        const char* bufp;  // pointer into buf
        size_t nw; // number written in each pass of the following loop:
        for (bufp = buf; nr > 0; nr -= nw, bufp += nw) {
          for (nw = 0; nw < nr; nw++) {
            switch (bufp[nw]) {
            case ']':
              if (end_cdata < 2)   end_cdata += 1;  // saturating counter
              continue;  // keep scanning
            case '>':
              if (end_cdata == 2)  break;  // found CDATA delimiter!
            default:
              end_cdata = 0;
              continue;  // keep scanning
            }
            break;
          }
          file->write(bufp, nw);
          if (nw < nr) {
            file->print_raw("]]><![CDATA[");
            end_cdata = 0;  // reset state machine
          }
        }
      }
      if (saw_slop) {
        file->print_raw_cr("]]>");
        file->print_raw_cr("</fragment>");
      }
      file->print_raw_cr("</compilation_log>");
      close(partial_fd);
    }
    CompileLog* next_log = log->_next;
    delete log; // Removes partial file
    log = next_log;
  }
  _first = NULL;
}
void CompileLog::finish_log(outputStream* file) {
  char buf[4 * K];
  finish_log_on_error(file, buf, sizeof(buf));
}
void CompileLog::inline_success(const char* reason) {
  begin_elem("inline_success reason='");
  text("%s", reason);
  end_elem("'");
}
void CompileLog::inline_fail(const char* reason) {
  begin_elem("inline_fail reason='");
  text("%s", reason);
  end_elem("'");
}
void CompileLog::set_context(const char* format, ...) {
  va_list ap;
  va_start(ap, format);
  clear_context();
  _context.print("<");
  _context.vprint(format, ap);
  _context.print_cr("/>");
  va_end(ap);
}
void CompileLog::code_cache_state() {
  begin_elem("code_cache");
  CodeCache::log_state(this);
  end_elem("%s", "");
}
C:\hotspot-69087d08d473\src\share\vm/compiler/compileLog.hpp
#ifndef SHARE_VM_COMPILER_COMPILELOG_HPP
#define SHARE_VM_COMPILER_COMPILELOG_HPP
#include "utilities/xmlstream.hpp"
class ciBaseObject;
class ciObject;
class ciMetadata;
class ciSymbol;
class CompileLog : public xmlStream {
 private:
  const char*   _file;           // name of file where XML goes
  julong        _file_end;       // last good end of file
  intx          _thread_id;      // which compile thread
  stringStream  _context;        // optional, killable context marker
  char          _context_buffer[100];
  char*         _identities;     // array of boolean
  int           _identities_limit;
  int           _identities_capacity;
  CompileLog*   _next;           // static chain of all logs
  static CompileLog* _first;     // head of static chain
  void va_tag(bool push, const char* format, va_list ap) ATTRIBUTE_PRINTF(3, 0);
 public:
  CompileLog(const char* file_name, FILE* fp, intx thread_id);
  ~CompileLog();
  intx          thread_id()                      { return _thread_id; }
  const char*   file()                           { return _file; }
  stringStream* context()                        { return &_context; }
  void    clear_context()                        { context()->reset(); }
  void      set_context(const char* format, ...) ATTRIBUTE_PRINTF(2, 3);
  void          name(ciSymbol* s);               // name='s'
  void          name(Symbol* s)                  { xmlStream::name(s); }
  int           identify(ciBaseObject* obj);
  void          clear_identities();
  void inline_fail   (const char* reason);
  void inline_success(const char* reason);
  virtual void see_tag(const char* tag, bool push);
  virtual void pop_tag(const char* tag);
  void mark_file_end() { _file_end = out()->count(); }
  void code_cache_state();
  static void finish_log(outputStream* out);
  static void finish_log_on_error(outputStream* out, char *buf, int buflen);
};
#endif // SHARE_VM_COMPILER_COMPILELOG_HPP
C:\hotspot-69087d08d473\src\share\vm/compiler/compilerOracle.cpp
#include "precompiled.hpp"
#include "compiler/compilerOracle.hpp"
#include "memory/allocation.inline.hpp"
#include "memory/oopFactory.hpp"
#include "memory/resourceArea.hpp"
#include "oops/klass.hpp"
#include "oops/method.hpp"
#include "oops/oop.inline.hpp"
#include "oops/symbol.hpp"
#include "runtime/handles.inline.hpp"
#include "runtime/jniHandles.hpp"
class MethodMatcher : public CHeapObj<mtCompiler> {
 public:
  enum Mode {
    Exact,
    Prefix = 1,
    Suffix = 2,
    Substring = Prefix | Suffix,
    Any,
    Unknown = -1
  };
 protected:
  Symbol*        _class_name;
  Symbol*        _method_name;
  Symbol*        _signature;
  Mode           _class_mode;
  Mode           _method_mode;
  MethodMatcher* _next;
  static bool match(Symbol* candidate, Symbol* match, Mode match_mode);
  Symbol* class_name() const { return _class_name; }
  Symbol* method_name() const { return _method_name; }
  Symbol* signature() const { return _signature; }
 public:
  MethodMatcher(Symbol* class_name, Mode class_mode,
                Symbol* method_name, Mode method_mode,
                Symbol* signature, MethodMatcher* next);
  MethodMatcher(Symbol* class_name, Symbol* method_name, MethodMatcher* next);
  MethodMatcher* find(methodHandle method) {
    Symbol* class_name  = method->method_holder()->name();
    Symbol* method_name = method->name();
    for (MethodMatcher* current = this; current != NULL; current = current->_next) {
      if (match(class_name, current->class_name(), current->_class_mode) &&
          match(method_name, current->method_name(), current->_method_mode) &&
          (current->signature() == NULL || current->signature() == method->signature())) {
        return current;
      }
    }
    return NULL;
  }
  bool match(methodHandle method) {
    return find(method) != NULL;
  }
  MethodMatcher* next() const { return _next; }
  static void print_symbol(Symbol* h, Mode mode) {
    ResourceMark rm;
    if (mode == Suffix || mode == Substring || mode == Any) {
      tty->print("*");
    }
    if (mode != Any) {
      h->print_symbol_on(tty);
    }
    if (mode == Prefix || mode == Substring) {
      tty->print("*");
    }
  }
  void print_base() {
    print_symbol(class_name(), _class_mode);
    tty->print(".");
    print_symbol(method_name(), _method_mode);
    if (signature() != NULL) {
      tty->print(" ");
      signature()->print_symbol_on(tty);
    }
  }
  virtual void print() {
    print_base();
    tty->cr();
  }
};
MethodMatcher::MethodMatcher(Symbol* class_name, Symbol* method_name, MethodMatcher* next) {
  _class_name  = class_name;
  _method_name = method_name;
  _next        = next;
  _class_mode  = MethodMatcher::Exact;
  _method_mode = MethodMatcher::Exact;
  _signature   = NULL;
}
MethodMatcher::MethodMatcher(Symbol* class_name, Mode class_mode,
                             Symbol* method_name, Mode method_mode,
                             Symbol* signature, MethodMatcher* next):
    _class_mode(class_mode)
  , _method_mode(method_mode)
  , _next(next)
  , _class_name(class_name)
  , _method_name(method_name)
  , _signature(signature) {
}
bool MethodMatcher::match(Symbol* candidate, Symbol* match, Mode match_mode) {
  if (match_mode == Any) {
    return true;
  }
  if (match_mode == Exact) {
    return candidate == match;
  }
  ResourceMark rm;
  const char * candidate_string = candidate->as_C_string();
  const char * match_string = match->as_C_string();
  switch (match_mode) {
  case Prefix:
    return strstr(candidate_string, match_string) == candidate_string;
  case Suffix: {
    size_t clen = strlen(candidate_string);
    size_t mlen = strlen(match_string);
    return clen >= mlen && strcmp(candidate_string + clen - mlen, match_string) == 0;
  }
  case Substring:
    return strstr(candidate_string, match_string) != NULL;
  default:
    return false;
  }
}
enum OptionType {
  IntxType,
  UintxType,
  BoolType,
  CcstrType,
  UnknownType
};
template<typename T>
static OptionType get_type_for() {
  return UnknownType;
};
template<> OptionType get_type_for<intx>() {
  return IntxType;
}
template<> OptionType get_type_for<uintx>() {
  return UintxType;
}
template<> OptionType get_type_for<bool>() {
  return BoolType;
}
template<> OptionType get_type_for<ccstr>() {
  return CcstrType;
}
template<typename T>
static const T copy_value(const T value) {
  return value;
}
template<> const ccstr copy_value<ccstr>(const ccstr value) {
  return (const ccstr)strdup(value);
}
template <typename T>
class TypedMethodOptionMatcher : public MethodMatcher {
  const char* _option;
  OptionType _type;
  const T _value;
public:
  TypedMethodOptionMatcher(Symbol* class_name, Mode class_mode,
                           Symbol* method_name, Mode method_mode,
                           Symbol* signature, const char* opt,
                           const T value,  MethodMatcher* next) :
    MethodMatcher(class_name, class_mode, method_name, method_mode, signature, next),
                  _type(get_type_for<T>()), _value(copy_value<T>(value)) {
    _option = strdup(opt);
  }
  ~TypedMethodOptionMatcher() {
    free((void*)_option);
  }
  TypedMethodOptionMatcher* match(methodHandle method, const char* opt) {
    TypedMethodOptionMatcher* current = this;
    while (current != NULL) {
      current = (TypedMethodOptionMatcher*)current->find(method);
      if (current == NULL) {
        return NULL;
      }
      if (strcmp(current->_option, opt) == 0) {
        return current;
      }
      current = current->next();
    }
    return NULL;
  }
  TypedMethodOptionMatcher* next() {
    return (TypedMethodOptionMatcher*)_next;
  }
  OptionType get_type(void) {
      return _type;
  };
  T value() { return _value; }
  void print() {
    ttyLocker ttyl;
    print_base();
    tty->print(" %s", _option);
    tty->print(" <unknown option type>");
    tty->cr();
  }
};
template<>
void TypedMethodOptionMatcher<intx>::print() {
  ttyLocker ttyl;
  print_base();
  tty->print(" intx %s", _option);
  tty->print(" = " INTX_FORMAT, _value);
  tty->cr();
};
template<>
void TypedMethodOptionMatcher<uintx>::print() {
  ttyLocker ttyl;
  print_base();
  tty->print(" uintx %s", _option);
  tty->print(" = " UINTX_FORMAT, _value);
  tty->cr();
};
template<>
void TypedMethodOptionMatcher<bool>::print() {
  ttyLocker ttyl;
  print_base();
  tty->print(" bool %s", _option);
  tty->print(" = %s", _value ? "true" : "false");
  tty->cr();
};
template<>
void TypedMethodOptionMatcher<ccstr>::print() {
  ttyLocker ttyl;
  print_base();
  tty->print(" const char* %s", _option);
  tty->print(" = '%s'", _value);
  tty->cr();
};
enum OracleCommand {
  UnknownCommand = -1,
  OracleFirstCommand = 0,
  BreakCommand = OracleFirstCommand,
  PrintCommand,
  ExcludeCommand,
  InlineCommand,
  DontInlineCommand,
  CompileOnlyCommand,
  LogCommand,
  OptionCommand,
  QuietCommand,
  HelpCommand,
  OracleCommandCount
};
static const char * command_names[] = {
  "break",
  "print",
  "exclude",
  "inline",
  "dontinline",
  "compileonly",
  "log",
  "option",
  "quiet",
  "help"
};
class MethodMatcher;
static MethodMatcher* lists[OracleCommandCount] = { 0, };
static bool check_predicate(OracleCommand command, methodHandle method) {
  return ((lists[command] != NULL) &&
          !method.is_null() &&
          lists[command]->match(method));
}
static MethodMatcher* add_predicate(OracleCommand command,
                                    Symbol* class_name, MethodMatcher::Mode c_mode,
                                    Symbol* method_name, MethodMatcher::Mode m_mode,
                                    Symbol* signature) {
  assert(command != OptionCommand, "must use add_option_string");
  if (command == LogCommand && !LogCompilation && lists[LogCommand] == NULL)
    tty->print_cr("Warning:  +LogCompilation must be enabled in order for individual methods to be logged.");
  lists[command] = new MethodMatcher(class_name, c_mode, method_name, m_mode, signature, lists[command]);
  return lists[command];
}
template<typename T>
static MethodMatcher* add_option_string(Symbol* class_name, MethodMatcher::Mode c_mode,
                                        Symbol* method_name, MethodMatcher::Mode m_mode,
                                        Symbol* signature,
                                        const char* option,
                                        T value) {
  lists[OptionCommand] = new TypedMethodOptionMatcher<T>(class_name, c_mode, method_name, m_mode,
                                                         signature, option, value, lists[OptionCommand]);
  return lists[OptionCommand];
}
template<typename T>
static bool get_option_value(methodHandle method, const char* option, T& value) {
   TypedMethodOptionMatcher<T>* m;
   if (lists[OptionCommand] != NULL
       && (m = ((TypedMethodOptionMatcher<T>*)lists[OptionCommand])->match(method, option)) != NULL
       && m->get_type() == get_type_for<T>()) {
       value = m->value();
       return true;
   } else {
     return false;
   }
}
bool CompilerOracle::has_option_string(methodHandle method, const char* option) {
  bool value = false;
  get_option_value(method, option, value);
  return value;
}
template<typename T>
bool CompilerOracle::has_option_value(methodHandle method, const char* option, T& value) {
  return ::get_option_value(method, option, value);
}
template bool CompilerOracle::has_option_value<intx>(methodHandle method, const char* option, intx& value);
template bool CompilerOracle::has_option_value<uintx>(methodHandle method, const char* option, uintx& value);
template bool CompilerOracle::has_option_value<bool>(methodHandle method, const char* option, bool& value);
template bool CompilerOracle::has_option_value<ccstr>(methodHandle method, const char* option, ccstr& value);
bool CompilerOracle::should_exclude(methodHandle method, bool& quietly) {
  quietly = true;
  if (lists[ExcludeCommand] != NULL) {
    if (lists[ExcludeCommand]->match(method)) {
      quietly = _quiet;
      return true;
    }
  }
  if (lists[CompileOnlyCommand] != NULL) {
    return !lists[CompileOnlyCommand]->match(method);
  }
  return false;
}
bool CompilerOracle::should_inline(methodHandle method) {
  return (check_predicate(InlineCommand, method));
}
bool CompilerOracle::should_not_inline(methodHandle method) {
  return (check_predicate(DontInlineCommand, method));
}
bool CompilerOracle::should_print(methodHandle method) {
  return (check_predicate(PrintCommand, method));
}
bool CompilerOracle::should_log(methodHandle method) {
  if (!LogCompilation)            return false;
  if (lists[LogCommand] == NULL)  return true;  // by default, log all
  return (check_predicate(LogCommand, method));
}
bool CompilerOracle::should_break_at(methodHandle method) {
  return check_predicate(BreakCommand, method);
}
static OracleCommand parse_command_name(const char * line, int* bytes_read) {
  assert(ARRAY_SIZE(command_names) == OracleCommandCount,
         "command_names size mismatch");
  char command[33];
  int result = sscanf(line, "%32[a-z]%n", command, bytes_read);
  for (uint i = 0; i < ARRAY_SIZE(command_names); i++) {
    if (strcmp(command, command_names[i]) == 0) {
      return (OracleCommand)i;
    }
  }
  return UnknownCommand;
}
static void usage() {
  tty->print_cr("  CompileCommand and the CompilerOracle allows simple control over");
  tty->print_cr("  what's allowed to be compiled.  The standard supported directives");
  tty->print_cr("  are exclude and compileonly.  The exclude directive stops a method");
  tty->print_cr("  from being compiled and compileonly excludes all methods except for");
  tty->print_cr("  the ones mentioned by compileonly directives.  The basic form of");
  tty->print_cr("  all commands is a command name followed by the name of the method");
  tty->print_cr("  in one of two forms: the standard class file format as in");
  tty->print_cr("  class/name.methodName or the PrintCompilation format");
  tty->print_cr("  class.name::methodName.  The method name can optionally be followed");
  tty->print_cr("  by a space then the signature of the method in the class file");
  tty->print_cr("  format.  Otherwise the directive applies to all methods with the");
  tty->print_cr("  same name and class regardless of signature.  Leading and trailing");
  tty->print_cr("  *'s in the class and/or method name allows a small amount of");
  tty->print_cr("  wildcarding.  ");
  tty->cr();
  tty->print_cr("  Examples:");
  tty->cr();
  tty->print_cr("  exclude java/lang/StringBuffer.append");
  tty->print_cr("  compileonly java/lang/StringBuffer.toString ()Ljava/lang/String;");
  tty->print_cr("  exclude java/lang/String*.*");
  tty->print_cr("  exclude *.toString");
}
#define RANGEBASE "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789$_<>" \
        "\x80\x81\x82\x83\x84\x85\x86\x87\x88\x89\x8a\x8b\x8c\x8d\x8e\x8f" \
        "\x90\x91\x92\x93\x94\x95\x96\x97\x98\x99\x9a\x9b\x9c\x9d\x9e\x9f" \
        "\xa0\xa1\xa2\xa3\xa4\xa5\xa6\xa7\xa8\xa9\xaa\xab\xac\xad\xae\xaf" \
        "\xb0\xb1\xb2\xb3\xb4\xb5\xb6\xb7\xb8\xb9\xba\xbb\xbc\xbd\xbe\xbf" \
        "\xc0\xc1\xc2\xc3\xc4\xc5\xc6\xc7\xc8\xc9\xca\xcb\xcc\xcd\xce\xcf" \
        "\xd0\xd1\xd2\xd3\xd4\xd5\xd6\xd7\xd8\xd9\xda\xdb\xdc\xdd\xde\xdf" \
        "\xe0\xe1\xe2\xe3\xe4\xe5\xe6\xe7\xe8\xe9\xea\xeb\xec\xed\xee\xef" \
        "\xf0\xf1\xf2\xf3\xf4\xf5\xf6\xf7\xf8\xf9\xfa\xfb\xfc\xfd\xfe\xff"
#define RANGE0 "[*" RANGEBASE "]"
#define RANGESLASH "[*" RANGEBASE "/]"
static MethodMatcher::Mode check_mode(char name[], const char*& error_msg) {
  int match = MethodMatcher::Exact;
  while (name[0] == '*') {
    match |= MethodMatcher::Suffix;
    strcpy(name, name + 1);
  }
  if (strcmp(name, "*") == 0) return MethodMatcher::Any;
  size_t len = strlen(name);
  while (len > 0 && name[len - 1] == '*') {
    match |= MethodMatcher::Prefix;
    name[--len] = '\0';
  }
  if (strstr(name, "*") != NULL) {
    error_msg = "  Embedded * not allowed";
    return MethodMatcher::Unknown;
  }
  return (MethodMatcher::Mode)match;
}
static bool scan_line(const char * line,
                      char class_name[],  MethodMatcher::Mode* c_mode,
                      char method_name[], MethodMatcher::Mode* m_mode,
                      int* bytes_read, const char*& error_msg) {
  error_msg = NULL;
  if (2 == sscanf(line, "%*[ \t]%255" RANGESLASH "%*[ ]" "%255"  RANGE0 "%n", class_name, method_name, bytes_read)) {
    return *c_mode != MethodMatcher::Unknown && *m_mode != MethodMatcher::Unknown;
  }
  return false;
}
static MethodMatcher* scan_flag_and_value(const char* type, const char* line, int& total_bytes_read,
                                          Symbol* c_name, MethodMatcher::Mode c_match,
                                          Symbol* m_name, MethodMatcher::Mode m_match,
                                          Symbol* signature,
                                          char* errorbuf, const int buf_size) {
  total_bytes_read = 0;
  int bytes_read = 0;
  char flag[256];
  if (sscanf(line, "%*[ \t]%255[a-zA-Z0-9]%n", flag, &bytes_read) == 1) {
    line += bytes_read;
    total_bytes_read += bytes_read;
    if (strcmp(type, "intx") == 0) {
      intx value;
      if (sscanf(line, "%*[ \t]" INTX_FORMAT "%n", &value, &bytes_read) == 1) {
        total_bytes_read += bytes_read;
        return add_option_string(c_name, c_match, m_name, m_match, signature, flag, value);
      } else {
        jio_snprintf(errorbuf, buf_size, "  Value cannot be read for flag %s of type %s ", flag, type);
      }
    } else if (strcmp(type, "uintx") == 0) {
      uintx value;
      if (sscanf(line, "%*[ \t]" UINTX_FORMAT "%n", &value, &bytes_read) == 1) {
        total_bytes_read += bytes_read;
        return add_option_string(c_name, c_match, m_name, m_match, signature, flag, value);
      } else {
        jio_snprintf(errorbuf, buf_size, "  Value cannot be read for flag %s of type %s", flag, type);
      }
    } else if (strcmp(type, "ccstr") == 0) {
      ResourceMark rm;
      char* value = NEW_RESOURCE_ARRAY(char, strlen(line) + 1);
      if (sscanf(line, "%*[ \t]%255[_a-zA-Z0-9]%n", value, &bytes_read) == 1) {
        total_bytes_read += bytes_read;
        return add_option_string(c_name, c_match, m_name, m_match, signature, flag, (ccstr)value);
      } else {
        jio_snprintf(errorbuf, buf_size, "  Value cannot be read for flag %s of type %s", flag, type);
      }
    } else if (strcmp(type, "ccstrlist") == 0) {
      ResourceMark rm;
      char* value = NEW_RESOURCE_ARRAY(char, strlen(line) + 1);
      char* next_value = value;
      if (sscanf(line, "%*[ \t]%255[_a-zA-Z0-9]%n", next_value, &bytes_read) == 1) {
        total_bytes_read += bytes_read;
        line += bytes_read;
        next_value += bytes_read;
        char* end_value = next_value-1;
        while (sscanf(line, "%*[ \t]%255[_a-zA-Z0-9]%n", next_value, &bytes_read) == 1) {
          total_bytes_read += bytes_read;
          line += bytes_read;
          next_value += bytes_read;
          end_value = next_value-1;
        }
        return add_option_string(c_name, c_match, m_name, m_match, signature, flag, (ccstr)value);
      } else {
        jio_snprintf(errorbuf, buf_size, "  Value cannot be read for flag %s of type %s", flag, type);
      }
    } else if (strcmp(type, "bool") == 0) {
      char value[256];
      if (sscanf(line, "%*[ \t]%255[a-zA-Z]%n", value, &bytes_read) == 1) {
        if (strcmp(value, "true") == 0) {
          total_bytes_read += bytes_read;
          return add_option_string(c_name, c_match, m_name, m_match, signature, flag, true);
        } else if (strcmp(value, "false") == 0) {
          total_bytes_read += bytes_read;
          return add_option_string(c_name, c_match, m_name, m_match, signature, flag, false);
        } else {
          jio_snprintf(errorbuf, buf_size, "  Value cannot be read for flag %s of type %s", flag, type);
        }
      } else {
        jio_snprintf(errorbuf, sizeof(errorbuf), "  Value cannot be read for flag %s of type %s", flag, type);
      }
    } else {
      jio_snprintf(errorbuf, sizeof(errorbuf), "  Type %s not supported ", type);
    }
  } else {
    jio_snprintf(errorbuf, sizeof(errorbuf), "  Flag name for type %s should be alphanumeric ", type);
  }
  return NULL;
}
void CompilerOracle::parse_from_line(char* line) {
  if (line[0] == '\0') return;
  if (line[0] == '#')  return;
  bool have_colon = (strstr(line, "::") != NULL);
  for (char* lp = line; *lp != '\0'; lp++) {
    if (have_colon) {
      if (*lp == '.')  *lp = '/';   // dots build the package prefix
      if (*lp == ':')  *lp = ' ';
    }
    if (*lp == ',' || *lp == '.')  *lp = ' ';
  }
  char* original_line = line;
  int bytes_read;
  OracleCommand command = parse_command_name(line, &bytes_read);
  line += bytes_read;
  ResourceMark rm;
  if (command == UnknownCommand) {
    ttyLocker ttyl;
    tty->print_cr("CompilerOracle: unrecognized line");
    tty->print_cr("  \"%s\"", original_line);
    return;
  }
  if (command == QuietCommand) {
    _quiet = true;
    return;
  }
  if (command == HelpCommand) {
    usage();
    return;
  }
  MethodMatcher::Mode c_match = MethodMatcher::Exact;
  MethodMatcher::Mode m_match = MethodMatcher::Exact;
  char class_name[256];
  char method_name[256];
  char sig[1024];
  char errorbuf[1024];
  const char* error_msg = NULL; // description of first error that appears
  MethodMatcher* match = NULL;
  if (scan_line(line, class_name, &c_match, method_name, &m_match, &bytes_read, error_msg)) {
    EXCEPTION_MARK;
    Symbol* c_name = SymbolTable::new_symbol(class_name, CHECK);
    Symbol* m_name = SymbolTable::new_symbol(method_name, CHECK);
    Symbol* signature = NULL;
    line += bytes_read;
    if (1 == sscanf(line, "%*[ \t](%254[[);/" RANGEBASE "]%n", sig + 1, &bytes_read)) {
      sig[0] = '(';
      line += bytes_read;
      signature = SymbolTable::new_symbol(sig, CHECK);
    }
    if (command == OptionCommand) {
      char option[256]; // stores flag for Type (1) and type of Type (2)
      while (sscanf(line, "%*[ \t]%255[a-zA-Z0-9]%n", option, &bytes_read) == 1) {
        if (match != NULL && !_quiet) {
          ttyLocker ttyl;
          tty->print("CompilerOracle: %s ", command_names[command]);
          match->print();
        }
        line += bytes_read;
        if (strcmp(option, "intx") == 0
            || strcmp(option, "uintx") == 0
            || strcmp(option, "bool") == 0
            || strcmp(option, "ccstr") == 0
            || strcmp(option, "ccstrlist") == 0
            ) {
          match = scan_flag_and_value(option, line, bytes_read,
                                      c_name, c_match, m_name, m_match, signature,
                                      errorbuf, sizeof(errorbuf));
          if (match == NULL) {
            error_msg = errorbuf;
            break;
          }
          line += bytes_read;
        } else {
          match = add_option_string(c_name, c_match, m_name, m_match, signature, option, true);
        }
      } // while(
    } else {
      match = add_predicate(command, c_name, c_match, m_name, m_match, signature);
    }
  }
  ttyLocker ttyl;
  if (error_msg != NULL) {
    tty->print_cr("CompilerOracle: unrecognized line");
    tty->print_cr("  \"%s\"", original_line);
    if (error_msg != NULL) {
      tty->print_cr("%s", error_msg);
    }
  } else {
    bytes_read = 0;
    sscanf(line, "%*[ \t]%n", &bytes_read);
    if (line[bytes_read] != '\0') {
      tty->print_cr("CompilerOracle: unrecognized line");
      tty->print_cr("  \"%s\"", original_line);
      tty->print_cr("  Unrecognized text %s after command ", line);
    } else if (match != NULL && !_quiet) {
      tty->print("CompilerOracle: %s ", command_names[command]);
      match->print();
    }
  }
}
static const char* default_cc_file = ".hotspot_compiler";
static const char* cc_file() {
#ifdef ASSERT
  if (CompileCommandFile == NULL)
    return default_cc_file;
#endif
  return CompileCommandFile;
}
bool CompilerOracle::has_command_file() {
  return cc_file() != NULL;
}
bool CompilerOracle::_quiet = false;
void CompilerOracle::parse_from_file() {
  assert(has_command_file(), "command file must be specified");
  FILE* stream = fopen(cc_file(), "rt");
  if (stream == NULL) return;
  char token[1024];
  int  pos = 0;
  int  c = getc(stream);
  while(c != EOF && pos < (int)(sizeof(token)-1)) {
    if (c == '\n') {
      token[pos++] = '\0';
      parse_from_line(token);
      pos = 0;
    } else {
      token[pos++] = c;
    }
    c = getc(stream);
  }
  token[pos++] = '\0';
  parse_from_line(token);
  fclose(stream);
}
void CompilerOracle::parse_from_string(const char* str, void (*parse_line)(char*)) {
  char token[1024];
  int  pos = 0;
  const char* sp = str;
  int  c = *sp++;
  while (c != '\0' && pos < (int)(sizeof(token)-1)) {
    if (c == '\n') {
      token[pos++] = '\0';
      parse_line(token);
      pos = 0;
    } else {
      token[pos++] = c;
    }
    c = *sp++;
  }
  token[pos++] = '\0';
  parse_line(token);
}
void CompilerOracle::append_comment_to_file(const char* message) {
  assert(has_command_file(), "command file must be specified");
  fileStream stream(fopen(cc_file(), "at"));
  stream.print("# ");
  for (int index = 0; message[index] != '\0'; index++) {
    stream.put(message[index]);
    if (message[index] == '\n') stream.print("# ");
  }
  stream.cr();
}
void CompilerOracle::append_exclude_to_file(methodHandle method) {
  assert(has_command_file(), "command file must be specified");
  fileStream stream(fopen(cc_file(), "at"));
  stream.print("exclude ");
  method->method_holder()->name()->print_symbol_on(&stream);
  stream.print(".");
  method->name()->print_symbol_on(&stream);
  method->signature()->print_symbol_on(&stream);
  stream.cr();
  stream.cr();
}
void compilerOracle_init() {
  CompilerOracle::parse_from_string(CompileCommand, CompilerOracle::parse_from_line);
  CompilerOracle::parse_from_string(CompileOnly, CompilerOracle::parse_compile_only);
  if (CompilerOracle::has_command_file()) {
    CompilerOracle::parse_from_file();
  } else {
    struct stat buf;
    if (os::stat(default_cc_file, &buf) == 0) {
      warning("%s file is present but has been ignored.  "
              "Run with -XX:CompileCommandFile=%s to load the file.",
              default_cc_file, default_cc_file);
    }
  }
  if (lists[PrintCommand] != NULL) {
    if (PrintAssembly) {
      warning("CompileCommand and/or %s file contains 'print' commands, but PrintAssembly is also enabled", default_cc_file);
    } else if (FLAG_IS_DEFAULT(DebugNonSafepoints)) {
      warning("printing of assembly code is enabled; turning on DebugNonSafepoints to gain additional output");
      DebugNonSafepoints = true;
    }
  }
}
void CompilerOracle::parse_compile_only(char * line) {
  int i;
  char name[1024];
  const char* className = NULL;
  const char* methodName = NULL;
  bool have_colon = (strstr(line, "::") != NULL);
  char method_sep = have_colon ? ':' : '.';
  if (Verbose) {
    tty->print_cr("%s", line);
  }
  ResourceMark rm;
  while (*line != '\0') {
    MethodMatcher::Mode c_match = MethodMatcher::Exact;
    MethodMatcher::Mode m_match = MethodMatcher::Exact;
    for (i = 0;
         i < 1024 && *line != '\0' && *line != method_sep && *line != ',' && !isspace(*line);
         line++, i++) {
      name[i] = *line;
      if (name[i] == '.')  name[i] = '/';  // package prefix uses '/'
    }
    if (i > 0) {
      char* newName = NEW_RESOURCE_ARRAY( char, i + 1);
      if (newName == NULL)
        return;
      strncpy(newName, name, i);
      newName[i] = '\0';
      if (className == NULL) {
        className = newName;
        c_match = MethodMatcher::Prefix;
      } else {
        methodName = newName;
      }
    }
    if (*line == method_sep) {
      if (className == NULL) {
        className = "";
        c_match = MethodMatcher::Any;
      } else {
        if (strchr(className, '/') != NULL) {
          c_match = MethodMatcher::Exact;
        } else {
          c_match = MethodMatcher::Suffix;
        }
      }
    } else {
      if (className == NULL) {
        ShouldNotReachHere();
      } else {
        if (strchr(className, '/') != NULL) {
          c_match = MethodMatcher::Prefix;
        } else if (className[0] == '\0') {
          c_match = MethodMatcher::Any;
        } else {
          c_match = MethodMatcher::Substring;
        }
      }
    }
    if (*line == ',' || *line == '\0' || (line[0] == '.' && line[1] == '\0')) {
      if (methodName == NULL) {
        methodName = "";
        if (*line != method_sep) {
          m_match = MethodMatcher::Any;
        }
      }
      EXCEPTION_MARK;
      Symbol* c_name = SymbolTable::new_symbol(className, CHECK);
      Symbol* m_name = SymbolTable::new_symbol(methodName, CHECK);
      Symbol* signature = NULL;
      add_predicate(CompileOnlyCommand, c_name, c_match, m_name, m_match, signature);
      if (PrintVMOptions) {
        tty->print("CompileOnly: compileonly ");
        lists[CompileOnlyCommand]->print();
      }
      className = NULL;
      methodName = NULL;
    }
    line = *line == '\0' ? line : line + 1;
  }
}
C:\hotspot-69087d08d473\src\share\vm/compiler/compilerOracle.hpp
#ifndef SHARE_VM_COMPILER_COMPILERORACLE_HPP
#define SHARE_VM_COMPILER_COMPILERORACLE_HPP
#include "memory/allocation.hpp"
#include "oops/oopsHierarchy.hpp"
class CompilerOracle : AllStatic {
 private:
  static bool _quiet;
 public:
  static bool has_command_file();
  static void parse_from_file();
  static bool should_exclude(methodHandle method, bool& quietly);
  static bool should_inline(methodHandle method);
  static bool should_not_inline(methodHandle method);
  static bool should_print(methodHandle method);
  static bool should_log(methodHandle method);
  static bool should_break_at(methodHandle method);
  static bool has_option_string(methodHandle method, const char * option);
  template<typename T>
  static bool has_option_value(methodHandle method, const char* option, T& value);
  static void parse_from_string(const char* command_string, void (*parser)(char*));
  static void parse_from_line(char* line);
  static void parse_compile_only(char * line);
  static void append_comment_to_file(const char* message);
  static void append_exclude_to_file(methodHandle method);
};
#endif // SHARE_VM_COMPILER_COMPILERORACLE_HPP
C:\hotspot-69087d08d473\src\share\vm/compiler/disassembler.cpp
#include "precompiled.hpp"
#include "classfile/javaClasses.hpp"
#include "code/codeCache.hpp"
#include "compiler/disassembler.hpp"
#include "gc_interface/collectedHeap.hpp"
#include "memory/cardTableModRefBS.hpp"
#include "runtime/fprofiler.hpp"
#include "runtime/handles.inline.hpp"
#include "runtime/stubCodeGenerator.hpp"
#include "runtime/stubRoutines.hpp"
#ifdef TARGET_ARCH_x86
# include "depChecker_x86.hpp"
#endif
#ifdef TARGET_ARCH_aarch64
# include "depChecker_aarch64.hpp"
#endif
#ifdef TARGET_ARCH_sparc
# include "depChecker_sparc.hpp"
#endif
#ifdef TARGET_ARCH_zero
# include "depChecker_zero.hpp"
#endif
#ifdef TARGET_ARCH_arm
# include "depChecker_arm.hpp"
#endif
#ifdef TARGET_ARCH_ppc
# include "depChecker_ppc.hpp"
#endif
#ifdef SHARK
#include "shark/sharkEntry.hpp"
#endif
PRAGMA_FORMAT_MUTE_WARNINGS_FOR_GCC
void*       Disassembler::_library               = NULL;
bool        Disassembler::_tried_to_load_library = false;
Disassembler::decode_func_virtual Disassembler::_decode_instructions_virtual = NULL;
Disassembler::decode_func Disassembler::_decode_instructions = NULL;
static const char hsdis_library_name[] = "hsdis-" HOTSPOT_LIB_ARCH;
static const char decode_instructions_virtual_name[] = "decode_instructions_virtual";
static const char decode_instructions_name[] = "decode_instructions";
static bool use_new_version = true;
#define COMMENT_COLUMN  40 LP64_ONLY(+8) /*could be an option*/
#define BYTES_COMMENT   ";..."  /* funky byte display comment */
bool Disassembler::load_library() {
  if (_decode_instructions_virtual != NULL || _decode_instructions != NULL) {
    return true;
  }
  if (_tried_to_load_library) {
    return false;
  }
  char ebuf[1024];
  char buf[JVM_MAXPATHLEN];
  os::jvm_path(buf, sizeof(buf));
  int jvm_offset = -1;
  int lib_offset = -1;
  {
    const char* base = buf;
    const char* p = strrchr(buf, *os::file_separator());
    if (p != NULL) lib_offset = p - base + 1;
    p = strstr(p ? p : base, "jvm");
    if (p != NULL)  jvm_offset = p - base;
  }
  if (jvm_offset >= 0) {
    strcpy(&buf[jvm_offset], hsdis_library_name);
    strcat(&buf[jvm_offset], os::dll_file_extension());
    _library = os::dll_load(buf, ebuf, sizeof ebuf);
    if (_library == NULL) {
      strcpy(&buf[lib_offset], hsdis_library_name);
      strcat(&buf[lib_offset], os::dll_file_extension());
      _library = os::dll_load(buf, ebuf, sizeof ebuf);
    }
    if (_library == NULL) {
      buf[lib_offset - 1] = '\0';
      const char* p = strrchr(buf, *os::file_separator());
      if (p != NULL) {
        lib_offset = p - buf + 1;
        strcpy(&buf[lib_offset], hsdis_library_name);
        strcat(&buf[lib_offset], os::dll_file_extension());
        _library = os::dll_load(buf, ebuf, sizeof ebuf);
      }
    }
  }
  if (_library == NULL) {
    strcpy(&buf[0], hsdis_library_name);
    strcat(&buf[0], os::dll_file_extension());
    _library = os::dll_load(buf, ebuf, sizeof ebuf);
  }
  if (_library != NULL) {
    _decode_instructions_virtual = CAST_TO_FN_PTR(Disassembler::decode_func_virtual,
                                          os::dll_lookup(_library, decode_instructions_virtual_name));
  }
  if (_decode_instructions_virtual == NULL) {
    _decode_instructions = CAST_TO_FN_PTR(Disassembler::decode_func,
                                          os::dll_lookup(_library, decode_instructions_name));
    use_new_version = false;
  } else {
    use_new_version = true;
  }
  _tried_to_load_library = true;
  if (_decode_instructions_virtual == NULL && _decode_instructions == NULL) {
    tty->print_cr("Could not load %s; %s; %s", buf,
                  ((_library != NULL)
                   ? "entry point is missing"
                   : (WizardMode || PrintMiscellaneous)
                   ? (const char*)ebuf
                   : "library not loadable"),
                  "PrintAssembly is disabled");
    return false;
  }
  tty->print_cr("Loaded disassembler from %s", buf);
  return true;
}
class decode_env {
 private:
  nmethod*      _nm;
  CodeBlob*     _code;
  CodeStrings   _strings;
  outputStream* _output;
  address       _start, _end;
  char          _option_buf[512];
  char          _print_raw;
  bool          _print_pc;
  bool          _print_bytes;
  address       _cur_insn;
  int           _total_ticks;
  int           _bytes_per_line; // arch-specific formatting option
  static bool match(const char* event, const char* tag) {
    size_t taglen = strlen(tag);
    if (strncmp(event, tag, taglen) != 0)
      return false;
    char delim = event[taglen];
    return delim == '\0' || delim == ' ' || delim == '/' || delim == '=';
  }
  void collect_options(const char* p) {
    if (p == NULL || p[0] == '\0')  return;
    size_t opt_so_far = strlen(_option_buf);
    if (opt_so_far + 1 + strlen(p) + 1 > sizeof(_option_buf))  return;
    char* fillp = &_option_buf[opt_so_far];
    if (opt_so_far > 0) *fillp++ = ',';
    strcat(fillp, p);
    char* q = fillp;
    while ((q = strpbrk(q, " \t\n")) != NULL)
  }
  void print_insn_labels();
  void print_insn_bytes(address pc0, address pc);
  void print_address(address value);
 public:
  decode_env(CodeBlob* code, outputStream* output, CodeStrings c = CodeStrings());
  address decode_instructions(address start, address end);
  void start_insn(address pc) {
    _cur_insn = pc;
    output()->bol();
    print_insn_labels();
  }
  void end_insn(address pc) {
    address pc0 = cur_insn();
    outputStream* st = output();
    if (_print_bytes && pc > pc0)
      print_insn_bytes(pc0, pc);
    if (_nm != NULL) {
      _nm->print_code_comment_on(st, COMMENT_COLUMN, pc0, pc);
    }
    if (total_ticks() != 0) {
      address bucket_pc = FlatProfiler::bucket_start_for(pc);
      if (bucket_pc != NULL && bucket_pc > pc0 && bucket_pc <= pc) {
        int bucket_count = FlatProfiler::bucket_count_for(pc0);
        if (bucket_count != 0) {
          st->bol();
          st->print_cr("%3.1f%% [%d]", bucket_count*100.0/total_ticks(), bucket_count);
        }
      }
    }
    st->cr();
  }
  address handle_event(const char* event, address arg);
  outputStream* output() { return _output; }
  address cur_insn() { return _cur_insn; }
  int total_ticks() { return _total_ticks; }
  void set_total_ticks(int n) { _total_ticks = n; }
  const char* options() { return _option_buf; }
};
decode_env::decode_env(CodeBlob* code, outputStream* output, CodeStrings c) :
  _nm((code != NULL && code->is_nmethod()) ? (nmethod*)code : NULL),
  _code(code),
  _strings(),
  _output(output ? output : tty),
  _start(NULL),
  _end(NULL),
  _print_raw(0),
  _print_pc(true),
  _print_bytes(false),
  _cur_insn(NULL),
  _total_ticks(0),
  _bytes_per_line(Disassembler::pd_instruction_alignment())
{
  memset(_option_buf, 0, sizeof(_option_buf));
  _strings.copy(c);
  collect_options(Disassembler::pd_cpu_opts());
  collect_options(PrintAssemblyOptions);
  if (strstr(options(), "hsdis-")) {
    if (strstr(options(), "hsdis-print-raw"))
      _print_raw = (strstr(options(), "xml") ? 2 : 1);
    if (strstr(options(), "hsdis-print-pc"))
      _print_pc = !_print_pc;
    if (strstr(options(), "hsdis-print-bytes"))
      _print_bytes = !_print_bytes;
  }
  if (strstr(options(), "help")) {
    tty->print_cr("PrintAssemblyOptions help:");
    tty->print_cr("  hsdis-print-raw       test plugin by requesting raw output");
    tty->print_cr("  hsdis-print-raw-xml   test plugin by requesting raw xml");
    tty->print_cr("  hsdis-print-pc        turn off PC printing (on by default)");
    tty->print_cr("  hsdis-print-bytes     turn on instruction byte output");
    tty->print_cr("combined options: %s", options());
  }
}
address decode_env::handle_event(const char* event, address arg) {
  if (match(event, "insn")) {
    start_insn(arg);
  } else if (match(event, "/insn")) {
    end_insn(arg);
  } else if (match(event, "addr")) {
    if (arg != NULL) {
      print_address(arg);
      return arg;
    }
  } else if (match(event, "mach")) {
    static char buffer[32] = { 0, };
    if (strcmp(buffer, (const char*)arg) != 0 ||
        strlen((const char*)arg) > sizeof(buffer) - 1) {
      strncpy(buffer, (const char*)arg, sizeof(buffer) - 1);
      buffer[sizeof(buffer) - 1] = '\0';
      output()->print_cr("[Disassembling for mach='%s']", arg);
    }
  } else if (match(event, "format bytes-per-line")) {
    _bytes_per_line = (int) (intptr_t) arg;
  } else {
  }
  return NULL;
}
void decode_env::print_address(address adr) {
  outputStream* st = _output;
  if (adr == NULL) {
    st->print("NULL");
    return;
  }
  int small_num = (int)(intptr_t)adr;
  if ((intptr_t)adr == (intptr_t)small_num
      && -1 <= small_num && small_num <= 9) {
    st->print("%d", small_num);
    return;
  }
  if (Universe::is_fully_initialized()) {
    if (StubRoutines::contains(adr)) {
      StubCodeDesc* desc = StubCodeDesc::desc_for(adr);
      if (desc == NULL)
        desc = StubCodeDesc::desc_for(adr + frame::pc_return_offset);
      if (desc != NULL) {
        st->print("Stub::%s", desc->name());
        if (desc->begin() != adr)
          st->print("%+d 0x%p",adr - desc->begin(), adr);
        else if (WizardMode) st->print(" " PTR_FORMAT, adr);
        return;
      }
      st->print("Stub::<unknown> " PTR_FORMAT, adr);
      return;
    }
    BarrierSet* bs = Universe::heap()->barrier_set();
    if (bs->kind() == BarrierSet::CardTableModRef &&
        adr == (address)((CardTableModRefBS*)(bs))->byte_map_base) {
      st->print("word_map_base");
      if (WizardMode) st->print(" " INTPTR_FORMAT, (intptr_t)adr);
      return;
    }
    oop obj;
    if (_nm != NULL
        && (obj = _nm->embeddedOop_at(cur_insn())) != NULL
        && (address) obj == adr
        && Universe::heap()->is_in(obj)
        && Universe::heap()->is_in(obj->klass())) {
      julong c = st->count();
      obj->print_value_on(st);
      if (st->count() == c) {
        st->print("(a %s)", obj->klass()->external_name());
      }
      return;
    }
  }
  st->print(PTR_FORMAT, adr);
}
void decode_env::print_insn_labels() {
  address p = cur_insn();
  outputStream* st = output();
  CodeBlob* cb = _code;
  if (cb != NULL) {
    cb->print_block_comment(st, p);
  }
  _strings.print_block_comment(st, (intptr_t)(p - _start));
  if (_print_pc) {
    st->print("  " PTR_FORMAT ": ", p);
  }
}
void decode_env::print_insn_bytes(address pc, address pc_limit) {
  outputStream* st = output();
  size_t incr = 1;
  size_t perline = _bytes_per_line;
  if ((size_t) Disassembler::pd_instruction_alignment() >= sizeof(int)
      && !((uintptr_t)pc % sizeof(int))
      && !((uintptr_t)pc_limit % sizeof(int))) {
    incr = sizeof(int);
    if (perline % incr)  perline += incr - (perline % incr);
  }
  while (pc < pc_limit) {
    st->move_to(COMMENT_COLUMN);
    address pc0 = pc;
    address pc1 = pc + perline;
    if (pc1 > pc_limit)  pc1 = pc_limit;
    for (; pc < pc1; pc += incr) {
      if (pc == pc0)
        st->print(BYTES_COMMENT);
      else if ((uint)(pc - pc0) % sizeof(int) == 0)
        st->print(" ");         // put out a space on word boundaries
      if (incr == sizeof(int))
            st->print("%08lx", *(int*)pc);
      else  st->print("%02x",   (*pc)&0xFF);
    }
    st->cr();
  }
}
static void* event_to_env(void* env_pv, const char* event, void* arg) {
  decode_env* env = (decode_env*) env_pv;
  return env->handle_event(event, (address) arg);
}
ATTRIBUTE_PRINTF(2, 3)
static int printf_to_env(void* env_pv, const char* format, ...) {
  decode_env* env = (decode_env*) env_pv;
  outputStream* st = env->output();
  size_t flen = strlen(format);
  const char* raw = NULL;
  if (flen == 0)  return 0;
  if (flen == 1 && format[0] == '\n') { st->bol(); return 1; }
  if (flen < 2 ||
      strchr(format, '%') == NULL) {
    raw = format;
  } else if (format[0] == '%' && format[1] == '%' &&
             strchr(format+2, '%') == NULL) {
    flen--;
    raw = format+1;
  }
  if (raw != NULL) {
    st->print_raw(raw, (int) flen);
    return (int) flen;
  }
  va_list ap;
  va_start(ap, format);
  julong cnt0 = st->count();
  st->vprint(format, ap);
  julong cnt1 = st->count();
  va_end(ap);
  return (int)(cnt1 - cnt0);
}
address decode_env::decode_instructions(address start, address end) {
  _start = start; _end = end;
  assert(((((intptr_t)start | (intptr_t)end) % Disassembler::pd_instruction_alignment()) == 0), "misaligned insn addr");
  const int show_bytes = false; // for disassembler debugging
  if (!Disassembler::can_decode()) {
    return NULL;
  }
  if (_print_raw) {
    FILE* out = stdout;
    FILE* xmlout = (_print_raw > 1 ? out : NULL);
    return use_new_version ?
      (address)
      (*Disassembler::_decode_instructions_virtual)((uintptr_t)start, (uintptr_t)end,
                                                    start, end - start,
                                                    NULL, (void*) xmlout,
                                                    NULL, (void*) out,
                                                    options(), 0/*nice new line*/)
      :
      (address)
      (*Disassembler::_decode_instructions)(start, end,
                                            NULL, (void*) xmlout,
                                            NULL, (void*) out,
                                            options());
  }
  return use_new_version ?
    (address)
    (*Disassembler::_decode_instructions_virtual)((uintptr_t)start, (uintptr_t)end,
                                                  start, end - start,
                                                  &event_to_env,  (void*) this,
                                                  &printf_to_env, (void*) this,
                                                  options(), 0/*nice new line*/)
    :
    (address)
    (*Disassembler::_decode_instructions)(start, end,
                                          &event_to_env,  (void*) this,
                                          &printf_to_env, (void*) this,
                                          options());
}
void Disassembler::decode(CodeBlob* cb, outputStream* st) {
  ttyLocker ttyl;
  if (!load_library())  return;
  decode_env env(cb, st);
  env.output()->print_cr("Decoding CodeBlob " PTR_FORMAT, cb);
  env.decode_instructions(cb->code_begin(), cb->code_end());
}
void Disassembler::decode(address start, address end, outputStream* st, CodeStrings c) {
  ttyLocker ttyl;
  if (!load_library())  return;
  decode_env env(CodeCache::find_blob_unsafe(start), st, c);
  env.decode_instructions(start, end);
}
void Disassembler::decode(nmethod* nm, outputStream* st) {
  ttyLocker ttyl;
  if (!load_library())  return;
  decode_env env(nm, st);
  env.output()->print_cr("Decoding compiled method " PTR_FORMAT ":", nm);
  env.output()->print_cr("Code:");
#ifdef SHARK
  SharkEntry* entry = (SharkEntry *) nm->code_begin();
  unsigned char* p   = entry->code_start();
  unsigned char* end = entry->code_limit();
#else
  unsigned char* p   = nm->code_begin();
  unsigned char* end = nm->code_end();
#endif // SHARK
  if (FlatProfiler::bucket_start_for(p) != NULL) {
    unsigned char* p1 = p;
    int total_bucket_count = 0;
    while (p1 < end) {
      unsigned char* p0 = p1;
      p1 += pd_instruction_alignment();
      address bucket_pc = FlatProfiler::bucket_start_for(p1);
      if (bucket_pc != NULL && bucket_pc > p0 && bucket_pc <= p1)
        total_bucket_count += FlatProfiler::bucket_count_for(p0);
    }
    env.set_total_ticks(total_bucket_count);
  }
  if (nm->consts_size() > 0) {
    nm->print_nmethod_labels(env.output(), nm->consts_begin());
    int offset = 0;
    for (address p = nm->consts_begin(); p < nm->consts_end(); p += 4, offset += 4) {
      if ((offset % 8) == 0) {
        env.output()->print_cr("  " PTR_FORMAT " (offset: %4d): " PTR32_FORMAT "   " PTR64_FORMAT, p, offset, *((int32_t*) p), *((int64_t*) p));
      } else {
        env.output()->print_cr("  " PTR_FORMAT " (offset: %4d): " PTR32_FORMAT,                    p, offset, *((int32_t*) p));
      }
    }
  }
  env.decode_instructions(p, end);
}
C:\hotspot-69087d08d473\src\share\vm/compiler/disassembler.hpp
#ifndef SHARE_VM_COMPILER_DISASSEMBLER_HPP
#define SHARE_VM_COMPILER_DISASSEMBLER_HPP
#include "asm/codeBuffer.hpp"
#include "runtime/globals.hpp"
#ifdef TARGET_OS_FAMILY_linux
# include "os_linux.inline.hpp"
#endif
#ifdef TARGET_OS_FAMILY_solaris
# include "os_solaris.inline.hpp"
#endif
#ifdef TARGET_OS_FAMILY_windows
# include "os_windows.inline.hpp"
#endif
#ifdef TARGET_OS_FAMILY_aix
# include "os_aix.inline.hpp"
#endif
#ifdef TARGET_OS_FAMILY_bsd
# include "os_bsd.inline.hpp"
#endif
class decode_env;
class Disassembler {
  friend class decode_env;
 private:
  typedef void* (*decode_func_virtual)(uintptr_t start_va, uintptr_t end_va,
                               unsigned char* buffer, uintptr_t length,
                               void* (*event_callback)(void*, const char*, void*),
                               void* event_stream,
                               int (*printf_callback)(void*, const char*, ...),
                               void* printf_stream,
                               const char* options,
                               int newline);
  typedef void* (*decode_func)(void* start_va, void* end_va,
                               void* (*event_callback)(void*, const char*, void*),
                               void* event_stream,
                               int (*printf_callback)(void*, const char*, ...),
                               void* printf_stream,
                               const char* options);
  static void*    _library;
  static bool     _tried_to_load_library;
  static decode_func_virtual _decode_instructions_virtual;
  static decode_func _decode_instructions;
  static bool load_library();
#ifdef TARGET_ARCH_x86
# include "disassembler_x86.hpp"
#endif
#ifdef TARGET_ARCH_aarch64
# include "disassembler_aarch64.hpp"
#endif
#ifdef TARGET_ARCH_sparc
# include "disassembler_sparc.hpp"
#endif
#ifdef TARGET_ARCH_zero
# include "disassembler_zero.hpp"
#endif
#ifdef TARGET_ARCH_arm
# include "disassembler_arm.hpp"
#endif
#ifdef TARGET_ARCH_ppc
# include "disassembler_ppc.hpp"
#endif
 public:
  static bool can_decode() {
    return (_decode_instructions_virtual != NULL) ||
           (_decode_instructions != NULL) ||
           load_library();
  }
  static void decode(CodeBlob *cb,               outputStream* st = NULL);
  static void decode(nmethod* nm,                outputStream* st = NULL);
  static void decode(address begin, address end, outputStream* st = NULL, CodeStrings c = CodeStrings());
};
#endif // SHARE_VM_COMPILER_DISASSEMBLER_HPP
C:\hotspot-69087d08d473\src\share\vm/compiler/methodLiveness.cpp
#include "precompiled.hpp"
#include "ci/ciMethod.hpp"
#include "ci/ciMethodBlocks.hpp"
#include "ci/ciStreams.hpp"
#include "compiler/methodLiveness.hpp"
#include "interpreter/bytecode.hpp"
#include "interpreter/bytecodes.hpp"
#include "memory/allocation.inline.hpp"
#include "utilities/bitMap.inline.hpp"
PRAGMA_FORMAT_MUTE_WARNINGS_FOR_GCC
#ifndef PRODUCT
class BitCounter: public BitMapClosure {
 private:
  int _count;
 public:
  BitCounter() : _count(0) {}
  virtual bool do_bit(size_t offset) {
    _count++;
    return true;
  }
  int count() {
    return _count;
  }
};
long MethodLiveness::_total_bytes = 0;
int  MethodLiveness::_total_methods = 0;
long MethodLiveness::_total_blocks = 0;
int  MethodLiveness::_max_method_blocks = 0;
long MethodLiveness::_total_edges = 0;
int  MethodLiveness::_max_block_edges = 0;
long MethodLiveness::_total_exc_edges = 0;
int  MethodLiveness::_max_block_exc_edges = 0;
long MethodLiveness::_total_method_locals = 0;
int  MethodLiveness::_max_method_locals = 0;
long MethodLiveness::_total_locals_queried = 0;
long MethodLiveness::_total_live_locals_queried = 0;
long MethodLiveness::_total_visits = 0;
#endif
elapsedTimer MethodLiveness::_time_build_graph;
elapsedTimer MethodLiveness::_time_gen_kill;
elapsedTimer MethodLiveness::_time_flow;
elapsedTimer MethodLiveness::_time_query;
elapsedTimer MethodLiveness::_time_total;
MethodLiveness::MethodLiveness(Arena* arena, ciMethod* method)
#ifdef COMPILER1
  : _bci_block_start((uintptr_t*)arena->Amalloc((method->code_size() >> LogBitsPerByte) + 1), method->code_size())
#endif
{
  _arena = arena;
  _method = method;
  _bit_map_size_bits = method->max_locals();
  _bit_map_size_words = (_bit_map_size_bits / sizeof(unsigned int)) + 1;
#ifdef COMPILER1
  _bci_block_start.clear();
#endif
}
void MethodLiveness::compute_liveness() {
#ifndef PRODUCT
  if (TraceLivenessGen) {
    tty->print_cr("################################################################");
    tty->print("# Computing liveness information for ");
    method()->print_short_name();
  }
  if (TimeLivenessAnalysis) _time_total.start();
#endif
  {
    TraceTime buildGraph(NULL, &_time_build_graph, TimeLivenessAnalysis);
    init_basic_blocks();
  }
  {
    TraceTime genKill(NULL, &_time_gen_kill, TimeLivenessAnalysis);
    init_gen_kill();
  }
  {
    TraceTime flow(NULL, &_time_flow, TimeLivenessAnalysis);
    propagate_liveness();
  }
#ifndef PRODUCT
  if (TimeLivenessAnalysis) _time_total.stop();
  if (TimeLivenessAnalysis) {
    _total_bytes += method()->code_size();
    _total_methods++;
    int num_blocks = _block_count;
    _total_blocks += num_blocks;
    _max_method_blocks = MAX2(num_blocks,_max_method_blocks);
    for (int i=0; i<num_blocks; i++) {
      BasicBlock *block = _block_list[i];
      int numEdges = block->_normal_predecessors->length();
      int numExcEdges = block->_exception_predecessors->length();
      _total_edges += numEdges;
      _total_exc_edges += numExcEdges;
      _max_block_edges = MAX2(numEdges,_max_block_edges);
      _max_block_exc_edges = MAX2(numExcEdges,_max_block_exc_edges);
    }
    int numLocals = _bit_map_size_bits;
    _total_method_locals += numLocals;
    _max_method_locals = MAX2(numLocals,_max_method_locals);
  }
#endif
}
void MethodLiveness::init_basic_blocks() {
  bool bailout = false;
  int method_len = method()->code_size();
  ciMethodBlocks *mblocks = method()->get_method_blocks();
  _block_map = new (arena()) GrowableArray<BasicBlock*>(arena(), method_len, method_len, NULL);
  _block_count = mblocks->num_blocks();
  _block_list = (BasicBlock **) arena()->Amalloc(sizeof(BasicBlock *) * _block_count);
  GrowableArray<BasicBlock*>* jsr_exit_list = new GrowableArray<BasicBlock*>(5);
  GrowableArray<BasicBlock*>* ret_list = new GrowableArray<BasicBlock*>(5);
  for (int blk = 0; blk < _block_count; blk++) {
    ciBlock *cib = mblocks->block(blk);
     int start_bci = cib->start_bci();
    _block_list[blk] = new (arena()) BasicBlock(this, start_bci, cib->limit_bci());
    _block_map->at_put(start_bci, _block_list[blk]);
#ifdef COMPILER1
    _bci_block_start.set_bit(start_bci);
#endif // COMPILER1
  }
  ciBytecodeStream bytes(method());
  for (int blk = 0; blk < _block_count; blk++) {
    BasicBlock *current_block = _block_list[blk];
    int bci =  mblocks->block(blk)->control_bci();
    if (bci == ciBlock::fall_through_bci) {
      int limit = current_block->limit_bci();
      if (limit < method_len) {
        BasicBlock *next = _block_map->at(limit);
        assert( next != NULL, "must be a block immediately following this one.");
        next->add_normal_predecessor(current_block);
      }
      continue;
    }
    bytes.reset_to_bci(bci);
    Bytecodes::Code code = bytes.next();
    BasicBlock *dest;
    assert (current_block != NULL, "we must have a current block");
    switch (code) {
      case Bytecodes::_ifeq:
      case Bytecodes::_ifne:
      case Bytecodes::_iflt:
      case Bytecodes::_ifge:
      case Bytecodes::_ifgt:
      case Bytecodes::_ifle:
      case Bytecodes::_if_icmpeq:
      case Bytecodes::_if_icmpne:
      case Bytecodes::_if_icmplt:
      case Bytecodes::_if_icmpge:
      case Bytecodes::_if_icmpgt:
      case Bytecodes::_if_icmple:
      case Bytecodes::_if_acmpeq:
      case Bytecodes::_if_acmpne:
      case Bytecodes::_ifnull:
      case Bytecodes::_ifnonnull:
        dest = _block_map->at(bytes.next_bci());
        assert(dest != NULL, "must be a block immediately following this one.");
        dest->add_normal_predecessor(current_block);
        dest = _block_map->at(bytes.get_dest());
        assert(dest != NULL, "branch desination must start a block.");
        dest->add_normal_predecessor(current_block);
        break;
      case Bytecodes::_goto:
        dest = _block_map->at(bytes.get_dest());
        assert(dest != NULL, "branch desination must start a block.");
        dest->add_normal_predecessor(current_block);
        break;
      case Bytecodes::_goto_w:
        dest = _block_map->at(bytes.get_far_dest());
        assert(dest != NULL, "branch desination must start a block.");
        dest->add_normal_predecessor(current_block);
        break;
      case Bytecodes::_tableswitch:
        {
          Bytecode_tableswitch tableswitch(&bytes);
          int len = tableswitch.length();
          dest = _block_map->at(bci + tableswitch.default_offset());
          assert(dest != NULL, "branch desination must start a block.");
          dest->add_normal_predecessor(current_block);
          while (--len >= 0) {
            dest = _block_map->at(bci + tableswitch.dest_offset_at(len));
            assert(dest != NULL, "branch desination must start a block.");
            dest->add_normal_predecessor(current_block);
          }
          break;
        }
      case Bytecodes::_lookupswitch:
        {
          Bytecode_lookupswitch lookupswitch(&bytes);
          int npairs = lookupswitch.number_of_pairs();
          dest = _block_map->at(bci + lookupswitch.default_offset());
          assert(dest != NULL, "branch desination must start a block.");
          dest->add_normal_predecessor(current_block);
          while(--npairs >= 0) {
            LookupswitchPair pair = lookupswitch.pair_at(npairs);
            dest = _block_map->at( bci + pair.offset());
            assert(dest != NULL, "branch desination must start a block.");
            dest->add_normal_predecessor(current_block);
          }
          break;
        }
      case Bytecodes::_jsr:
        {
          assert(bytes.is_wide()==false, "sanity check");
          dest = _block_map->at(bytes.get_dest());
          assert(dest != NULL, "branch desination must start a block.");
          dest->add_normal_predecessor(current_block);
          BasicBlock *jsrExit = _block_map->at(current_block->limit_bci());
          assert(jsrExit != NULL, "jsr return bci must start a block.");
          jsr_exit_list->append(jsrExit);
          break;
        }
      case Bytecodes::_jsr_w:
        {
          dest = _block_map->at(bytes.get_far_dest());
          assert(dest != NULL, "branch desination must start a block.");
          dest->add_normal_predecessor(current_block);
          BasicBlock *jsrExit = _block_map->at(current_block->limit_bci());
          assert(jsrExit != NULL, "jsr return bci must start a block.");
          jsr_exit_list->append(jsrExit);
          break;
        }
      case Bytecodes::_wide:
        assert(false, "wide opcodes should not be seen here");
        break;
      case Bytecodes::_athrow:
      case Bytecodes::_ireturn:
      case Bytecodes::_lreturn:
      case Bytecodes::_freturn:
      case Bytecodes::_dreturn:
      case Bytecodes::_areturn:
      case Bytecodes::_return:
        break;
      case Bytecodes::_ret:
        ret_list->append(current_block);
        break;
      case Bytecodes::_breakpoint:
        bailout = true;
        break;
      default:
        break;
    }
  }
  int ret_list_len = ret_list->length();
  int jsr_exit_list_len = jsr_exit_list->length();
  if (ret_list_len > 0 && jsr_exit_list_len > 0) {
    for (int i = jsr_exit_list_len - 1; i >= 0; i--) {
      BasicBlock *jsrExit = jsr_exit_list->at(i);
      for (int i = ret_list_len - 1; i >= 0; i--) {
        jsrExit->add_normal_predecessor(ret_list->at(i));
      }
    }
  }
  for (int b=_block_count-1; b >= 0; b--) {
    BasicBlock *block = _block_list[b];
    int block_start = block->start_bci();
    int block_limit = block->limit_bci();
    ciExceptionHandlerStream handlers(method());
    for (; !handlers.is_done(); handlers.next()) {
      ciExceptionHandler* handler = handlers.handler();
      int start       = handler->start();
      int limit       = handler->limit();
      int handler_bci = handler->handler_bci();
      int intersect_start = MAX2(block_start, start);
      int intersect_limit = MIN2(block_limit, limit);
      if (intersect_start < intersect_limit) {
        _block_map->at(handler_bci)->add_exception_predecessor(block);
        if (handler->is_catch_all()) {
          if (intersect_start == block_start && intersect_limit == block_limit) {
            break;
          }
        }
      }
    }
  }
}
void MethodLiveness::init_gen_kill() {
  for (int i=_block_count-1; i >= 0; i--) {
    _block_list[i]->compute_gen_kill(method());
  }
}
void MethodLiveness::propagate_liveness() {
  int num_blocks = _block_count;
  BasicBlock *block;
  _work_list = NULL;
  for (int i = 0; i < num_blocks; i++) {
    block = _block_list[i];
    block->set_next(_work_list);
    block->set_on_work_list(true);
    _work_list = block;
  }
  while ((block = work_list_get()) != NULL) {
    block->propagate(this);
    NOT_PRODUCT(_total_visits++;)
  }
}
void MethodLiveness::work_list_add(BasicBlock *block) {
  if (!block->on_work_list()) {
    block->set_next(_work_list);
    block->set_on_work_list(true);
    _work_list = block;
  }
}
MethodLiveness::BasicBlock *MethodLiveness::work_list_get() {
  BasicBlock *block = _work_list;
  if (block != NULL) {
    block->set_on_work_list(false);
    _work_list = block->next();
  }
  return block;
}
MethodLivenessResult MethodLiveness::get_liveness_at(int entry_bci) {
  int bci = entry_bci;
  bool is_entry = false;
  if (entry_bci == InvocationEntryBci) {
    is_entry = true;
    bci = 0;
  }
  MethodLivenessResult answer((BitMap::bm_word_t*)NULL,0);
  if (_block_count > 0) {
    if (TimeLivenessAnalysis) _time_total.start();
    if (TimeLivenessAnalysis) _time_query.start();
    assert( 0 <= bci && bci < method()->code_size(), "bci out of range" );
    BasicBlock *block = _block_map->at(bci);
    int t = bci;
    while (block == NULL && t > 0) {
     block = _block_map->at(--t);
    }
    assert( block != NULL, "invalid bytecode index; must be instruction index" );
    assert(bci >= block->start_bci() && bci < block->limit_bci(), "block must contain bci.");
    answer = block->get_liveness_at(method(), bci);
    if (is_entry && method()->is_synchronized() && !method()->is_static()) {
      answer.at_put(0, true);
    }
#ifndef PRODUCT
    if (TraceLivenessQuery) {
      tty->print("Liveness query of ");
      method()->print_short_name();
      tty->print(" @ %d : result is ", bci);
      answer.print_on(tty);
    }
    if (TimeLivenessAnalysis) _time_query.stop();
    if (TimeLivenessAnalysis) _time_total.stop();
#endif
  }
#ifndef PRODUCT
  if (TimeLivenessAnalysis) {
    _total_locals_queried += _bit_map_size_bits;
    BitCounter counter;
    answer.iterate(&counter);
    _total_live_locals_queried += counter.count();
  }
#endif
  return answer;
}
#ifndef PRODUCT
void MethodLiveness::print_times() {
  tty->print_cr ("Accumulated liveness analysis times/statistics:");
  tty->print_cr ("-----------------------------------------------");
  tty->print_cr ("  Total         : %3.3f sec.", _time_total.seconds());
  tty->print_cr ("    Build graph : %3.3f sec. (%2.2f%%)", _time_build_graph.seconds(),
                 _time_build_graph.seconds() * 100 / _time_total.seconds());
  tty->print_cr ("    Gen / Kill  : %3.3f sec. (%2.2f%%)", _time_gen_kill.seconds(),
                 _time_gen_kill.seconds() * 100 / _time_total.seconds());
  tty->print_cr ("    Dataflow    : %3.3f sec. (%2.2f%%)", _time_flow.seconds(),
                 _time_flow.seconds() * 100 / _time_total.seconds());
  tty->print_cr ("    Query       : %3.3f sec. (%2.2f%%)", _time_query.seconds(),
                 _time_query.seconds() * 100 / _time_total.seconds());
  tty->print_cr ("  #bytes   : %8d (%3.0f bytes per sec)",
                 _total_bytes,
                 _total_bytes / _time_total.seconds());
  tty->print_cr ("  #methods : %8d (%3.0f methods per sec)",
                 _total_methods,
                 _total_methods / _time_total.seconds());
  tty->print_cr ("    avg locals : %3.3f    max locals : %3d",
                 (float)_total_method_locals / _total_methods,
                 _max_method_locals);
  tty->print_cr ("    avg blocks : %3.3f    max blocks : %3d",
                 (float)_total_blocks / _total_methods,
                 _max_method_blocks);
  tty->print_cr ("    avg bytes  : %3.3f",
                 (float)_total_bytes / _total_methods);
  tty->print_cr ("  #blocks  : %8d",
                 _total_blocks);
  tty->print_cr ("    avg normal predecessors    : %3.3f  max normal predecessors    : %3d",
                 (float)_total_edges / _total_blocks,
                 _max_block_edges);
  tty->print_cr ("    avg exception predecessors : %3.3f  max exception predecessors : %3d",
                 (float)_total_exc_edges / _total_blocks,
                 _max_block_exc_edges);
  tty->print_cr ("    avg visits                 : %3.3f",
                 (float)_total_visits / _total_blocks);
  tty->print_cr ("  #locals queried : %8d    #live : %8d   %%live : %2.2f%%",
                 _total_locals_queried,
                 _total_live_locals_queried,
                 100.0 * _total_live_locals_queried / _total_locals_queried);
}
#endif
MethodLiveness::BasicBlock::BasicBlock(MethodLiveness *analyzer, int start, int limit) :
         _gen((uintptr_t*)analyzer->arena()->Amalloc(BytesPerWord * analyzer->bit_map_size_words()),
                         analyzer->bit_map_size_bits()),
         _kill((uintptr_t*)analyzer->arena()->Amalloc(BytesPerWord * analyzer->bit_map_size_words()),
                         analyzer->bit_map_size_bits()),
         _entry((uintptr_t*)analyzer->arena()->Amalloc(BytesPerWord * analyzer->bit_map_size_words()),
                         analyzer->bit_map_size_bits()),
         _normal_exit((uintptr_t*)analyzer->arena()->Amalloc(BytesPerWord * analyzer->bit_map_size_words()),
                         analyzer->bit_map_size_bits()),
         _exception_exit((uintptr_t*)analyzer->arena()->Amalloc(BytesPerWord * analyzer->bit_map_size_words()),
                         analyzer->bit_map_size_bits()),
         _last_bci(-1) {
  _analyzer = analyzer;
  _start_bci = start;
  _limit_bci = limit;
  _normal_predecessors =
    new (analyzer->arena()) GrowableArray<MethodLiveness::BasicBlock*>(analyzer->arena(), 5, 0, NULL);
  _exception_predecessors =
    new (analyzer->arena()) GrowableArray<MethodLiveness::BasicBlock*>(analyzer->arena(), 5, 0, NULL);
  _normal_exit.clear();
  _exception_exit.clear();
  _entry.clear();
  _gen.clear();
  _kill.clear();
}
MethodLiveness::BasicBlock *MethodLiveness::BasicBlock::split(int split_bci) {
  int start = _start_bci;
  int limit = _limit_bci;
  if (TraceLivenessGen) {
    tty->print_cr(" ** Splitting block (%d,%d) at %d", start, limit, split_bci);
  }
  GrowableArray<BasicBlock*>* save_predecessors = _normal_predecessors;
  assert (start < split_bci && split_bci < limit, "improper split");
  BasicBlock *first_half = new (_analyzer->arena()) BasicBlock(_analyzer, start, split_bci);
  _normal_predecessors = first_half->_normal_predecessors;
  _start_bci = split_bci;
  add_normal_predecessor(first_half);
  first_half->_normal_predecessors = save_predecessors;
  return first_half;
}
void MethodLiveness::BasicBlock::compute_gen_kill(ciMethod* method) {
  ciBytecodeStream bytes(method);
  bytes.reset_to_bci(start_bci());
  bytes.set_max_bci(limit_bci());
  compute_gen_kill_range(&bytes);
}
void MethodLiveness::BasicBlock::compute_gen_kill_range(ciBytecodeStream *bytes) {
  _gen.clear();
  _kill.clear();
  while (bytes->next() != ciBytecodeStream::EOBC()) {
    compute_gen_kill_single(bytes);
  }
}
void MethodLiveness::BasicBlock::compute_gen_kill_single(ciBytecodeStream *instruction) {
  int localNum;
  switch (instruction->cur_bc()) {
    case Bytecodes::_nop:
    case Bytecodes::_goto:
    case Bytecodes::_goto_w:
    case Bytecodes::_aconst_null:
    case Bytecodes::_new:
    case Bytecodes::_iconst_m1:
    case Bytecodes::_iconst_0:
    case Bytecodes::_iconst_1:
    case Bytecodes::_iconst_2:
    case Bytecodes::_iconst_3:
    case Bytecodes::_iconst_4:
    case Bytecodes::_iconst_5:
    case Bytecodes::_fconst_0:
    case Bytecodes::_fconst_1:
    case Bytecodes::_fconst_2:
    case Bytecodes::_bipush:
    case Bytecodes::_sipush:
    case Bytecodes::_lconst_0:
    case Bytecodes::_lconst_1:
    case Bytecodes::_dconst_0:
    case Bytecodes::_dconst_1:
    case Bytecodes::_ldc2_w:
    case Bytecodes::_ldc:
    case Bytecodes::_ldc_w:
    case Bytecodes::_iaload:
    case Bytecodes::_faload:
    case Bytecodes::_baload:
    case Bytecodes::_caload:
    case Bytecodes::_saload:
    case Bytecodes::_laload:
    case Bytecodes::_daload:
    case Bytecodes::_aaload:
    case Bytecodes::_iastore:
    case Bytecodes::_fastore:
    case Bytecodes::_bastore:
    case Bytecodes::_castore:
    case Bytecodes::_sastore:
    case Bytecodes::_lastore:
    case Bytecodes::_dastore:
    case Bytecodes::_aastore:
    case Bytecodes::_pop:
    case Bytecodes::_pop2:
    case Bytecodes::_dup:
    case Bytecodes::_dup_x1:
    case Bytecodes::_dup_x2:
    case Bytecodes::_dup2:
    case Bytecodes::_dup2_x1:
    case Bytecodes::_dup2_x2:
    case Bytecodes::_swap:
    case Bytecodes::_iadd:
    case Bytecodes::_fadd:
    case Bytecodes::_isub:
    case Bytecodes::_fsub:
    case Bytecodes::_imul:
    case Bytecodes::_fmul:
    case Bytecodes::_idiv:
    case Bytecodes::_fdiv:
    case Bytecodes::_irem:
    case Bytecodes::_frem:
    case Bytecodes::_ishl:
    case Bytecodes::_ishr:
    case Bytecodes::_iushr:
    case Bytecodes::_iand:
    case Bytecodes::_ior:
    case Bytecodes::_ixor:
    case Bytecodes::_l2f:
    case Bytecodes::_l2i:
    case Bytecodes::_d2f:
    case Bytecodes::_d2i:
    case Bytecodes::_fcmpl:
    case Bytecodes::_fcmpg:
    case Bytecodes::_ladd:
    case Bytecodes::_dadd:
    case Bytecodes::_lsub:
    case Bytecodes::_dsub:
    case Bytecodes::_lmul:
    case Bytecodes::_dmul:
    case Bytecodes::_ldiv:
    case Bytecodes::_ddiv:
    case Bytecodes::_lrem:
    case Bytecodes::_drem:
    case Bytecodes::_land:
    case Bytecodes::_lor:
    case Bytecodes::_lxor:
    case Bytecodes::_ineg:
    case Bytecodes::_fneg:
    case Bytecodes::_i2f:
    case Bytecodes::_f2i:
    case Bytecodes::_i2c:
    case Bytecodes::_i2s:
    case Bytecodes::_i2b:
    case Bytecodes::_lneg:
    case Bytecodes::_dneg:
    case Bytecodes::_l2d:
    case Bytecodes::_d2l:
    case Bytecodes::_lshl:
    case Bytecodes::_lshr:
    case Bytecodes::_lushr:
    case Bytecodes::_i2l:
    case Bytecodes::_i2d:
    case Bytecodes::_f2l:
    case Bytecodes::_f2d:
    case Bytecodes::_lcmp:
    case Bytecodes::_dcmpl:
    case Bytecodes::_dcmpg:
    case Bytecodes::_ifeq:
    case Bytecodes::_ifne:
    case Bytecodes::_iflt:
    case Bytecodes::_ifge:
    case Bytecodes::_ifgt:
    case Bytecodes::_ifle:
    case Bytecodes::_tableswitch:
    case Bytecodes::_ireturn:
    case Bytecodes::_freturn:
    case Bytecodes::_if_icmpeq:
    case Bytecodes::_if_icmpne:
    case Bytecodes::_if_icmplt:
    case Bytecodes::_if_icmpge:
    case Bytecodes::_if_icmpgt:
    case Bytecodes::_if_icmple:
    case Bytecodes::_lreturn:
    case Bytecodes::_dreturn:
    case Bytecodes::_if_acmpeq:
    case Bytecodes::_if_acmpne:
    case Bytecodes::_jsr:
    case Bytecodes::_jsr_w:
    case Bytecodes::_getstatic:
    case Bytecodes::_putstatic:
    case Bytecodes::_getfield:
    case Bytecodes::_putfield:
    case Bytecodes::_invokevirtual:
    case Bytecodes::_invokespecial:
    case Bytecodes::_invokestatic:
    case Bytecodes::_invokeinterface:
    case Bytecodes::_invokedynamic:
    case Bytecodes::_newarray:
    case Bytecodes::_anewarray:
    case Bytecodes::_checkcast:
    case Bytecodes::_arraylength:
    case Bytecodes::_instanceof:
    case Bytecodes::_athrow:
    case Bytecodes::_areturn:
    case Bytecodes::_monitorenter:
    case Bytecodes::_monitorexit:
    case Bytecodes::_ifnull:
    case Bytecodes::_ifnonnull:
    case Bytecodes::_multianewarray:
    case Bytecodes::_lookupswitch:
      break;
    case Bytecodes::_return:
      if (instruction->method()->intrinsic_id() == vmIntrinsics::_Object_init) {
        load_one(0);
      }
      break;
    case Bytecodes::_lload:
    case Bytecodes::_dload:
      load_two(instruction->get_index());
      break;
    case Bytecodes::_lload_0:
    case Bytecodes::_dload_0:
      load_two(0);
      break;
    case Bytecodes::_lload_1:
    case Bytecodes::_dload_1:
      load_two(1);
      break;
    case Bytecodes::_lload_2:
    case Bytecodes::_dload_2:
      load_two(2);
      break;
    case Bytecodes::_lload_3:
    case Bytecodes::_dload_3:
      load_two(3);
      break;
    case Bytecodes::_iload:
    case Bytecodes::_iinc:
    case Bytecodes::_fload:
    case Bytecodes::_aload:
    case Bytecodes::_ret:
      load_one(instruction->get_index());
      break;
    case Bytecodes::_iload_0:
    case Bytecodes::_fload_0:
    case Bytecodes::_aload_0:
      load_one(0);
      break;
    case Bytecodes::_iload_1:
    case Bytecodes::_fload_1:
    case Bytecodes::_aload_1:
      load_one(1);
      break;
    case Bytecodes::_iload_2:
    case Bytecodes::_fload_2:
    case Bytecodes::_aload_2:
      load_one(2);
      break;
    case Bytecodes::_iload_3:
    case Bytecodes::_fload_3:
    case Bytecodes::_aload_3:
      load_one(3);
      break;
    case Bytecodes::_lstore:
    case Bytecodes::_dstore:
      store_two(localNum = instruction->get_index());
      break;
    case Bytecodes::_lstore_0:
    case Bytecodes::_dstore_0:
      store_two(0);
      break;
    case Bytecodes::_lstore_1:
    case Bytecodes::_dstore_1:
      store_two(1);
      break;
    case Bytecodes::_lstore_2:
    case Bytecodes::_dstore_2:
      store_two(2);
      break;
    case Bytecodes::_lstore_3:
    case Bytecodes::_dstore_3:
      store_two(3);
      break;
    case Bytecodes::_istore:
    case Bytecodes::_fstore:
    case Bytecodes::_astore:
      store_one(instruction->get_index());
      break;
    case Bytecodes::_istore_0:
    case Bytecodes::_fstore_0:
    case Bytecodes::_astore_0:
      store_one(0);
      break;
    case Bytecodes::_istore_1:
    case Bytecodes::_fstore_1:
    case Bytecodes::_astore_1:
      store_one(1);
      break;
    case Bytecodes::_istore_2:
    case Bytecodes::_fstore_2:
    case Bytecodes::_astore_2:
      store_one(2);
      break;
    case Bytecodes::_istore_3:
    case Bytecodes::_fstore_3:
    case Bytecodes::_astore_3:
      store_one(3);
      break;
    case Bytecodes::_wide:
      fatal("Iterator should skip this bytecode");
      break;
    default:
      tty->print("unexpected opcode: %d\n", instruction->cur_bc());
      ShouldNotReachHere();
      break;
  }
}
void MethodLiveness::BasicBlock::load_two(int local) {
  load_one(local);
  load_one(local+1);
}
void MethodLiveness::BasicBlock::load_one(int local) {
  if (!_kill.at(local)) {
    _gen.at_put(local, true);
  }
}
void MethodLiveness::BasicBlock::store_two(int local) {
  store_one(local);
  store_one(local+1);
}
void MethodLiveness::BasicBlock::store_one(int local) {
  if (!_gen.at(local)) {
    _kill.at_put(local, true);
  }
}
void MethodLiveness::BasicBlock::propagate(MethodLiveness *ml) {
  _entry.set_union(_normal_exit);
  _entry.set_difference(_kill);
  _entry.set_union(_gen);
  _entry.set_union(_exception_exit);
  if (TraceLivenessGen) {
    tty->print_cr(" ** Visiting block at %d **", start_bci());
    print_on(tty);
  }
  int i;
  for (i=_normal_predecessors->length()-1; i>=0; i--) {
    BasicBlock *block = _normal_predecessors->at(i);
    if (block->merge_normal(_entry)) {
      ml->work_list_add(block);
    }
  }
  for (i=_exception_predecessors->length()-1; i>=0; i--) {
    BasicBlock *block = _exception_predecessors->at(i);
    if (block->merge_exception(_entry)) {
      ml->work_list_add(block);
    }
  }
}
bool MethodLiveness::BasicBlock::merge_normal(BitMap other) {
  return _normal_exit.set_union_with_result(other);
}
bool MethodLiveness::BasicBlock::merge_exception(BitMap other) {
  return _exception_exit.set_union_with_result(other);
}
MethodLivenessResult MethodLiveness::BasicBlock::get_liveness_at(ciMethod* method, int bci) {
  MethodLivenessResult answer(NEW_RESOURCE_ARRAY(BitMap::bm_word_t, _analyzer->bit_map_size_words()),
                _analyzer->bit_map_size_bits());
  answer.set_is_valid();
#ifndef ASSERT
  if (bci == start_bci()) {
    answer.set_from(_entry);
    return answer;
  }
#endif
#ifdef ASSERT
  ResourceMark rm;
  BitMap g(_gen.size()); g.set_from(_gen);
  BitMap k(_kill.size()); k.set_from(_kill);
#endif
  if (_last_bci != bci || trueInDebug) {
    ciBytecodeStream bytes(method);
    bytes.reset_to_bci(bci);
    bytes.set_max_bci(limit_bci());
    compute_gen_kill_range(&bytes);
    assert(_last_bci != bci ||
           (g.is_same(_gen) && k.is_same(_kill)), "cached computation is incorrect");
    _last_bci = bci;
  }
  answer.clear();
  answer.set_union(_normal_exit);
  answer.set_difference(_kill);
  answer.set_union(_gen);
  answer.set_union(_exception_exit);
#ifdef ASSERT
  if (bci == start_bci()) {
    assert(answer.is_same(_entry), "optimized answer must be accurate");
  }
#endif
  return answer;
}
#ifndef PRODUCT
void MethodLiveness::BasicBlock::print_on(outputStream *os) const {
  os->print_cr("===================================================================");
  os->print_cr("    Block start: %4d, limit: %4d", _start_bci, _limit_bci);
  os->print   ("    Normal predecessors (%2d)      @", _normal_predecessors->length());
  int i;
  for (i=0; i < _normal_predecessors->length(); i++) {
    os->print(" %4d", _normal_predecessors->at(i)->start_bci());
  }
  os->cr();
  os->print   ("    Exceptional predecessors (%2d) @", _exception_predecessors->length());
  for (i=0; i < _exception_predecessors->length(); i++) {
    os->print(" %4d", _exception_predecessors->at(i)->start_bci());
  }
  os->cr();
  os->print ("    Normal Exit   : ");
  _normal_exit.print_on(os);
  os->print ("    Gen           : ");
  _gen.print_on(os);
  os->print ("    Kill          : ");
  _kill.print_on(os);
  os->print ("    Exception Exit: ");
  _exception_exit.print_on(os);
  os->print ("    Entry         : ");
  _entry.print_on(os);
}
#endif // PRODUCT
C:\hotspot-69087d08d473\src\share\vm/compiler/methodLiveness.hpp
#ifndef SHARE_VM_COMPILER_METHODLIVENESS_HPP
#define SHARE_VM_COMPILER_METHODLIVENESS_HPP
#include "utilities/bitMap.hpp"
#include "utilities/growableArray.hpp"
class ciMethod;
class MethodLivenessResult : public BitMap {
 private:
  bool _is_valid;
 public:
  MethodLivenessResult(BitMap::bm_word_t* map, idx_t size_in_bits)
    : BitMap(map, size_in_bits)
    , _is_valid(false)
  {}
  MethodLivenessResult(idx_t size_in_bits)
    : BitMap(size_in_bits)
    , _is_valid(false)
  {}
  void set_is_valid() { _is_valid = true; }
  bool is_valid() { return _is_valid; }
};
class MethodLiveness : public ResourceObj {
 public:
  class BasicBlock : public ResourceObj {
   private:
    friend class MethodLiveness;
    MethodLiveness* _analyzer;
    int _start_bci;
    int _limit_bci;
    BitMap _entry;
    BitMap _normal_exit;
    BitMap _exception_exit;
    BitMap _gen;
    BitMap _kill;
    int    _last_bci;
    GrowableArray<BasicBlock*>* _normal_predecessors;
    GrowableArray<BasicBlock*>* _exception_predecessors;
    BasicBlock *_next;
    bool _on_work_list;
    bool merge_normal(BitMap other);
    bool merge_exception(BitMap other);
    void compute_gen_kill_range(ciBytecodeStream *bytes);
    void compute_gen_kill_single(ciBytecodeStream *instruction);
    void load_one(int local);
    void load_two(int local);
    void store_one(int local);
    void store_two(int local);
    BasicBlock(MethodLiveness *analyzer, int start, int limit);
    int start_bci() const { return _start_bci; }
    int limit_bci() const { return _limit_bci; }
    void set_limit_bci(int limit) { _limit_bci = limit; }
    BasicBlock *next() const { return _next; }
    void set_next(BasicBlock *next) { _next = next; }
    bool on_work_list() const { return _on_work_list; }
    void set_on_work_list(bool val) { _on_work_list = val; }
    void add_normal_predecessor(BasicBlock *pred) {
      _normal_predecessors->append_if_missing(pred);
    }
    void add_exception_predecessor(BasicBlock *pred) {
      _exception_predecessors->append_if_missing(pred);
    }
    BasicBlock *split(int splitBci);
    void compute_gen_kill(ciMethod* method);
    void propagate(MethodLiveness *ml);
    MethodLivenessResult get_liveness_at(ciMethod* method, int bci);
    void print_on(outputStream *os) const PRODUCT_RETURN;
  }; // End of MethodLiveness::BasicBlock
 private:
  ciMethod* _method;
  ciMethod* method() const { return _method; }
  Arena*       _arena;
  Arena*       arena() const { return _arena; }
  int _code_size;
  int _bit_map_size_bits;
  int _bit_map_size_words;
  BasicBlock **_block_list;
  int  _block_count;
  GrowableArray<BasicBlock*>* _block_map;
  BasicBlock *_work_list;
#ifdef COMPILER1
  BitMap _bci_block_start;
#endif // COMPILER1
  void init_basic_blocks();
  void init_gen_kill();
  void propagate_liveness();
 friend class MethodLiveness::BasicBlock;
  int bit_map_size_bits() const { return _bit_map_size_bits; }
  int bit_map_size_words() const { return _bit_map_size_words; }
  BasicBlock *work_list_get();
  void work_list_add(BasicBlock *block);
  static elapsedTimer _time_build_graph;
  static elapsedTimer _time_gen_kill;
  static elapsedTimer _time_flow;
  static elapsedTimer _time_query;
  static elapsedTimer _time_total;
#ifndef PRODUCT
  static long _total_bytes;
  static int  _total_methods;
  static long _total_blocks;
  static int  _max_method_blocks;
  static long _total_edges;
  static int  _max_block_edges;
  static long _total_exc_edges;
  static int  _max_block_exc_edges;
  static long _total_method_locals;
  static int  _max_method_locals;
  static long _total_locals_queried;
  static long _total_live_locals_queried;
  static long _total_visits;
#endif
 public:
  MethodLiveness(Arena* arena, ciMethod* method);
  void compute_liveness();
  MethodLivenessResult get_liveness_at(int bci);
#ifdef COMPILER1
  const BitMap get_bci_block_start() const { return _bci_block_start; }
#endif // COMPILER1
  static void print_times() PRODUCT_RETURN;
};
#endif // SHARE_VM_COMPILER_METHODLIVENESS_HPP
C:\hotspot-69087d08d473\src\share\vm/compiler/oopMap.cpp
#include "precompiled.hpp"
#include "code/codeBlob.hpp"
#include "code/codeCache.hpp"
#include "code/nmethod.hpp"
#include "code/scopeDesc.hpp"
#include "compiler/oopMap.hpp"
#include "gc_interface/collectedHeap.hpp"
#include "memory/allocation.inline.hpp"
#include "memory/resourceArea.hpp"
#include "runtime/frame.inline.hpp"
#include "runtime/signature.hpp"
#ifdef COMPILER1
#include "c1/c1_Defs.hpp"
#endif
OopMapStream::OopMapStream(OopMap* oop_map) {
  if(oop_map->omv_data() == NULL) {
    _stream = new CompressedReadStream(oop_map->write_stream()->buffer());
  } else {
    _stream = new CompressedReadStream(oop_map->omv_data());
  }
  _mask = OopMapValue::type_mask_in_place;
  _size = oop_map->omv_count();
  _position = 0;
  _valid_omv = false;
}
OopMapStream::OopMapStream(OopMap* oop_map, int oop_types_mask) {
  if(oop_map->omv_data() == NULL) {
    _stream = new CompressedReadStream(oop_map->write_stream()->buffer());
  } else {
    _stream = new CompressedReadStream(oop_map->omv_data());
  }
  _mask = oop_types_mask;
  _size = oop_map->omv_count();
  _position = 0;
  _valid_omv = false;
}
void OopMapStream::find_next() {
  while(_position++ < _size) {
    _omv.read_from(_stream);
    if(((int)_omv.type() & _mask) > 0) {
      _valid_omv = true;
      return;
    }
  }
  _valid_omv = false;
}
OopMap::OopMap(int frame_size, int arg_count) {
  set_write_stream(new CompressedWriteStream(32));
  set_omv_data(NULL);
  set_omv_count(0);
#ifdef ASSERT
  _locs_length = VMRegImpl::stack2reg(0)->value() + frame_size + arg_count;
  _locs_used   = NEW_RESOURCE_ARRAY(OopMapValue::oop_types, _locs_length);
  for(int i = 0; i < _locs_length; i++) _locs_used[i] = OopMapValue::unused_value;
#endif
}
OopMap::OopMap(OopMap::DeepCopyToken, OopMap* source) {
  set_write_stream(new CompressedWriteStream(source->omv_count() * 2));
  set_omv_data(NULL);
  set_omv_count(0);
  set_offset(source->offset());
#ifdef ASSERT
  _locs_length = source->_locs_length;
  _locs_used = NEW_RESOURCE_ARRAY(OopMapValue::oop_types, _locs_length);
  for(int i = 0; i < _locs_length; i++) _locs_used[i] = OopMapValue::unused_value;
#endif
  for (OopMapStream oms(source); !oms.is_done(); oms.next()) {
    OopMapValue omv = oms.current();
    omv.write_on(write_stream());
    increment_count();
  }
}
OopMap* OopMap::deep_copy() {
  return new OopMap(_deep_copy_token, this);
}
void OopMap::copy_to(address addr) {
  memcpy(addr,this,sizeof(OopMap));
  memcpy(addr + sizeof(OopMap),write_stream()->buffer(),write_stream()->position());
  OopMap* new_oop = (OopMap*)addr;
  new_oop->set_omv_data_size(write_stream()->position());
  new_oop->set_omv_data((unsigned char *)(addr + sizeof(OopMap)));
  new_oop->set_write_stream(NULL);
}
int OopMap::heap_size() const {
  int size = sizeof(OopMap);
  int align = sizeof(void *) - 1;
  if(write_stream() != NULL) {
    size += write_stream()->position();
  } else {
    size += omv_data_size();
  }
  size = ((size+align) & ~align);
  return size;
}
void OopMap::set_xxx(VMReg reg, OopMapValue::oop_types x, VMReg optional) {
  assert(reg->value() < _locs_length, "too big reg value for stack size");
  assert( _locs_used[reg->value()] == OopMapValue::unused_value, "cannot insert twice" );
  debug_only( _locs_used[reg->value()] = x; )
  OopMapValue o(reg, x);
  if(x == OopMapValue::callee_saved_value) {
    assert(optional->is_reg(), "Trying to callee save a stack location");
    o.set_content_reg(optional);
  } else if(x == OopMapValue::derived_oop_value) {
    o.set_content_reg(optional);
  }
  o.write_on(write_stream());
  increment_count();
}
void OopMap::set_oop(VMReg reg) {
  set_xxx(reg, OopMapValue::oop_value, VMRegImpl::Bad());
}
void OopMap::set_value(VMReg reg) {
  if (ZapDeadCompiledLocals)
    set_xxx(reg, OopMapValue::value_value, VMRegImpl::Bad());
}
void OopMap::set_narrowoop(VMReg reg) {
  set_xxx(reg, OopMapValue::narrowoop_value, VMRegImpl::Bad());
}
void OopMap::set_callee_saved(VMReg reg, VMReg caller_machine_register ) {
  set_xxx(reg, OopMapValue::callee_saved_value, caller_machine_register);
}
void OopMap::set_derived_oop(VMReg reg, VMReg derived_from_local_register ) {
  if( reg == derived_from_local_register ) {
    set_oop(reg);
  } else {
    set_xxx(reg, OopMapValue::derived_oop_value, derived_from_local_register);
  }
}
OopMapSet::OopMapSet() {
  set_om_size(MinOopMapAllocation);
  set_om_count(0);
  OopMap** temp = NEW_RESOURCE_ARRAY(OopMap*, om_size());
  set_om_data(temp);
}
void OopMapSet::grow_om_data() {
  int new_size = om_size() * 2;
  OopMap** new_data = NEW_RESOURCE_ARRAY(OopMap*, new_size);
  memcpy(new_data,om_data(),om_size() * sizeof(OopMap*));
  set_om_size(new_size);
  set_om_data(new_data);
}
void OopMapSet::copy_to(address addr) {
  address temp = addr;
  int align = sizeof(void *) - 1;
  memcpy(addr,this,sizeof(OopMapSet));
  temp += sizeof(OopMapSet);
  temp = (address)((intptr_t)(temp + align) & ~align);
  OopMapSet* new_set = (OopMapSet*)addr;
  new_set->set_om_data((OopMap**)temp);
  temp += (om_count() * sizeof(OopMap*));
  for(int i=0; i < om_count(); i++) {
    OopMap* map = at(i);
    map->copy_to((address)temp);
    new_set->set(i,(OopMap*)temp);
    temp += map->heap_size();
  }
  new_set->set_om_size(-1);
}
void OopMapSet::add_gc_map(int pc_offset, OopMap *map ) {
  assert(om_size() != -1,"Cannot grow a fixed OopMapSet");
  if(om_count() >= om_size()) {
    grow_om_data();
  }
  map->set_offset(pc_offset);
#ifdef ASSERT
  if(om_count() > 0) {
    OopMap* last = at(om_count()-1);
    if (last->offset() == map->offset() ) {
      fatal("OopMap inserted twice");
    }
    if(last->offset() > map->offset()) {
      tty->print_cr( "WARNING, maps not sorted: pc[%d]=%d, pc[%d]=%d",
                      om_count(),last->offset(),om_count()+1,map->offset());
    }
  }
#endif // ASSERT
  set(om_count(),map);
  increment_count();
}
int OopMapSet::heap_size() const {
  int size = sizeof(OopMap);
  int align = sizeof(void *) - 1;
  size = ((size+align) & ~align);
  size += om_count() * sizeof(OopMap*);
  for(int i=0; i < om_count(); i++) {
    size += at(i)->heap_size();
  }
  return size;
}
OopMap* OopMapSet::singular_oop_map() {
  guarantee(om_count() == 1, "Make sure we only have a single gc point");
  return at(0);
}
OopMap* OopMapSet::find_map_at_offset(int pc_offset) const {
  int i, len = om_count();
  assert( len > 0, "must have pointer maps" );
  for( i = 0; i < len; i++) {
    if( at(i)->offset() >= pc_offset )
      break;
  }
  assert( i < len, "oopmap not found" );
  OopMap* m = at(i);
  assert( m->offset() == pc_offset, "oopmap not found" );
  return m;
}
class DoNothingClosure: public OopClosure {
 public:
  void do_oop(oop* p)       {}
  void do_oop(narrowOop* p) {}
};
static DoNothingClosure do_nothing;
static void add_derived_oop(oop* base, oop* derived) {
#ifndef TIERED
  COMPILER1_PRESENT(ShouldNotReachHere();)
#endif // TIERED
#ifdef COMPILER2
  DerivedPointerTable::add(derived, base);
#endif // COMPILER2
}
#ifndef PRODUCT
static void trace_codeblob_maps(const frame *fr, const RegisterMap *reg_map) {
  tty->print_cr("------ ");
  CodeBlob* cb = fr->cb();
  OopMapSet* maps = cb->oop_maps();
  OopMap* map = cb->oop_map_for_return_address(fr->pc());
  map->print();
  if( cb->is_nmethod() ) {
    nmethod* nm = (nmethod*)cb;
    if (nm->is_native_method()) {
      tty->print("bci: 0 (native)");
    } else {
      ScopeDesc* scope  = nm->scope_desc_at(fr->pc());
      tty->print("bci: %d ",scope->bci());
    }
  }
  tty->cr();
  fr->print_on(tty);
  tty->print("     ");
  cb->print_value_on(tty);  tty->cr();
  reg_map->print();
  tty->print_cr("------ ");
}
#endif // PRODUCT
void OopMapSet::oops_do(const frame *fr, const RegisterMap* reg_map, OopClosure* f) {
  all_do(fr, reg_map, f, add_derived_oop, &do_nothing);
}
void OopMapSet::all_do(const frame *fr, const RegisterMap *reg_map,
                       OopClosure* oop_fn, void derived_oop_fn(oop*, oop*),
                       OopClosure* value_fn) {
  CodeBlob* cb = fr->cb();
  assert(cb != NULL, "no codeblob");
  NOT_PRODUCT(if (TraceCodeBlobStacks) trace_codeblob_maps(fr, reg_map);)
  OopMapSet* maps = cb->oop_maps();
  OopMap* map = cb->oop_map_for_return_address(fr->pc());
  assert(map != NULL, "no ptr map found");
  OopMapValue omv;
  {
    OopMapStream oms(map,OopMapValue::derived_oop_value);
    if (!oms.is_done()) {
#ifndef TIERED
      COMPILER1_PRESENT(ShouldNotReachHere();)
#endif // !TIERED
      MutexLockerEx x(DerivedPointerTableGC_lock, Mutex::_no_safepoint_check_flag);
      do {
        omv = oms.current();
        oop* loc = fr->oopmapreg_to_location(omv.reg(),reg_map);
        if ( loc != NULL ) {
          oop *derived_loc = loc;
          oop *base_loc    = fr->oopmapreg_to_location(omv.content_reg(), reg_map);
          if (base_loc != NULL && *base_loc != (oop)NULL && !Universe::is_narrow_oop_base(*base_loc)) {
            derived_oop_fn(base_loc, derived_loc);
          }
        }
        oms.next();
      }  while (!oms.is_done());
    }
  }
  int mask = OopMapValue::oop_value | OopMapValue::value_value | OopMapValue::narrowoop_value;
  {
    for (OopMapStream oms(map,mask); !oms.is_done(); oms.next()) {
      omv = oms.current();
      oop* loc = fr->oopmapreg_to_location(omv.reg(),reg_map);
      if ( loc != NULL ) {
        if ( omv.type() == OopMapValue::oop_value ) {
          oop val = *loc;
          if (val == (oop)NULL || Universe::is_narrow_oop_base(val)) {
            continue;
          }
#ifdef ASSERT
          if ((((uintptr_t)loc & (sizeof(*loc)-1)) != 0) ||
             !Universe::heap()->is_in_or_null(*loc)) {
            tty->print_cr("# Found non oop pointer.  Dumping state at failure");
            trace_codeblob_maps(fr, reg_map);
            omv.print();
            tty->print_cr("register r");
            omv.reg()->print();
            tty->print_cr("loc = %p *loc = %p\n", loc, (address)*loc);
            assert(Universe::heap()->is_in_or_null(*loc), "found non oop pointer");
          }
#endif // ASSERT
          oop_fn->do_oop(loc);
        } else if ( omv.type() == OopMapValue::value_value ) {
          assert((*loc) == (oop)NULL || !Universe::is_narrow_oop_base(*loc),
                 "found invalid value pointer");
          value_fn->do_oop(loc);
        } else if ( omv.type() == OopMapValue::narrowoop_value ) {
          narrowOop *nl = (narrowOop*)loc;
#ifndef VM_LITTLE_ENDIAN
          if (!omv.reg()->is_stack()) {
            nl = (narrowOop*)((address)nl + 4);
          }
#endif
          oop_fn->do_oop(nl);
        }
      }
    }
  }
}
void OopMapSet::update_register_map(const frame *fr, RegisterMap *reg_map) {
  ResourceMark rm;
  CodeBlob* cb = fr->cb();
  assert(cb != NULL, "no codeblob");
  assert( reg_map->_update_for_id == NULL || fr->is_older(reg_map->_update_for_id),
         "already updated this map; do not 'update' it twice!" );
  debug_only(reg_map->_update_for_id = fr->id());
  assert((reg_map->include_argument_oops() ||
          !cb->caller_must_gc_arguments(reg_map->thread())),
         "include_argument_oops should already be set");
  address pc = fr->pc();
  OopMap* map  = cb->oop_map_for_return_address(pc);
  assert(map != NULL, "no ptr map found");
  DEBUG_ONLY(int nof_callee = 0;)
  for (OopMapStream oms(map, OopMapValue::callee_saved_value); !oms.is_done(); oms.next()) {
    OopMapValue omv = oms.current();
    VMReg reg = omv.content_reg();
    oop* loc = fr->oopmapreg_to_location(omv.reg(), reg_map);
    reg_map->set_location(reg, (address) loc);
    DEBUG_ONLY(nof_callee++;)
  }
#ifdef COMPILER2
  assert(cb->is_compiled_by_c1() || !cb->is_runtime_stub() ||
         (nof_callee >= SAVED_ON_ENTRY_REG_COUNT || nof_callee >= C_SAVED_ON_ENTRY_REG_COUNT),
         "must save all");
#endif // COMPILER2
}
#ifndef PRODUCT
bool OopMap::has_derived_pointer() const {
#ifndef TIERED
  COMPILER1_PRESENT(return false);
#endif // !TIERED
#ifdef COMPILER2
  OopMapStream oms((OopMap*)this,OopMapValue::derived_oop_value);
  return oms.is_done();
#else
  return false;
#endif // COMPILER2
}
#endif //PRODUCT
static
void print_register_type(OopMapValue::oop_types x, VMReg optional,
                         outputStream* st) {
  switch( x ) {
  case OopMapValue::oop_value:
    st->print("Oop");
    break;
  case OopMapValue::value_value:
    st->print("Value");
    break;
  case OopMapValue::narrowoop_value:
    st->print("NarrowOop");
    break;
  case OopMapValue::callee_saved_value:
    st->print("Callers_");
    optional->print_on(st);
    break;
  case OopMapValue::derived_oop_value:
    st->print("Derived_oop_");
    optional->print_on(st);
    break;
  default:
    ShouldNotReachHere();
  }
}
void OopMapValue::print_on(outputStream* st) const {
  reg()->print_on(st);
  st->print("=");
  print_register_type(type(),content_reg(),st);
  st->print(" ");
}
void OopMap::print_on(outputStream* st) const {
  OopMapValue omv;
  st->print("OopMap{");
  for(OopMapStream oms((OopMap*)this); !oms.is_done(); oms.next()) {
    omv = oms.current();
    omv.print_on(st);
  }
  st->print("off=%d}", (int) offset());
}
void OopMapSet::print_on(outputStream* st) const {
  int i, len = om_count();
  st->print_cr("OopMapSet contains %d OopMaps\n",len);
  for( i = 0; i < len; i++) {
    OopMap* m = at(i);
    st->print_cr("#%d ",i);
    m->print_on(st);
    st->cr();
  }
}
#ifdef COMPILER2
class DerivedPointerEntry : public CHeapObj<mtCompiler> {
 private:
  oop*     _location; // Location of derived pointer (also pointing to the base)
  intptr_t _offset;   // Offset from base pointer
 public:
  DerivedPointerEntry(oop* location, intptr_t offset) { _location = location; _offset = offset; }
  oop* location()    { return _location; }
  intptr_t  offset() { return _offset; }
};
GrowableArray<DerivedPointerEntry*>* DerivedPointerTable::_list = NULL;
bool DerivedPointerTable::_active = false;
void DerivedPointerTable::clear() {
  assert (!_active, "should not be active");
  assert(_list == NULL || _list->length() == 0, "table not empty");
  if (_list == NULL) {
    _list = new (ResourceObj::C_HEAP, mtCompiler) GrowableArray<DerivedPointerEntry*>(10, true); // Allocated on C heap
  }
  _active = true;
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值