sssssssss9


void LoopInvariantCodeMotion::process_block(BlockBegin* block) {
  TRACE_VALUE_NUMBERING(tty->print_cr("processing block B%d", block->block_id()));
  Instruction* prev = block;
  Instruction* cur = block->next();
  while (cur != NULL) {
    bool cur_invariant = false;
    if (cur->as_Constant() != NULL) {
      cur_invariant = !cur->can_trap();
    } else if (cur->as_ArithmeticOp() != NULL || cur->as_LogicOp() != NULL || cur->as_ShiftOp() != NULL) {
      assert(cur->as_Op2() != NULL, "must be Op2");
      Op2* op2 = (Op2*)cur;
      cur_invariant = !op2->can_trap() && is_invariant(op2->x()) && is_invariant(op2->y());
    } else if (cur->as_LoadField() != NULL) {
      LoadField* lf = (LoadField*)cur;
      cur_invariant = !lf->needs_patching() && !lf->field()->is_volatile() && !_short_loop_optimizer->has_field_store(lf->field()->type()->basic_type()) && is_invariant(lf->obj()) && _insert_is_pred;
    } else if (cur->as_ArrayLength() != NULL) {
      ArrayLength *length = cur->as_ArrayLength();
      cur_invariant = is_invariant(length->array());
    } else if (cur->as_LoadIndexed() != NULL) {
      LoadIndexed *li = (LoadIndexed *)cur->as_LoadIndexed();
      cur_invariant = !_short_loop_optimizer->has_indexed_store(as_BasicType(cur->type())) && is_invariant(li->array()) && is_invariant(li->index()) && _insert_is_pred;
    }
    if (cur_invariant) {
      _gvn->substitute(cur);
      if (cur->as_Constant() == NULL) {
        cur->pin();
      }
      Instruction* next = cur->next();
      Instruction* in = _insertion_point->next();
      _insertion_point = _insertion_point->set_next(cur);
      cur->set_next(in);
      cur->set_flag(Instruction::DeoptimizeOnException, true);
      cur->set_exception_handlers(NULL);
      TRACE_VALUE_NUMBERING(tty->print_cr("Instruction %c%d is loop invariant", cur->type()->tchar(), cur->id()));
      if (cur->state_before() != NULL) {
        cur->set_state_before(_state->copy());
      }
      if (cur->exception_state() != NULL) {
        cur->set_exception_state(_state->copy());
      }
      cur = prev->set_next(next);
    } else {
      prev = cur;
      cur = cur->next();
    }
  }
}
bool ShortLoopOptimizer::process(BlockBegin* loop_header) {
  TRACE_VALUE_NUMBERING(tty->print_cr("** loop header block"));
  _too_complicated_loop = false;
  _loop_blocks.clear();
  _loop_blocks.append(loop_header);
  for (int i = 0; i < _loop_blocks.length(); i++) {
    BlockBegin* block = _loop_blocks.at(i);
    TRACE_VALUE_NUMBERING(tty->print_cr("processing loop block B%d", block->block_id()));
    if (block->is_set(BlockBegin::exception_entry_flag)) {
      return false;
    }
    for (int j = block->number_of_preds() - 1; j >= 0; j--) {
      BlockBegin* pred = block->pred_at(j);
      if (pred->is_set(BlockBegin::osr_entry_flag)) {
        return false;
      }
      ValueMap* pred_map = value_map_of(pred);
      if (pred_map != NULL) {
        current_map()->kill_map(pred_map);
      } else if (!_loop_blocks.contains(pred)) {
        if (_loop_blocks.length() >= ValueMapMaxLoopSize) {
          return false;
        }
        _loop_blocks.append(pred);
      }
    }
    for (Value instr = block->next(); instr != NULL; instr = instr->next()) {
      instr->visit(this);
      if (_too_complicated_loop) {
        return false;
      }
    }
  }
  bool optimistic = this->_gvn->compilation()->is_optimistic();
  if (UseLoopInvariantCodeMotion && optimistic) {
    LoopInvariantCodeMotion code_motion(this, _gvn, loop_header, &_loop_blocks);
  }
  TRACE_VALUE_NUMBERING(tty->print_cr("** loop successfully optimized"));
  return true;
}
GlobalValueNumbering::GlobalValueNumbering(IR* ir)
  : _current_map(NULL)
  , _value_maps(ir->linear_scan_order()->length(), NULL)
  , _compilation(ir->compilation())
{
  TRACE_VALUE_NUMBERING(tty->print_cr("****** start of global value numbering"));
  ShortLoopOptimizer short_loop_optimizer(this);
  BlockList* blocks = ir->linear_scan_order();
  int num_blocks = blocks->length();
  BlockBegin* start_block = blocks->at(0);
  assert(start_block == ir->start() && start_block->number_of_preds() == 0 && start_block->dominator() == NULL, "must be start block");
  assert(start_block->next()->as_Base() != NULL && start_block->next()->next() == NULL, "start block must not have instructions");
  for_each_state_value(start_block->state(), value,
     assert(value->as_Local() != NULL, "only method parameters allowed");
     set_processed(value);
  );
  set_value_map_of(start_block, new ValueMap());
  for (int i = 1; i < num_blocks; i++) {
    BlockBegin* block = blocks->at(i);
    TRACE_VALUE_NUMBERING(tty->print_cr("**** processing block B%d", block->block_id()));
    int num_preds = block->number_of_preds();
    assert(num_preds > 0, "block must have predecessors");
    BlockBegin* dominator = block->dominator();
    assert(dominator != NULL, "dominator must exist");
    assert(value_map_of(dominator) != NULL, "value map of dominator must exist");
    _current_map = new ValueMap(value_map_of(dominator));
    if (num_preds == 1 && !block->is_set(BlockBegin::exception_entry_flag)) {
      assert(dominator == block->pred_at(0), "dominator must be equal to predecessor");
    } else if (block->is_set(BlockBegin::linear_scan_loop_header_flag)) {
      if (!short_loop_optimizer.process(block)) {
        current_map()->kill_memory();
      }
    } else {
      for (int j = 0; j < num_preds; j++) {
        BlockBegin* pred = block->pred_at(j);
        ValueMap* pred_map = value_map_of(pred);
        if (pred_map != NULL) {
          current_map()->kill_map(value_map_of(pred));
        } else {
          current_map()->kill_memory();
        }
      }
    }
    for_each_phi_fun(block, phi,
      set_processed(phi);
    );
    TRACE_VALUE_NUMBERING(tty->print("value map before processing block: "); current_map()->print());
    for (Value instr = block->next(); instr != NULL; instr = instr->next()) {
      instr->visit(this);
      substitute(instr);
    }
    set_value_map_of(block, current_map());
  }
  if (_has_substitutions) {
    SubstitutionResolver resolver(ir);
  }
  TRACE_VALUE_NUMBERING(tty->print("****** end of global value numbering. "); ValueMap::print_statistics());
}
void GlobalValueNumbering::substitute(Instruction* instr) {
  assert(!instr->has_subst(), "substitution already set");
  Value subst = current_map()->find_insert(instr);
  if (subst != instr) {
    assert(!subst->has_subst(), "can't have a substitution");
    TRACE_VALUE_NUMBERING(tty->print_cr("substitution for %d set to %d", instr->id(), subst->id()));
    instr->set_subst(subst);
    _has_substitutions = true;
  }
  set_processed(instr);
}
C:\hotspot-69087d08d473\src\share\vm/c1/c1_ValueMap.hpp
#ifndef SHARE_VM_C1_C1_VALUEMAP_HPP
#define SHARE_VM_C1_C1_VALUEMAP_HPP
#include "c1/c1_Instruction.hpp"
#include "c1/c1_ValueSet.hpp"
#include "memory/allocation.hpp"
class ValueMapEntry: public CompilationResourceObj {
 private:
  intx           _hash;
  Value          _value;
  int            _nesting;
  ValueMapEntry* _next;
 public:
  ValueMapEntry(intx hash, Value value, int nesting, ValueMapEntry* next)
    : _hash(hash)
    , _value(value)
    , _nesting(nesting)
    , _next(next)
  {
  }
  intx           hash()      { return _hash; }
  Value          value()     { return _value; }
  int            nesting()   { return _nesting; }
  ValueMapEntry* next()      { return _next; }
  void set_next(ValueMapEntry* next) { _next = next; }
};
define_array(ValueMapEntryArray, ValueMapEntry*)
define_stack(ValueMapEntryList, ValueMapEntryArray)
class ValueMap: public CompilationResourceObj {
 private:
  int           _nesting;
  ValueMapEntryArray _entries;
  ValueSet      _killed_values;
  int           _entry_count;
  int           nesting()                        { return _nesting; }
  bool          is_local_value_numbering()       { return _nesting == 0; }
  bool          is_global_value_numbering()      { return _nesting > 0; }
  int           entry_count()                    { return _entry_count; }
  int           size()                           { return _entries.length(); }
  ValueMapEntry* entry_at(int i)                 { return _entries.at(i); }
  int           entry_index(intx hash, int n)    { return (unsigned int)hash % n; }
  int           size_threshold()                 { return size(); }
  void          kill_value(Value v)              { if (is_global_value_numbering()) _killed_values.put(v); }
  bool          is_killed(Value v)               { if (is_global_value_numbering()) return _killed_values.contains(v); else return false; }
  void          increase_table_size();
#ifndef PRODUCT
  static int _number_of_finds;
  static int _number_of_hits;
  static int _number_of_kills;
#endif // PRODUCT
 public:
  ValueMap();                // empty value map
  ValueMap(ValueMap* old);   // value map with increased nesting
  Value find_insert(Value x);
  void kill_memory();
  void kill_field(ciField* field, bool all_offsets);
  void kill_array(ValueType* type);
  void kill_exception();
  void kill_map(ValueMap* map);
  void kill_all();
#ifndef PRODUCT
  void print();
  static void reset_statistics();
  static void print_statistics();
#endif
};
define_array(ValueMapArray, ValueMap*)
class ValueNumberingVisitor: public InstructionVisitor {
 protected:
  virtual void kill_memory() = 0;
  virtual void kill_field(ciField* field, bool all_offsets) = 0;
  virtual void kill_array(ValueType* type) = 0;
  void do_StoreField     (StoreField*      x) {
    if (x->is_init_point() ||  // putstatic is an initialization point so treat it as a wide kill
        x->field()->is_volatile()) {
      kill_memory();
    } else {
      kill_field(x->field(), x->needs_patching());
    }
  }
  void do_StoreIndexed   (StoreIndexed*    x) { kill_array(x->type()); }
  void do_MonitorEnter   (MonitorEnter*    x) { kill_memory(); }
  void do_MonitorExit    (MonitorExit*     x) { kill_memory(); }
  void do_Invoke         (Invoke*          x) { kill_memory(); }
  void do_UnsafePutRaw   (UnsafePutRaw*    x) { kill_memory(); }
  void do_UnsafePutObject(UnsafePutObject* x) { kill_memory(); }
  void do_UnsafeGetAndSetObject(UnsafeGetAndSetObject* x) { kill_memory(); }
  void do_UnsafeGetRaw   (UnsafeGetRaw*    x) { /* nothing to do */ }
  void do_UnsafeGetObject(UnsafeGetObject* x) {
    if (x->is_volatile()) { // the JMM requires this
      kill_memory();
    }
  }
  void do_Intrinsic      (Intrinsic*       x) { if (!x->preserves_state()) kill_memory(); }
  void do_Phi            (Phi*             x) { /* nothing to do */ }
  void do_Local          (Local*           x) { /* nothing to do */ }
  void do_Constant       (Constant*        x) { /* nothing to do */ }
  void do_LoadField      (LoadField*       x) {
    if (x->is_init_point() ||         // getstatic is an initialization point so treat it as a wide kill
        x->field()->is_volatile()) {  // the JMM requires this
      kill_memory();
    }
  }
  void do_ArrayLength    (ArrayLength*     x) { /* nothing to do */ }
  void do_LoadIndexed    (LoadIndexed*     x) { /* nothing to do */ }
  void do_NegateOp       (NegateOp*        x) { /* nothing to do */ }
  void do_ArithmeticOp   (ArithmeticOp*    x) { /* nothing to do */ }
  void do_ShiftOp        (ShiftOp*         x) { /* nothing to do */ }
  void do_LogicOp        (LogicOp*         x) { /* nothing to do */ }
  void do_CompareOp      (CompareOp*       x) { /* nothing to do */ }
  void do_IfOp           (IfOp*            x) { /* nothing to do */ }
  void do_Convert        (Convert*         x) { /* nothing to do */ }
  void do_NullCheck      (NullCheck*       x) { /* nothing to do */ }
  void do_TypeCast       (TypeCast*        x) { /* nothing to do */ }
  void do_NewInstance    (NewInstance*     x) { /* nothing to do */ }
  void do_NewTypeArray   (NewTypeArray*    x) { /* nothing to do */ }
  void do_NewObjectArray (NewObjectArray*  x) { /* nothing to do */ }
  void do_NewMultiArray  (NewMultiArray*   x) { /* nothing to do */ }
  void do_CheckCast      (CheckCast*       x) { /* nothing to do */ }
  void do_InstanceOf     (InstanceOf*      x) { /* nothing to do */ }
  void do_BlockBegin     (BlockBegin*      x) { /* nothing to do */ }
  void do_Goto           (Goto*            x) { /* nothing to do */ }
  void do_If             (If*              x) { /* nothing to do */ }
  void do_IfInstanceOf   (IfInstanceOf*    x) { /* nothing to do */ }
  void do_TableSwitch    (TableSwitch*     x) { /* nothing to do */ }
  void do_LookupSwitch   (LookupSwitch*    x) { /* nothing to do */ }
  void do_Return         (Return*          x) { /* nothing to do */ }
  void do_Throw          (Throw*           x) { /* nothing to do */ }
  void do_Base           (Base*            x) { /* nothing to do */ }
  void do_OsrEntry       (OsrEntry*        x) { /* nothing to do */ }
  void do_ExceptionObject(ExceptionObject* x) { /* nothing to do */ }
  void do_RoundFP        (RoundFP*         x) { /* nothing to do */ }
  void do_UnsafePrefetchRead (UnsafePrefetchRead*  x) { /* nothing to do */ }
  void do_UnsafePrefetchWrite(UnsafePrefetchWrite* x) { /* nothing to do */ }
  void do_ProfileCall    (ProfileCall*     x) { /* nothing to do */ }
  void do_ProfileReturnType (ProfileReturnType*  x) { /* nothing to do */ }
  void do_ProfileInvoke  (ProfileInvoke*   x) { /* nothing to do */ };
  void do_RuntimeCall    (RuntimeCall*     x) { /* nothing to do */ };
  void do_MemBar         (MemBar*          x) { /* nothing to do */ };
  void do_RangeCheckPredicate(RangeCheckPredicate* x) { /* nothing to do */ };
#ifdef ASSERT
  void do_Assert         (Assert*          x) { /* nothing to do */ };
#endif
};
class ValueNumberingEffects: public ValueNumberingVisitor {
 private:
  ValueMap*     _map;
 public:
  void          kill_memory()                                 { _map->kill_memory(); }
  void          kill_field(ciField* field, bool all_offsets)  { _map->kill_field(field, all_offsets); }
  void          kill_array(ValueType* type)                   { _map->kill_array(type); }
  ValueNumberingEffects(ValueMap* map): _map(map) {}
};
class GlobalValueNumbering: public ValueNumberingVisitor {
 private:
  Compilation*  _compilation;     // compilation data
  ValueMap*     _current_map;     // value map of current block
  ValueMapArray _value_maps;      // list of value maps for all blocks
  ValueSet      _processed_values;  // marker for instructions that were already processed
  bool          _has_substitutions; // set to true when substitutions must be resolved
 public:
  Compilation*  compilation() const              { return _compilation; }
  ValueMap*     current_map()                    { return _current_map; }
  ValueMap*     value_map_of(BlockBegin* block)  { return _value_maps.at(block->linear_scan_number()); }
  void          set_value_map_of(BlockBegin* block, ValueMap* map)   { assert(value_map_of(block) == NULL, ""); _value_maps.at_put(block->linear_scan_number(), map); }
  bool          is_processed(Value v)            { return _processed_values.contains(v); }
  void          set_processed(Value v)           { _processed_values.put(v); }
  void          kill_memory()                                 { current_map()->kill_memory(); }
  void          kill_field(ciField* field, bool all_offsets)  { current_map()->kill_field(field, all_offsets); }
  void          kill_array(ValueType* type)                   { current_map()->kill_array(type); }
  GlobalValueNumbering(IR* ir);
  void          substitute(Instruction* instr);  // substitute instruction if it is contained in current value map
};
#endif // SHARE_VM_C1_C1_VALUEMAP_HPP
C:\hotspot-69087d08d473\src\share\vm/c1/c1_ValueSet.cpp
#include "precompiled.hpp"
#include "c1/c1_ValueSet.hpp"
C:\hotspot-69087d08d473\src\share\vm/c1/c1_ValueSet.hpp
#ifndef SHARE_VM_C1_C1_VALUESET_HPP
#define SHARE_VM_C1_C1_VALUESET_HPP
#include "c1/c1_Instruction.hpp"
#include "memory/allocation.hpp"
#include "utilities/bitMap.inline.hpp"
class ValueSet: public CompilationResourceObj {
 private:
  BitMap _map;
 public:
  ValueSet();
  ValueSet* copy();
  bool contains(Value x);
  void put     (Value x);
  void remove  (Value x);
  bool set_intersect(ValueSet* other);
  void set_union(ValueSet* other);
  void clear   ();
  void set_from(ValueSet* other);
  bool equals  (ValueSet* other);
};
inline ValueSet::ValueSet() : _map(Instruction::number_of_instructions()) {
  _map.clear();
}
inline ValueSet* ValueSet::copy() {
  ValueSet* res = new ValueSet();
  res->_map.set_from(_map);
  return res;
}
inline bool ValueSet::contains(Value x) {
  return _map.at(x->id());
}
inline void ValueSet::put(Value x) {
  _map.set_bit(x->id());
}
inline void ValueSet::remove(Value x) {
  _map.clear_bit(x->id());
}
inline bool ValueSet::set_intersect(ValueSet* other) {
  return _map.set_intersection_with_result(other->_map);
}
inline void ValueSet::set_union(ValueSet* other) {
  _map.set_union(other->_map);
}
inline void ValueSet::clear() {
  _map.clear();
}
inline void ValueSet::set_from(ValueSet* other) {
  _map.set_from(other->_map);
}
inline bool ValueSet::equals(ValueSet* other) {
  return _map.is_same(other->_map);
}
#endif // SHARE_VM_C1_C1_VALUESET_HPP
C:\hotspot-69087d08d473\src\share\vm/c1/c1_ValueStack.cpp
#include "precompiled.hpp"
#include "c1/c1_IR.hpp"
#include "c1/c1_InstructionPrinter.hpp"
#include "c1/c1_ValueStack.hpp"
ValueStack::ValueStack(IRScope* scope, ValueStack* caller_state)
: _scope(scope)
, _caller_state(caller_state)
, _bci(-99)
, _kind(Parsing)
, _locals(scope->method()->max_locals(), NULL)
, _stack(scope->method()->max_stack())
, _locks()
{
  verify();
}
ValueStack::ValueStack(ValueStack* copy_from, Kind kind, int bci)
  : _scope(copy_from->scope())
  , _caller_state(copy_from->caller_state())
  , _bci(bci)
  , _kind(kind)
  , _locals()
  , _stack()
  , _locks(copy_from->locks_size())
{
  assert(kind != EmptyExceptionState || !Compilation::current()->env()->should_retain_local_variables(), "need locals");
  if (kind != EmptyExceptionState) {
    _locals = Values(copy_from->locals_size());
    _locals.appendAll(&copy_from->_locals);
  }
  if (kind != ExceptionState && kind != EmptyExceptionState) {
    if (kind == Parsing) {
      _stack = Values(scope()->method()->max_stack());
    } else {
      _stack = Values(copy_from->stack_size());
    }
    _stack.appendAll(&copy_from->_stack);
  }
  _locks.appendAll(&copy_from->_locks);
  verify();
}
bool ValueStack::is_same(ValueStack* s) {
  if (scope() != s->scope()) return false;
  if (caller_state() != s->caller_state()) return false;
  if (locals_size() != s->locals_size()) return false;
  if (stack_size() != s->stack_size()) return false;
  if (locks_size() != s->locks_size()) return false;
  int index;
  Value value;
  for_each_stack_value(this, index, value) {
    if (value->type()->tag() != s->stack_at(index)->type()->tag()) return false;
  }
  for_each_lock_value(this, index, value) {
    if (value != s->lock_at(index)) return false;
  }
  return true;
}
void ValueStack::clear_locals() {
  for (int i = _locals.length() - 1; i >= 0; i--) {
    _locals.at_put(i, NULL);
  }
}
void ValueStack::pin_stack_for_linear_scan() {
  for_each_state_value(this, v,
    if (v->as_Constant() == NULL && v->as_Local() == NULL) {
      v->pin(Instruction::PinStackForStateSplit);
    }
  );
}
void ValueStack::apply(Values list, ValueVisitor* f) {
  for (int i = 0; i < list.length(); i++) {
    Value* va = list.adr_at(i);
    Value v0 = *va;
    if (v0 != NULL && !v0->type()->is_illegal()) {
      f->visit(va);
#ifdef ASSERT
      Value v1 = *va;
      assert(v1->type()->is_illegal() || v0->type()->tag() == v1->type()->tag(), "types must match");
      assert(!v1->type()->is_double_word() || list.at(i + 1) == NULL, "hi-word of doubleword value must be NULL");
#endif
      if (v0->type()->is_double_word()) i++;
    }
  }
}
void ValueStack::values_do(ValueVisitor* f) {
  ValueStack* state = this;
  for_each_state(state) {
    apply(state->_locals, f);
    apply(state->_stack, f);
    apply(state->_locks, f);
  }
}
Values* ValueStack::pop_arguments(int argument_size) {
  assert(stack_size() >= argument_size, "stack too small or too many arguments");
  int base = stack_size() - argument_size;
  Values* args = new Values(argument_size);
  for (int i = base; i < stack_size();) args->push(stack_at_inc(i));
  truncate_stack(base);
  return args;
}
int ValueStack::total_locks_size() const {
  int num_locks = 0;
  const ValueStack* state = this;
  for_each_state(state) {
    num_locks += state->locks_size();
  }
  return num_locks;
}
int ValueStack::lock(Value obj) {
  _locks.push(obj);
  int num_locks = total_locks_size();
  scope()->set_min_number_of_locks(num_locks);
  return num_locks - 1;
}
int ValueStack::unlock() {
  _locks.pop();
  return total_locks_size();
}
void ValueStack::setup_phi_for_stack(BlockBegin* b, int index) {
  assert(stack_at(index)->as_Phi() == NULL || stack_at(index)->as_Phi()->block() != b, "phi function already created");
  ValueType* t = stack_at(index)->type();
  Value phi = new Phi(t, b, -index - 1);
  _stack[index] = phi;
  assert(!t->is_double_word() || _stack.at(index + 1) == NULL, "hi-word of doubleword value must be NULL");
}
void ValueStack::setup_phi_for_local(BlockBegin* b, int index) {
  assert(local_at(index)->as_Phi() == NULL || local_at(index)->as_Phi()->block() != b, "phi function already created");
  ValueType* t = local_at(index)->type();
  Value phi = new Phi(t, b, index);
  store_local(index, phi);
}
#ifndef PRODUCT
void ValueStack::print() {
  scope()->method()->print_name();
  tty->cr();
  if (stack_is_empty()) {
    tty->print_cr("empty stack");
  } else {
    InstructionPrinter ip;
    for (int i = 0; i < stack_size();) {
      Value t = stack_at_inc(i);
      tty->print("%2d  ", i);
      tty->print("%c%d ", t->type()->tchar(), t->id());
      ip.print_instr(t);
      tty->cr();
    }
  }
  if (!no_active_locks()) {
    InstructionPrinter ip;
    for (int i = 0; i < locks_size(); i++) {
      Value t = lock_at(i);
      tty->print("lock %2d  ", i);
      if (t == NULL) {
        tty->print("this");
      } else {
        tty->print("%c%d ", t->type()->tchar(), t->id());
        ip.print_instr(t);
      }
      tty->cr();
    }
  }
  if (locals_size() > 0) {
    InstructionPrinter ip;
    for (int i = 0; i < locals_size();) {
      Value l = _locals[i];
      tty->print("local %d ", i);
      if (l == NULL) {
        tty->print("null");
        i ++;
      } else {
        tty->print("%c%d ", l->type()->tchar(), l->id());
        ip.print_instr(l);
        if (l->type()->is_illegal() || l->type()->is_single_word()) i ++; else i += 2;
      }
      tty->cr();
    }
  }
  if (caller_state() != NULL) {
    caller_state()->print();
  }
}
void ValueStack::verify() {
  assert(scope() != NULL, "scope must exist");
  if (caller_state() != NULL) {
    assert(caller_state()->scope() == scope()->caller(), "invalid caller scope");
    caller_state()->verify();
  }
  if (kind() == Parsing) {
    assert(bci() == -99, "bci not defined during parsing");
  } else {
    assert(bci() >= -1, "bci out of range");
    assert(bci() < scope()->method()->code_size(), "bci out of range");
    assert(bci() == SynchronizationEntryBCI || Bytecodes::is_defined(scope()->method()->java_code_at_bci(bci())), "make sure bci points at a real bytecode");
    assert(scope()->method()->liveness_at_bci(bci()).is_valid(), "liveness at bci must be valid");
  }
  int i;
  for (i = 0; i < stack_size(); i++) {
    Value v = _stack.at(i);
    if (v == NULL) {
      assert(_stack.at(i - 1)->type()->is_double_word(), "only hi-words are NULL on stack");
    } else if (v->type()->is_double_word()) {
      assert(_stack.at(i + 1) == NULL, "hi-word must be NULL");
    }
  }
  for (i = 0; i < locals_size(); i++) {
    Value v = _locals.at(i);
    if (v != NULL && v->type()->is_double_word()) {
      assert(_locals.at(i + 1) == NULL, "hi-word must be NULL");
    }
  }
  for_each_state_value(this, v,
    assert(v != NULL, "just test if state-iteration succeeds");
  );
}
#endif // PRODUCT
C:\hotspot-69087d08d473\src\share\vm/c1/c1_ValueStack.hpp
#ifndef SHARE_VM_C1_C1_VALUESTACK_HPP
#define SHARE_VM_C1_C1_VALUESTACK_HPP
#include "c1/c1_Instruction.hpp"
class ValueStack: public CompilationResourceObj {
 public:
  enum Kind {
    Parsing,             // During abstract interpretation in GraphBuilder
    CallerState,         // Caller state when inlining
    StateBefore,         // Before before execution of instruction
    StateAfter,          // After execution of instruction
    ExceptionState,      // Exception handling of instruction
    EmptyExceptionState, // Exception handling of instructions not covered by an xhandler
    BlockBeginState      // State of BlockBegin instruction with phi functions of this block
  };
 private:
  IRScope* _scope;                               // the enclosing scope
  ValueStack* _caller_state;
  int      _bci;
  Kind     _kind;
  Values   _locals;                              // the locals
  Values   _stack;                               // the expression stack
  Values   _locks;                               // the monitor stack (holding the locked values)
  Value check(ValueTag tag, Value t) {
    assert(tag == t->type()->tag() || tag == objectTag && t->type()->tag() == addressTag, "types must correspond");
    return t;
  }
  Value check(ValueTag tag, Value t, Value h) {
    assert(h == NULL, "hi-word of doubleword value must be NULL");
    return check(tag, t);
  }
  static void apply(Values list, ValueVisitor* f);
  ValueStack(ValueStack* copy_from, Kind kind, int bci);
 public:
  ValueStack(IRScope* scope, ValueStack* caller_state);
  ValueStack* copy()                             { return new ValueStack(this, _kind, _bci); }
  ValueStack* copy(Kind new_kind, int new_bci)   { return new ValueStack(this, new_kind, new_bci); }
  ValueStack* copy_for_parsing()                 { return new ValueStack(this, Parsing, -99); }
  void set_caller_state(ValueStack* s)           {
    assert(kind() == EmptyExceptionState ||
           (Compilation::current()->env()->should_retain_local_variables() && kind() == ExceptionState),
           "only EmptyExceptionStates can be modified");
    _caller_state = s;
  }
  bool is_same(ValueStack* s);                   // returns true if this & s's types match (w/o checking locals)
  IRScope* scope() const                         { return _scope; }
  ValueStack* caller_state() const               { return _caller_state; }
  int bci() const                                { return _bci; }
  Kind kind() const                              { return _kind; }
  int locals_size() const                        { return _locals.length(); }
  int stack_size() const                         { return _stack.length(); }
  int locks_size() const                         { return _locks.length(); }
  bool stack_is_empty() const                    { return _stack.is_empty(); }
  bool no_active_locks() const                   { return _locks.is_empty(); }
  int total_locks_size() const;
  void clear_locals();                           // sets all locals to NULL;
  void invalidate_local(int i) {
    assert(_locals.at(i)->type()->is_single_word() ||
           _locals.at(i + 1) == NULL, "hi-word of doubleword value must be NULL");
    _locals.at_put(i, NULL);
  }
  Value local_at(int i) const {
    Value x = _locals.at(i);
    assert(x == NULL || x->type()->is_single_word() ||
           _locals.at(i + 1) == NULL, "hi-word of doubleword value must be NULL");
    return x;
  }
  void store_local(int i, Value x) {
    if (i > 0) {
      Value prev = _locals.at(i - 1);
      if (prev != NULL && prev->type()->is_double_word()) {
        _locals.at_put(i - 1, NULL);
      }
    }
    _locals.at_put(i, x);
    if (x->type()->is_double_word()) {
      _locals.at_put(i + 1, NULL);
    }
  }
  Value stack_at(int i) const {
    Value x = _stack.at(i);
    assert(x->type()->is_single_word() ||
           _stack.at(i + 1) == NULL, "hi-word of doubleword value must be NULL");
    return x;
  }
  Value stack_at_inc(int& i) const {
    Value x = stack_at(i);
    i += x->type()->size();
    return x;
  }
  void stack_at_put(int i, Value x) {
    _stack.at_put(i, x);
  }
  void pin_stack_for_linear_scan();
  void values_do(ValueVisitor* f);
  void truncate_stack(int size)                  { _stack.trunc_to(size); }
  void raw_push(Value t)                         { _stack.push(t); }
  Value raw_pop()                                { return _stack.pop(); }
  void ipush(Value t)                            { _stack.push(check(intTag    , t)); }
  void fpush(Value t)                            { _stack.push(check(floatTag  , t)); }
  void apush(Value t)                            { _stack.push(check(objectTag , t)); }
  void rpush(Value t)                            { _stack.push(check(addressTag, t)); }
  void lpush(Value t)                            { _stack.push(check(longTag   , t)); _stack.push(NULL); }
  void dpush(Value t)                            { _stack.push(check(doubleTag , t)); _stack.push(NULL); }
  void push(ValueType* type, Value t) {
    switch (type->tag()) {
      case intTag    : ipush(t); return;
      case longTag   : lpush(t); return;
      case floatTag  : fpush(t); return;
      case doubleTag : dpush(t); return;
      case objectTag : apush(t); return;
      case addressTag: rpush(t); return;
    }
    ShouldNotReachHere();
  }
  Value ipop()                                   { return check(intTag    , _stack.pop()); }
  Value fpop()                                   { return check(floatTag  , _stack.pop()); }
  Value apop()                                   { return check(objectTag , _stack.pop()); }
  Value rpop()                                   { return check(addressTag, _stack.pop()); }
  Value lpop()                                   { Value h = _stack.pop(); return check(longTag  , _stack.pop(), h); }
  Value dpop()                                   { Value h = _stack.pop(); return check(doubleTag, _stack.pop(), h); }
  Value pop(ValueType* type) {
    switch (type->tag()) {
      case intTag    : return ipop();
      case longTag   : return lpop();
      case floatTag  : return fpop();
      case doubleTag : return dpop();
      case objectTag : return apop();
      case addressTag: return rpop();
    }
    ShouldNotReachHere();
    return NULL;
  }
  Values* pop_arguments(int argument_size);
  int lock  (Value obj);
  int unlock();
  Value lock_at(int i) const                     { return _locks.at(i); }
  void setup_phi_for_stack(BlockBegin* b, int index);
  void setup_phi_for_local(BlockBegin* b, int index);
  void print()  PRODUCT_RETURN;
  void verify() PRODUCT_RETURN;
};
#define temp_var3(x) temp__ ## x
#define temp_var2(x) temp_var3(x)
#define temp_var     temp_var2(__LINE__)
#define for_each_state(state)  \
  for (; state != NULL; state = state->caller_state())
#define for_each_local_value(state, index, value)                                              \
  int temp_var = state->locals_size();                                                         \
  for (index = 0;                                                                              \
       index < temp_var && (value = state->local_at(index), true);                             \
       index += (value == NULL || value->type()->is_illegal() ? 1 : value->type()->size()))    \
    if (value != NULL)
#define for_each_stack_value(state, index, value)                                              \
  int temp_var = state->stack_size();                                                          \
  for (index = 0;                                                                              \
       index < temp_var && (value = state->stack_at(index), true);                             \
       index += value->type()->size())
#define for_each_lock_value(state, index, value)                                               \
  int temp_var = state->locks_size();                                                          \
  for (index = 0;                                                                              \
       index < temp_var && (value = state->lock_at(index), true);                              \
       index++)                                                                                \
    if (value != NULL)
#define for_each_state_value(v_state, v_value, v_code)                                         \
{                                                                                              \
  int cur_index;                                                                               \
  ValueStack* cur_state = v_state;                                                             \
  Value v_value;                                                                               \
  for_each_state(cur_state) {                                                                  \
    {                                                                                            \
      for_each_local_value(cur_state, cur_index, v_value) {                                      \
        v_code;                                                                                  \
      }                                                                                          \
    }                                                                                          \
    {                                                                                            \
      for_each_stack_value(cur_state, cur_index, v_value) {                                      \
        v_code;                                                                                  \
      }                                                                                          \
    }                                                                                            \
  }                                                                                            \
}
#define for_each_phi_fun(v_block, v_phi, v_code)                                               \
{                                                                                              \
  int cur_index;                                                                               \
  ValueStack* cur_state = v_block->state();                                                    \
  Value value;                                                                                 \
  {                                                                                            \
    for_each_stack_value(cur_state, cur_index, value) {                                        \
      Phi* v_phi = value->as_Phi();                                                      \
      if (v_phi != NULL && v_phi->block() == v_block) {                                        \
        v_code;                                                                                \
      }                                                                                        \
    }                                                                                          \
  }                                                                                            \
  {                                                                                            \
    for_each_local_value(cur_state, cur_index, value) {                                        \
      Phi* v_phi = value->as_Phi();                                                      \
      if (v_phi != NULL && v_phi->block() == v_block) {                                        \
        v_code;                                                                                \
      }                                                                                        \
    }                                                                                          \
  }                                                                                            \
}
#endif // SHARE_VM_C1_C1_VALUESTACK_HPP
C:\hotspot-69087d08d473\src\share\vm/c1/c1_ValueType.cpp
#include "precompiled.hpp"
#include "c1/c1_ValueType.hpp"
#include "ci/ciArray.hpp"
#include "ci/ciInstance.hpp"
#include "ci/ciNullObject.hpp"
VoidType*       voidType     = NULL;
IntType*        intType      = NULL;
LongType*       longType     = NULL;
FloatType*      floatType    = NULL;
DoubleType*     doubleType   = NULL;
ObjectType*     objectType   = NULL;
ArrayType*      arrayType    = NULL;
InstanceType*   instanceType = NULL;
ClassType*      classType    = NULL;
AddressType*    addressType  = NULL;
IllegalType*    illegalType  = NULL;
IntConstant*    intZero      = NULL;
IntConstant*    intOne       = NULL;
ObjectConstant* objectNull   = NULL;
void ValueType::initialize(Arena* arena) {
  voidType     = new (arena) VoidType();
  intType      = new (arena) IntType();
  longType     = new (arena) LongType();
  floatType    = new (arena) FloatType();
  doubleType   = new (arena) DoubleType();
  objectType   = new (arena) ObjectType();
  arrayType    = new (arena) ArrayType();
  instanceType = new (arena) InstanceType();
  classType    = new (arena) ClassType();
  addressType  = new (arena) AddressType();
  illegalType  = new (arena) IllegalType();
  intZero     = new (arena) IntConstant(0);
  intOne      = new (arena) IntConstant(1);
  objectNull  = new (arena) ObjectConstant(ciNullObject::make());
};
ValueType* ValueType::meet(ValueType* y) const {
  assert(tag() == y->tag(), "types must match");
  return base();
}
ValueType* ValueType::join(ValueType* y) const {
  Unimplemented();
  return NULL;
}
ciType* ObjectConstant::exact_type() const {
  ciObject* c = constant_value();
  return (c != NULL && !c->is_null_object()) ? c->klass() : NULL;
}
ciType* ArrayConstant::exact_type() const {
  ciObject* c = constant_value();
  return (c != NULL && !c->is_null_object()) ? c->klass() : NULL;
}
ciType* InstanceConstant::exact_type() const {
  ciObject* c = constant_value();
  return (c != NULL && !c->is_null_object()) ? c->klass() : NULL;
}
ciType* ClassConstant::exact_type() const {
  return Compilation::current()->env()->Class_klass();
}
jobject ObjectType::encoding() const {
  assert(is_constant(), "must be");
  return constant_value()->constant_encoding();
}
bool ObjectType::is_loaded() const {
  assert(is_constant(), "must be");
  return constant_value()->is_loaded();
}
bool MetadataType::is_loaded() const {
  assert(is_constant(), "must be");
  return constant_value()->is_loaded();
}
ciObject* ObjectConstant::constant_value() const                   { return _value; }
ciObject* ArrayConstant::constant_value() const                    { return _value; }
ciObject* InstanceConstant::constant_value() const                 { return _value; }
ValueType* as_ValueType(BasicType type) {
  switch (type) {
    case T_VOID   : return voidType;
    case T_BYTE   : // fall through
    case T_CHAR   : // fall through
    case T_SHORT  : // fall through
    case T_BOOLEAN: // fall through
    case T_INT    : return intType;
    case T_LONG   : return longType;
    case T_FLOAT  : return floatType;
    case T_DOUBLE : return doubleType;
    case T_ARRAY  : return arrayType;
    case T_OBJECT : return objectType;
    case T_ADDRESS: return addressType;
    case T_ILLEGAL: return illegalType;
  }
  ShouldNotReachHere();
  return illegalType;
}
ValueType* as_ValueType(ciConstant value) {
  switch (value.basic_type()) {
    case T_BYTE   : // fall through
    case T_CHAR   : // fall through
    case T_SHORT  : // fall through
    case T_BOOLEAN: // fall through
    case T_INT    : return new IntConstant   (value.as_int   ());
    case T_LONG   : return new LongConstant  (value.as_long  ());
    case T_FLOAT  : return new FloatConstant (value.as_float ());
    case T_DOUBLE : return new DoubleConstant(value.as_double());
    case T_ARRAY  : // fall through (ciConstant doesn't have an array accessor)
    case T_OBJECT : {
      ciObject* obj = value.as_object();
      if (obj->is_null_object())
        return objectNull;
      if (obj->is_loaded()) {
        if (obj->is_array())
          return new ArrayConstant(obj->as_array());
        else if (obj->is_instance())
          return new InstanceConstant(obj->as_instance());
      }
      return new ObjectConstant(obj);
    }
  }
  ShouldNotReachHere();
  return illegalType;
}
BasicType as_BasicType(ValueType* type) {
  switch (type->tag()) {
    case voidTag:    return T_VOID;
    case intTag:     return T_INT;
    case longTag:    return T_LONG;
    case floatTag:   return T_FLOAT;
    case doubleTag:  return T_DOUBLE;
    case objectTag:  return T_OBJECT;
    case metaDataTag:return T_METADATA;
    case addressTag: return T_ADDRESS;
    case illegalTag: return T_ILLEGAL;
  }
  ShouldNotReachHere();
  return T_ILLEGAL;
}
C:\hotspot-69087d08d473\src\share\vm/c1/c1_ValueType.hpp
#ifndef SHARE_VM_C1_C1_VALUETYPE_HPP
#define SHARE_VM_C1_C1_VALUETYPE_HPP
#include "c1/c1_Compilation.hpp"
#include "ci/ciConstant.hpp"
#include "ci/ciMethodData.hpp"
class ValueType;
class   VoidType;
class   IntType;
class     IntConstant;
class     IntInterval;
class   LongType;
class     LongConstant;
class   FloatType;
class     FloatConstant;
class   DoubleType;
class     DoubleConstant;
class   ObjectType;
class     ObjectConstant;
class     ArrayType;
class       ArrayConstant;
class     InstanceType;
class       InstanceConstant;
class   MetadataType;
class     ClassType;
class       ClassConstant;
class     MethodType;
class       MethodConstant;
class     MethodDataType;
class       MethodDataConstant;
class   AddressType;
class     AddressConstant;
class   IllegalType;
extern VoidType*       voidType;
extern IntType*        intType;
extern LongType*       longType;
extern FloatType*      floatType;
extern DoubleType*     doubleType;
extern ObjectType*     objectType;
extern ArrayType*      arrayType;
extern InstanceType*   instanceType;
extern ClassType*      classType;
extern AddressType*    addressType;
extern IllegalType*    illegalType;
extern IntConstant*    intZero;
extern IntConstant*    intOne;
extern ObjectConstant* objectNull;
enum ValueTag {
  intTag,
  longTag,
  floatTag,
  doubleTag,
  objectTag,
  addressTag,
  metaDataTag,
  number_of_legal_tags,
  voidTag = number_of_legal_tags,
  illegalTag,
  number_of_tags
};
class ValueType: public CompilationResourceObj {
 private:
  const int _size;
  const ValueTag _tag;
  ValueType();
 protected:
  ValueType(ValueTag tag, int size): _tag(tag), _size(size) {}
 public:
  static void initialize(Arena* arena);
  virtual ValueType* base() const                = 0; // the 'canonical' type (e.g., intType for an IntConstant)
  ValueTag tag() const { return _tag; }          // the 'canonical' tag  (useful for type matching)
  int size() const {                             // the size of an object of the type in words
    assert(_size > -1, "shouldn't be asking for size");
    return _size;
  }
  virtual const char tchar() const               = 0; // the type 'character' for printing
  virtual const char* name() const               = 0; // the type name for printing
  virtual bool is_constant() const               { return false; }
  bool is_void()                                 { return tag() == voidTag;   }
  bool is_int()                                  { return tag() == intTag;    }
  bool is_long()                                 { return tag() == longTag;   }
  bool is_float()                                { return tag() == floatTag;  }
  bool is_double()                               { return tag() == doubleTag; }
  bool is_object()                               { return as_ObjectType()   != NULL; }
  bool is_array()                                { return as_ArrayType()    != NULL; }
  bool is_instance()                             { return as_InstanceType() != NULL; }
  bool is_class()                                { return as_ClassType()    != NULL; }
  bool is_method()                               { return as_MethodType()   != NULL; }
  bool is_method_data()                          { return as_MethodDataType() != NULL; }
  bool is_address()                              { return as_AddressType()  != NULL; }
  bool is_illegal()                              { return tag() == illegalTag; }
  bool is_int_kind() const                       { return tag() == intTag || tag() == longTag; }
  bool is_float_kind() const                     { return tag() == floatTag || tag() == doubleTag; }
  bool is_object_kind() const                    { return tag() == objectTag; }
  bool is_single_word() const                    { return _size == 1; }
  bool is_double_word() const                    { return _size == 2; }
  virtual VoidType*         as_VoidType()        { return NULL; }
  virtual IntType*          as_IntType()         { return NULL; }
  virtual LongType*         as_LongType()        { return NULL; }
  virtual FloatType*        as_FloatType()       { return NULL; }
  virtual DoubleType*       as_DoubleType()      { return NULL; }
  virtual ObjectType*       as_ObjectType()      { return NULL; }
  virtual ArrayType*        as_ArrayType()       { return NULL; }
  virtual InstanceType*     as_InstanceType()    { return NULL; }
  virtual ClassType*        as_ClassType()       { return NULL; }
  virtual MetadataType*     as_MetadataType()    { return NULL; }
  virtual MethodType*       as_MethodType()      { return NULL; }
  virtual MethodDataType*   as_MethodDataType()  { return NULL; }
  virtual AddressType*      as_AddressType()     { return NULL; }
  virtual IllegalType*      as_IllegalType()     { return NULL; }
  virtual IntConstant*      as_IntConstant()     { return NULL; }
  virtual LongConstant*     as_LongConstant()    { return NULL; }
  virtual FloatConstant*    as_FloatConstant()   { return NULL; }
  virtual DoubleConstant*   as_DoubleConstant()  { return NULL; }
  virtual ObjectConstant*   as_ObjectConstant()  { return NULL; }
  virtual InstanceConstant* as_InstanceConstant(){ return NULL; }
  virtual ClassConstant*    as_ClassConstant()   { return NULL; }
  virtual MethodConstant*   as_MethodConstant()  { return NULL; }
  virtual MethodDataConstant* as_MethodDataConstant() { return NULL; }
  virtual ArrayConstant*    as_ArrayConstant()   { return NULL; }
  virtual AddressConstant*  as_AddressConstant() { return NULL; }
  ValueType* meet(ValueType* y) const;
  ValueType* join(ValueType* y) const;
  void print(outputStream* s = tty)              { s->print("%s", name()); }
};
class VoidType: public ValueType {
 public:
  VoidType(): ValueType(voidTag, 0) {}
  virtual ValueType* base() const                { return voidType; }
  virtual const char tchar() const               { return 'v'; }
  virtual const char* name() const               { return "void"; }
  virtual VoidType* as_VoidType()                { return this; }
};
class IntType: public ValueType {
 public:
  IntType(): ValueType(intTag, 1) {}
  virtual ValueType* base() const                { return intType; }
  virtual const char tchar() const               { return 'i'; }
  virtual const char* name() const               { return "int"; }
  virtual IntType* as_IntType()                  { return this; }
};
class IntConstant: public IntType {
 private:
  jint _value;
 public:
  IntConstant(jint value)                        { _value = value; }
  jint value() const                             { return _value; }
  virtual bool is_constant() const               { return true; }
  virtual IntConstant* as_IntConstant()          { return this; }
};
class IntInterval: public IntType {
 private:
  jint _beg;
  jint _end;
 public:
  IntInterval(jint beg, jint end) {
    assert(beg <= end, "illegal interval");
    _beg = beg;
    _end = end;
  }
  jint beg() const                               { return _beg; }
  jint end() const                               { return _end; }
  virtual bool is_interval() const               { return true; }
};
class LongType: public ValueType {
 public:
  LongType(): ValueType(longTag, 2) {}
  virtual ValueType* base() const                { return longType; }
  virtual const char tchar() const               { return 'l'; }
  virtual const char* name() const               { return "long"; }
  virtual LongType* as_LongType()                { return this; }
};
class LongConstant: public LongType {
 private:
  jlong _value;
 public:
  LongConstant(jlong value)                      { _value = value; }
  jlong value() const                            { return _value; }
  virtual bool is_constant() const               { return true; }
  virtual LongConstant* as_LongConstant()        { return this; }
};
class FloatType: public ValueType {
 public:
  FloatType(): ValueType(floatTag, 1) {}
  virtual ValueType* base() const                { return floatType; }
  virtual const char tchar() const               { return 'f'; }
  virtual const char* name() const               { return "float"; }
  virtual FloatType* as_FloatType()              { return this; }
};
class FloatConstant: public FloatType {
 private:
  jfloat _value;
 public:
  FloatConstant(jfloat value)                    { _value = value; }
  jfloat value() const                           { return _value; }
  virtual bool is_constant() const               { return true; }
  virtual FloatConstant* as_FloatConstant()      { return this; }
};
class DoubleType: public ValueType {
 public:
  DoubleType(): ValueType(doubleTag, 2) {}
  virtual ValueType* base() const                { return doubleType; }
  virtual const char tchar() const               { return 'd'; }
  virtual const char* name() const               { return "double"; }
  virtual DoubleType* as_DoubleType()            { return this; }
};
class DoubleConstant: public DoubleType {
 private:
  jdouble _value;
 public:
  DoubleConstant(jdouble value)                  { _value = value; }
  jdouble value() const                          { return _value; }
  virtual bool is_constant() const               { return true; }
  virtual DoubleConstant* as_DoubleConstant()    { return this; }
};
class ObjectType: public ValueType {
 public:
  ObjectType(): ValueType(objectTag, 1) {}
  virtual ValueType* base() const                { return objectType; }
  virtual const char tchar() const               { return 'a'; }
  virtual const char* name() const               { return "object"; }
  virtual ObjectType* as_ObjectType()            { return this; }
  virtual ciObject* constant_value() const       { ShouldNotReachHere(); return NULL; }
  virtual ciType* exact_type() const             { return NULL; }
  bool is_loaded() const;
  jobject encoding() const;
};
class ObjectConstant: public ObjectType {
 private:
  ciObject* _value;
 public:
  ObjectConstant(ciObject* value)                { _value = value; }
  ciObject* value() const                        { return _value; }
  virtual bool is_constant() const               { return true; }
  virtual ObjectConstant* as_ObjectConstant()    { return this; }
  virtual ciObject* constant_value() const;
  virtual ciType* exact_type() const;
};
class ArrayType: public ObjectType {
 public:
  virtual ArrayType* as_ArrayType()              { return this; }
};
class ArrayConstant: public ArrayType {
 private:
  ciArray* _value;
 public:
  ArrayConstant(ciArray* value)                  { _value = value; }
  ciArray* value() const                         { return _value; }
  virtual bool is_constant() const               { return true; }
  virtual ArrayConstant* as_ArrayConstant()      { return this; }
  virtual ciObject* constant_value() const;
  virtual ciType* exact_type() const;
};
class InstanceType: public ObjectType {
 public:
  virtual InstanceType* as_InstanceType()        { return this; }
};
class InstanceConstant: public InstanceType {
 private:
  ciInstance* _value;
 public:
  InstanceConstant(ciInstance* value)            { _value = value; }
  ciInstance* value() const                      { return _value; }
  virtual bool is_constant() const               { return true; }
  virtual InstanceConstant* as_InstanceConstant(){ return this; }
  virtual ciObject* constant_value() const;
  virtual ciType* exact_type() const;
};
class MetadataType: public ValueType {
 public:
  MetadataType(): ValueType(metaDataTag, 1) {}
  virtual ValueType* base() const                       { return objectType; }
  virtual const char tchar() const                      { return 'a'; }
  virtual const char* name() const                      { return "object"; }
  virtual MetadataType* as_MetadataType()               { return this; }
  bool is_loaded() const;
  jobject encoding() const;
  virtual ciMetadata* constant_value() const            { ShouldNotReachHere(); return NULL;  }
};
class ClassType: public MetadataType {
 public:
  virtual ClassType* as_ClassType()              { return this; }
};
class ClassConstant: public ClassType {
 private:
  ciInstanceKlass* _value;
 public:
  ClassConstant(ciInstanceKlass* value)          { _value = value; }
  ciInstanceKlass* value() const                 { return _value; }
  virtual bool is_constant() const               { return true; }
  virtual ClassConstant* as_ClassConstant()      { return this; }
  virtual ciMetadata* constant_value() const            { return _value; }
  virtual ciType* exact_type() const;
};
class MethodType: public MetadataType {
 public:
  virtual MethodType* as_MethodType()                   { return this; }
};
class MethodConstant: public MethodType {
 private:
  ciMethod* _value;
 public:
  MethodConstant(ciMethod* value)                       { _value = value; }
  ciMethod* value() const                               { return _value; }
  virtual bool is_constant() const                      { return true; }
  virtual MethodConstant* as_MethodConstant()           { return this; }
  virtual ciMetadata* constant_value() const            { return _value; }
};
class MethodDataType: public MetadataType {
 public:
  virtual MethodDataType* as_MethodDataType()           { return this; }
};
class MethodDataConstant: public MethodDataType {
 private:
  ciMethodData* _value;
 public:
  MethodDataConstant(ciMethodData* value)               { _value = value; }
  ciMethodData* value() const                           { return _value; }
  virtual bool is_constant() const                      { return true; }
  virtual MethodDataConstant* as_MethodDataConstant()   { return this; }
  virtual ciMetadata* constant_value() const            { return _value; }
};
class AddressType: public ValueType {
 public:
  AddressType(): ValueType(addressTag, 1) {}
  virtual ValueType* base() const                { return addressType; }
  virtual const char tchar() const               { return 'r'; }
  virtual const char* name() const               { return "address"; }
  virtual AddressType* as_AddressType()          { return this; }
};
class AddressConstant: public AddressType {
 private:
  jint _value;
 public:
  AddressConstant(jint value)                    { _value = value; }
  jint value() const                             { return _value; }
  virtual bool is_constant() const               { return true; }
  virtual AddressConstant* as_AddressConstant()  { return this; }
};
class IllegalType: public ValueType {
 public:
  IllegalType(): ValueType(illegalTag, -1) {}
  virtual ValueType* base() const                { return illegalType; }
  virtual const char tchar() const               { return ' '; }
  virtual const char* name() const               { return "illegal"; }
  virtual IllegalType* as_IllegalType()          { return this; }
};
ValueType* as_ValueType(BasicType type);
ValueType* as_ValueType(ciConstant value);
BasicType  as_BasicType(ValueType* type);
inline ValueType* as_ValueType(ciType* type) { return as_ValueType(type->basic_type()); }
#endif // SHARE_VM_C1_C1_VALUETYPE_HPP
C:\hotspot-69087d08d473\src\share\vm/ci/bcEscapeAnalyzer.cpp
#include "precompiled.hpp"
#include "ci/bcEscapeAnalyzer.hpp"
#include "ci/ciConstant.hpp"
#include "ci/ciField.hpp"
#include "ci/ciMethodBlocks.hpp"
#include "ci/ciStreams.hpp"
#include "interpreter/bytecode.hpp"
#include "utilities/bitMap.inline.hpp"
#ifndef PRODUCT
  #define TRACE_BCEA(level, code)                                            \
    if (EstimateArgEscape && BCEATraceLevel >= level) {                        \
      code;                                                                  \
    }
#else
  #define TRACE_BCEA(level, code)
#endif
class BCEscapeAnalyzer::ArgumentMap {
  uint  _bits;
  enum {MAXBIT = 29,
        ALLOCATED = 1,
        UNKNOWN = 2};
  uint int_to_bit(uint e) const {
    if (e > MAXBIT)
      e = MAXBIT;
    return (1 << (e + 2));
  }
public:
  ArgumentMap()                         { _bits = 0;}
  void set_bits(uint bits)              { _bits = bits;}
  uint get_bits() const                 { return _bits;}
  void clear()                          { _bits = 0;}
  void set_all()                        { _bits = ~0u; }
  bool is_empty() const                 { return _bits == 0; }
  bool contains(uint var) const         { return (_bits & int_to_bit(var)) != 0; }
  bool is_singleton(uint var) const     { return (_bits == int_to_bit(var)); }
  bool contains_unknown() const         { return (_bits & UNKNOWN) != 0; }
  bool contains_allocated() const       { return (_bits & ALLOCATED) != 0; }
  bool contains_vars() const            { return (_bits & (((1 << MAXBIT) -1) << 2)) != 0; }
  void set(uint var)                    { _bits = int_to_bit(var); }
  void add(uint var)                    { _bits |= int_to_bit(var); }
  void add_unknown()                    { _bits = UNKNOWN; }
  void add_allocated()                  { _bits = ALLOCATED; }
  void set_union(const ArgumentMap &am)     { _bits |= am._bits; }
  void set_intersect(const ArgumentMap &am) { _bits |= am._bits; }
  void set_difference(const ArgumentMap &am) { _bits &=  ~am._bits; }
  void operator=(const ArgumentMap &am) { _bits = am._bits; }
  bool operator==(const ArgumentMap &am) { return _bits == am._bits; }
  bool operator!=(const ArgumentMap &am) { return _bits != am._bits; }
};
class BCEscapeAnalyzer::StateInfo {
public:
  ArgumentMap *_vars;
  ArgumentMap *_stack;
  int _stack_height;
  int _max_stack;
  bool _initialized;
  ArgumentMap empty_map;
  StateInfo() {
    empty_map.clear();
  }
  ArgumentMap raw_pop()  { guarantee(_stack_height > 0, "stack underflow"); return _stack[--_stack_height]; }
  ArgumentMap  apop()    { return raw_pop(); }
  void spop()            { raw_pop(); }
  void lpop()            { spop(); spop(); }
  void raw_push(ArgumentMap i)   { guarantee(_stack_height < _max_stack, "stack overflow"); _stack[_stack_height++] = i; }
  void apush(ArgumentMap i)      { raw_push(i); }
  void spush()           { raw_push(empty_map); }
  void lpush()           { spush(); spush(); }
};
void BCEscapeAnalyzer::set_returned(ArgumentMap vars) {
  for (int i = 0; i < _arg_size; i++) {
    if (vars.contains(i))
      _arg_returned.set(i);
  }
  _return_local = _return_local && !(vars.contains_unknown() || vars.contains_allocated());
  _return_allocated = _return_allocated && vars.contains_allocated() && !(vars.contains_unknown() || vars.contains_vars());
}
bool BCEscapeAnalyzer::is_argument(ArgumentMap vars) {
  for (int i = 0; i < _arg_size; i++) {
    if (vars.contains(i))
      return true;
  }
  return false;
}
bool BCEscapeAnalyzer::is_arg_stack(ArgumentMap vars){
  if (_conservative)
    return true;
  for (int i = 0; i < _arg_size; i++) {
    if (vars.contains(i) && _arg_stack.test(i))
      return true;
  }
  return false;
}
bool BCEscapeAnalyzer::returns_all(ArgumentMap vars) {
  for (int i = 0; i < _arg_size; i++) {
    if (vars.contains(i) && !_arg_returned.test(i)) {
      return false;
    }
  }
  return true;
}
void BCEscapeAnalyzer::clear_bits(ArgumentMap vars, VectorSet &bm) {
  for (int i = 0; i < _arg_size; i++) {
    if (vars.contains(i)) {
      bm >>= i;
    }
  }
}
void BCEscapeAnalyzer::set_method_escape(ArgumentMap vars) {
  clear_bits(vars, _arg_local);
  if (vars.contains_allocated()) {
    _allocated_escapes = true;
  }
}
void BCEscapeAnalyzer::set_global_escape(ArgumentMap vars, bool merge) {
  clear_bits(vars, _arg_local);
  clear_bits(vars, _arg_stack);
  if (vars.contains_allocated())
    _allocated_escapes = true;
  if (merge && !vars.is_empty()) {
    if (vars.contains_unknown() || vars.contains_allocated()) {
      _return_local = false;
    }
    if (vars.contains_unknown() || vars.contains_vars()) {
      _return_allocated = false;
    }
    if (_return_local && vars.contains_vars() && !returns_all(vars)) {
      _return_local = false;
    }
  }
}
void BCEscapeAnalyzer::set_dirty(ArgumentMap vars) {
  clear_bits(vars, _dirty);
}
void BCEscapeAnalyzer::set_modified(ArgumentMap vars, int offs, int size) {
  for (int i = 0; i < _arg_size; i++) {
    if (vars.contains(i)) {
      set_arg_modified(i, offs, size);
    }
  }
  if (vars.contains_unknown())
    _unknown_modified = true;
}
bool BCEscapeAnalyzer::is_recursive_call(ciMethod* callee) {
  for (BCEscapeAnalyzer* scope = this; scope != NULL; scope = scope->_parent) {
    if (scope->method() == callee) {
      return true;
    }
  }
  return false;
}
bool BCEscapeAnalyzer::is_arg_modified(int arg, int offset, int size_in_bytes) {
  if (offset == OFFSET_ANY)
    return _arg_modified[arg] != 0;
  assert(arg >= 0 && arg < _arg_size, "must be an argument.");
  bool modified = false;
  int l = offset / HeapWordSize;
  int h = round_to(offset + size_in_bytes, HeapWordSize) / HeapWordSize;
  if (l > ARG_OFFSET_MAX)
    l = ARG_OFFSET_MAX;
  if (h > ARG_OFFSET_MAX+1)
    h = ARG_OFFSET_MAX + 1;
  for (int i = l; i < h; i++) {
    modified = modified || (_arg_modified[arg] & (1 << i)) != 0;
  }
  return modified;
}
void BCEscapeAnalyzer::set_arg_modified(int arg, int offset, int size_in_bytes) {
  if (offset == OFFSET_ANY) {
    _arg_modified[arg] =  (uint) -1;
    return;
  }
  assert(arg >= 0 && arg < _arg_size, "must be an argument.");
  int l = offset / HeapWordSize;
  int h = round_to(offset + size_in_bytes, HeapWordSize) / HeapWordSize;
  if (l > ARG_OFFSET_MAX)
    l = ARG_OFFSET_MAX;
  if (h > ARG_OFFSET_MAX+1)
    h = ARG_OFFSET_MAX + 1;
  for (int i = l; i < h; i++) {
    _arg_modified[arg] |= (1 << i);
  }
}
void BCEscapeAnalyzer::invoke(StateInfo &state, Bytecodes::Code code, ciMethod* target, ciKlass* holder) {
  int i;
  ciInstanceKlass* klass = target->holder();
  ciInstanceKlass* calling_klass = method()->holder();
  ciInstanceKlass* callee_holder = ciEnv::get_instance_klass_for_declared_method_holder(holder);
  ciInstanceKlass* actual_recv = callee_holder;
  if (target->is_loaded() && !target->is_abstract() && target->can_be_statically_bound()) {
    switch (code) {
    case Bytecodes::_invokevirtual:
      code = Bytecodes::_invokespecial;
      break;
    case Bytecodes::_invokehandle:
      code = target->is_static() ? Bytecodes::_invokestatic : Bytecodes::_invokespecial;
      break;
    }
  }
  int arg_size = target->invoke_arg_size(code);
  int arg_base = MAX2(state._stack_height - arg_size, 0);
  bool directly_recursive = (method() == target) &&
               (code != Bytecodes::_invokevirtual || target->is_final_method() || state._stack[arg_base] .is_empty());
  bool skip_callee = true;
  for (i = state._stack_height - 1; i >= arg_base && skip_callee; i--) {
    ArgumentMap arg = state._stack[i];
    skip_callee = !is_argument(arg) || !is_arg_stack(arg) || (directly_recursive && arg.is_singleton(i - arg_base));
  }
  if (code == Bytecodes::_invokedynamic) {
    skip_callee = true;
  }
  if (skip_callee) {
    TRACE_BCEA(3, tty->print_cr("[EA] skipping method %s::%s", holder->name()->as_utf8(), target->name()->as_utf8()));
    for (i = 0; i < arg_size; i++) {
      set_method_escape(state.raw_pop());
    }
    _unknown_modified = true;  // assume the worst since we don't analyze the called method
    return;
  }
  ciMethod* inline_target = NULL;
  if (target->is_loaded() && klass->is_loaded()
      && (klass->is_initialized() || klass->is_interface() && target->holder()->is_initialized())
      && target->is_loaded()) {
    if (code == Bytecodes::_invokestatic
        || code == Bytecodes::_invokespecial
        || code == Bytecodes::_invokevirtual && target->is_final_method()) {
      inline_target = target;
    } else {
      inline_target = target->find_monomorphic_target(calling_klass, callee_holder, actual_recv);
    }
  }
  if (inline_target != NULL && !is_recursive_call(inline_target)) {
    BCEscapeAnalyzer analyzer(inline_target, this);
    bool must_record_dependencies = false;
    for (i = arg_size - 1; i >= 0; i--) {
      ArgumentMap arg = state.raw_pop();
      bool allocated = arg.contains_allocated();
      if (!(is_argument(arg) || allocated))
        continue;
      for (int j = 0; j < _arg_size; j++) {
        if (arg.contains(j)) {
          _arg_modified[j] |= analyzer._arg_modified[i];
        }
      }
      if (!(is_arg_stack(arg) || allocated)) {
      } else if (analyzer.is_arg_stack(i) && !analyzer.is_arg_returned(i)) {
        set_method_escape(arg);
        must_record_dependencies = true;
      } else {
        set_global_escape(arg);
      }
    }
    _unknown_modified = _unknown_modified || analyzer.has_non_arg_side_affects();
    if (must_record_dependencies) {
      if (code == Bytecodes::_invokeinterface || code == Bytecodes::_invokevirtual && !target->is_final_method()) {
        _dependencies.append(actual_recv);
        _dependencies.append(inline_target);
      }
      _dependencies.appendAll(analyzer.dependencies());
    }
  } else {
    TRACE_BCEA(1, tty->print_cr("[EA] virtual method %s is not monomorphic.",
                                target->name()->as_utf8()));
    for (i = 0; i < arg_size; i++) {
      ArgumentMap arg = state.raw_pop();
      if (!is_argument(arg))
        continue;
      set_modified(arg, OFFSET_ANY, type2size[T_INT]*HeapWordSize);
      set_global_escape(arg);
    }
    _unknown_modified = true;  // assume the worst since we don't know the called method
  }
}
bool BCEscapeAnalyzer::contains(uint arg_set1, uint arg_set2) {
  return ((~arg_set1) | arg_set2) == 0;
}
void BCEscapeAnalyzer::iterate_one_block(ciBlock *blk, StateInfo &state, GrowableArray<ciBlock *> &successors) {
  blk->set_processed();
  ciBytecodeStream s(method());
  int limit_bci = blk->limit_bci();
  bool fall_through = false;
  ArgumentMap allocated_obj;
  allocated_obj.add_allocated();
  ArgumentMap unknown_obj;
  unknown_obj.add_unknown();
  ArgumentMap empty_map;
  s.reset_to_bci(blk->start_bci());
  while (s.next() != ciBytecodeStream::EOBC() && s.cur_bci() < limit_bci) {
    fall_through = true;
    switch (s.cur_bc()) {
      case Bytecodes::_nop:
        break;
      case Bytecodes::_aconst_null:
        state.apush(unknown_obj);
        break;
      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:
        state.spush();
        break;
      case Bytecodes::_lconst_0:
      case Bytecodes::_lconst_1:
      case Bytecodes::_dconst_0:
      case Bytecodes::_dconst_1:
        state.lpush();
        break;
      case Bytecodes::_ldc:
      case Bytecodes::_ldc_w:
      case Bytecodes::_ldc2_w:
      {
        int index = s.get_constant_pool_index();
        constantTag tag = s.get_constant_pool_tag(index);
        if (tag.is_long() || tag.is_double()) {
          state.lpush();
        } else if (tag.basic_type() == T_OBJECT) {
          state.apush(unknown_obj);
        } else {
          state.spush();
        }
        break;
      }
      case Bytecodes::_aload:
        state.apush(state._vars[s.get_index()]);
        break;
      case Bytecodes::_iload:
      case Bytecodes::_fload:
      case Bytecodes::_iload_0:
      case Bytecodes::_iload_1:
      case Bytecodes::_iload_2:
      case Bytecodes::_iload_3:
      case Bytecodes::_fload_0:
      case Bytecodes::_fload_1:
      case Bytecodes::_fload_2:
      case Bytecodes::_fload_3:
        state.spush();
        break;
      case Bytecodes::_lload:
      case Bytecodes::_dload:
      case Bytecodes::_lload_0:
      case Bytecodes::_lload_1:
      case Bytecodes::_lload_2:
      case Bytecodes::_lload_3:
      case Bytecodes::_dload_0:
      case Bytecodes::_dload_1:
      case Bytecodes::_dload_2:
      case Bytecodes::_dload_3:
        state.lpush();
        break;
      case Bytecodes::_aload_0:
        state.apush(state._vars[0]);
        break;
      case Bytecodes::_aload_1:
        state.apush(state._vars[1]);
        break;
      case Bytecodes::_aload_2:
        state.apush(state._vars[2]);
        break;
      case Bytecodes::_aload_3:
        state.apush(state._vars[3]);
        break;
      case Bytecodes::_iaload:
      case Bytecodes::_faload:
      case Bytecodes::_baload:
      case Bytecodes::_caload:
      case Bytecodes::_saload:
        state.spop();
        set_method_escape(state.apop());
        state.spush();
        break;
      case Bytecodes::_laload:
      case Bytecodes::_daload:
        state.spop();
        set_method_escape(state.apop());
        state.lpush();
        break;
      case Bytecodes::_aaload:
        { state.spop();
          ArgumentMap array = state.apop();
          set_method_escape(array);
          state.apush(unknown_obj);
          set_dirty(array);
        }
        break;
      case Bytecodes::_istore:
      case Bytecodes::_fstore:
      case Bytecodes::_istore_0:
      case Bytecodes::_istore_1:
      case Bytecodes::_istore_2:
      case Bytecodes::_istore_3:
      case Bytecodes::_fstore_0:
      case Bytecodes::_fstore_1:
      case Bytecodes::_fstore_2:
      case Bytecodes::_fstore_3:
        state.spop();
        break;
      case Bytecodes::_lstore:
      case Bytecodes::_dstore:
      case Bytecodes::_lstore_0:
      case Bytecodes::_lstore_1:
      case Bytecodes::_lstore_2:
      case Bytecodes::_lstore_3:
      case Bytecodes::_dstore_0:
      case Bytecodes::_dstore_1:
      case Bytecodes::_dstore_2:
      case Bytecodes::_dstore_3:
        state.lpop();
        break;
      case Bytecodes::_astore:
        state._vars[s.get_index()] = state.apop();
        break;
      case Bytecodes::_astore_0:
        state._vars[0] = state.apop();
        break;
      case Bytecodes::_astore_1:
        state._vars[1] = state.apop();
        break;
      case Bytecodes::_astore_2:
        state._vars[2] = state.apop();
        break;
      case Bytecodes::_astore_3:
        state._vars[3] = state.apop();
        break;
      case Bytecodes::_iastore:
      case Bytecodes::_fastore:
      case Bytecodes::_bastore:
      case Bytecodes::_castore:
      case Bytecodes::_sastore:
      {
        state.spop();
        state.spop();
        ArgumentMap arr = state.apop();
        set_method_escape(arr);
        set_modified(arr, OFFSET_ANY, type2size[T_INT]*HeapWordSize);
        break;
      }
      case Bytecodes::_lastore:
      case Bytecodes::_dastore:
      {
        state.lpop();
        state.spop();
        ArgumentMap arr = state.apop();
        set_method_escape(arr);
        set_modified(arr, OFFSET_ANY, type2size[T_LONG]*HeapWordSize);
        break;
      }
      case Bytecodes::_aastore:
      {
        set_global_escape(state.apop());
        state.spop();
        ArgumentMap arr = state.apop();
        set_modified(arr, OFFSET_ANY, type2size[T_OBJECT]*HeapWordSize);
        break;
      }
      case Bytecodes::_pop:
        state.raw_pop();
        break;
      case Bytecodes::_pop2:
        state.raw_pop();
        state.raw_pop();
        break;
      case Bytecodes::_dup:
        { ArgumentMap w1 = state.raw_pop();
          state.raw_push(w1);
          state.raw_push(w1);
        }
        break;
      case Bytecodes::_dup_x1:
        { ArgumentMap w1 = state.raw_pop();
          ArgumentMap w2 = state.raw_pop();
          state.raw_push(w1);
          state.raw_push(w2);
          state.raw_push(w1);
        }
        break;
      case Bytecodes::_dup_x2:
        { ArgumentMap w1 = state.raw_pop();
          ArgumentMap w2 = state.raw_pop();
          ArgumentMap w3 = state.raw_pop();
          state.raw_push(w1);
          state.raw_push(w3);
          state.raw_push(w2);
          state.raw_push(w1);
        }
        break;
      case Bytecodes::_dup2:
        { ArgumentMap w1 = state.raw_pop();
          ArgumentMap w2 = state.raw_pop();
          state.raw_push(w2);
          state.raw_push(w1);
          state.raw_push(w2);
          state.raw_push(w1);
        }
        break;
      case Bytecodes::_dup2_x1:
        { ArgumentMap w1 = state.raw_pop();
          ArgumentMap w2 = state.raw_pop();
          ArgumentMap w3 = state.raw_pop();
          state.raw_push(w2);
          state.raw_push(w1);
          state.raw_push(w3);
          state.raw_push(w2);
          state.raw_push(w1);
        }
        break;
      case Bytecodes::_dup2_x2:
        { ArgumentMap w1 = state.raw_pop();
          ArgumentMap w2 = state.raw_pop();
          ArgumentMap w3 = state.raw_pop();
          ArgumentMap w4 = state.raw_pop();
          state.raw_push(w2);
          state.raw_push(w1);
          state.raw_push(w4);
          state.raw_push(w3);
          state.raw_push(w2);
          state.raw_push(w1);
        }
        break;
      case Bytecodes::_swap:
        { ArgumentMap w1 = state.raw_pop();
          ArgumentMap w2 = state.raw_pop();
          state.raw_push(w1);
          state.raw_push(w2);
        }
        break;
      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::_iand:
      case Bytecodes::_ior:
      case Bytecodes::_ixor:
        state.spop();
        state.spop();
        state.spush();
        break;
      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:
        state.lpop();
        state.lpop();
        state.lpush();
        break;
      case Bytecodes::_ishl:
      case Bytecodes::_ishr:
      case Bytecodes::_iushr:
        state.spop();
        state.spop();
        state.spush();
        break;
      case Bytecodes::_lshl:
      case Bytecodes::_lshr:
      case Bytecodes::_lushr:
        state.spop();
        state.lpop();
        state.lpush();
        break;
      case Bytecodes::_ineg:
      case Bytecodes::_fneg:
        state.spop();
        state.spush();
        break;
      case Bytecodes::_lneg:
      case Bytecodes::_dneg:
        state.lpop();
        state.lpush();
        break;
      case Bytecodes::_iinc:
        break;
      case Bytecodes::_i2l:
      case Bytecodes::_i2d:
      case Bytecodes::_f2l:
      case Bytecodes::_f2d:
        state.spop();
        state.lpush();
        break;
      case Bytecodes::_i2f:
      case Bytecodes::_f2i:
        state.spop();
        state.spush();
        break;
      case Bytecodes::_l2i:
      case Bytecodes::_l2f:
      case Bytecodes::_d2i:
      case Bytecodes::_d2f:
        state.lpop();
        state.spush();
        break;
      case Bytecodes::_l2d:
      case Bytecodes::_d2l:
        state.lpop();
        state.lpush();
        break;
      case Bytecodes::_i2b:
      case Bytecodes::_i2c:
      case Bytecodes::_i2s:
        state.spop();
        state.spush();
        break;
      case Bytecodes::_lcmp:
      case Bytecodes::_dcmpl:
      case Bytecodes::_dcmpg:
        state.lpop();
        state.lpop();
        state.spush();
        break;
      case Bytecodes::_fcmpl:
      case Bytecodes::_fcmpg:
        state.spop();
        state.spop();
        state.spush();
        break;
      case Bytecodes::_ifeq:
      case Bytecodes::_ifne:
      case Bytecodes::_iflt:
      case Bytecodes::_ifge:
      case Bytecodes::_ifgt:
      case Bytecodes::_ifle:
      {
        state.spop();
        int dest_bci = s.get_dest();
        assert(_methodBlocks->is_block_start(dest_bci), "branch destination must start a block");
        assert(s.next_bci() == limit_bci, "branch must end block");
        successors.push(_methodBlocks->block_containing(dest_bci));
        break;
      }
      case Bytecodes::_if_icmpeq:
      case Bytecodes::_if_icmpne:
      case Bytecodes::_if_icmplt:
      case Bytecodes::_if_icmpge:
      case Bytecodes::_if_icmpgt:
      case Bytecodes::_if_icmple:
      {
        state.spop();
        state.spop();
        int dest_bci = s.get_dest();
        assert(_methodBlocks->is_block_start(dest_bci), "branch destination must start a block");
        assert(s.next_bci() == limit_bci, "branch must end block");
        successors.push(_methodBlocks->block_containing(dest_bci));
        break;
      }
      case Bytecodes::_if_acmpeq:
      case Bytecodes::_if_acmpne:
      {
        set_method_escape(state.apop());
        set_method_escape(state.apop());
        int dest_bci = s.get_dest();
        assert(_methodBlocks->is_block_start(dest_bci), "branch destination must start a block");
        assert(s.next_bci() == limit_bci, "branch must end block");
        successors.push(_methodBlocks->block_containing(dest_bci));
        break;
      }
      case Bytecodes::_goto:
      {
        int dest_bci = s.get_dest();
        assert(_methodBlocks->is_block_start(dest_bci), "branch destination must start a block");
        assert(s.next_bci() == limit_bci, "branch must end block");
        successors.push(_methodBlocks->block_containing(dest_bci));
        fall_through = false;
        break;
      }
      case Bytecodes::_jsr:
      {
        int dest_bci = s.get_dest();
        assert(_methodBlocks->is_block_start(dest_bci), "branch destination must start a block");
        assert(s.next_bci() == limit_bci, "branch must end block");
        state.apush(empty_map);
        successors.push(_methodBlocks->block_containing(dest_bci));
        fall_through = false;
        break;
      }
      case Bytecodes::_ret:
        assert(s.next_bci() == limit_bci, "branch must end block");
        fall_through = false;
        break;
      case Bytecodes::_return:
        assert(s.next_bci() == limit_bci, "return must end block");
        fall_through = false;
        break;
      case Bytecodes::_tableswitch:
        {
          state.spop();
          Bytecode_tableswitch sw(&s);
          int len = sw.length();
          int dest_bci;
          for (int i = 0; i < len; i++) {
            dest_bci = s.cur_bci() + sw.dest_offset_at(i);
            assert(_methodBlocks->is_block_start(dest_bci), "branch destination must start a block");
            successors.push(_methodBlocks->block_containing(dest_bci));
          }
          dest_bci = s.cur_bci() + sw.default_offset();
          assert(_methodBlocks->is_block_start(dest_bci), "branch destination must start a block");
          successors.push(_methodBlocks->block_containing(dest_bci));
          assert(s.next_bci() == limit_bci, "branch must end block");
          fall_through = false;
          break;
        }
      case Bytecodes::_lookupswitch:
        {
          state.spop();
          Bytecode_lookupswitch sw(&s);
          int len = sw.number_of_pairs();
          int dest_bci;
          for (int i = 0; i < len; i++) {
            dest_bci = s.cur_bci() + sw.pair_at(i).offset();
            assert(_methodBlocks->is_block_start(dest_bci), "branch destination must start a block");
            successors.push(_methodBlocks->block_containing(dest_bci));
          }
          dest_bci = s.cur_bci() + sw.default_offset();
          assert(_methodBlocks->is_block_start(dest_bci), "branch destination must start a block");
          successors.push(_methodBlocks->block_containing(dest_bci));
          fall_through = false;
          break;
        }
      case Bytecodes::_ireturn:
      case Bytecodes::_freturn:
        state.spop();
        fall_through = false;
        break;
      case Bytecodes::_lreturn:
      case Bytecodes::_dreturn:
        state.lpop();
        fall_through = false;
        break;
      case Bytecodes::_areturn:
        set_returned(state.apop());
        fall_through = false;
        break;
      case Bytecodes::_getstatic:
      case Bytecodes::_getfield:
        { bool ignored_will_link;
          ciField* field = s.get_field(ignored_will_link);
          BasicType field_type = field->type()->basic_type();
          if (s.cur_bc() != Bytecodes::_getstatic) {
            set_method_escape(state.apop());
          }
          if (field_type == T_OBJECT || field_type == T_ARRAY) {
            state.apush(unknown_obj);
          } else if (type2size[field_type] == 1) {
            state.spush();
          } else {
            state.lpush();
          }
        }
        break;
      case Bytecodes::_putstatic:
      case Bytecodes::_putfield:
        { bool will_link;
          ciField* field = s.get_field(will_link);
          BasicType field_type = field->type()->basic_type();
          if (field_type == T_OBJECT || field_type == T_ARRAY) {
            set_global_escape(state.apop());
          } else if (type2size[field_type] == 1) {
            state.spop();
          } else {
            state.lpop();
          }
          if (s.cur_bc() != Bytecodes::_putstatic) {
            ArgumentMap p = state.apop();
            set_method_escape(p);
            set_modified(p, will_link ? field->offset() : OFFSET_ANY, type2size[field_type]*HeapWordSize);
          }
        }
        break;
      case Bytecodes::_invokevirtual:
      case Bytecodes::_invokespecial:
      case Bytecodes::_invokestatic:
      case Bytecodes::_invokedynamic:
      case Bytecodes::_invokeinterface:
        { bool ignored_will_link;
          ciSignature* declared_signature = NULL;
          ciMethod* target = s.get_method(ignored_will_link, &declared_signature);
          ciKlass*  holder = s.get_declared_method_holder();
          assert(declared_signature != NULL, "cannot be null");
          if (s.has_appendix()) {
            state.apush(unknown_obj);
          }
          invoke(state, s.cur_bc_raw(), target, holder);
          ciType* return_type = declared_signature->return_type();
          if (!return_type->is_primitive_type()) {
            state.apush(unknown_obj);
          } else if (return_type->is_one_word()) {
            state.spush();
          } else if (return_type->is_two_word()) {
            state.lpush();
          }
        }
        break;
      case Bytecodes::_new:
        state.apush(allocated_obj);
        break;
      case Bytecodes::_newarray:
      case Bytecodes::_anewarray:
        state.spop();
        state.apush(allocated_obj);
        break;
      case Bytecodes::_multianewarray:
        { int i = s.cur_bcp()[3];
          while (i-- > 0) state.spop();
          state.apush(allocated_obj);
        }
        break;
      case Bytecodes::_arraylength:
        set_method_escape(state.apop());
        state.spush();
        break;
      case Bytecodes::_athrow:
        set_global_escape(state.apop());
        fall_through = false;
        break;
      case Bytecodes::_checkcast:
        { ArgumentMap obj = state.apop();
          set_method_escape(obj);
          state.apush(obj);
        }
        break;
      case Bytecodes::_instanceof:
        set_method_escape(state.apop());
        state.spush();
        break;
      case Bytecodes::_monitorenter:
      case Bytecodes::_monitorexit:
        state.apop();
        break;
      case Bytecodes::_wide:
        ShouldNotReachHere();
        break;
      case Bytecodes::_ifnull:
      case Bytecodes::_ifnonnull:
      {
        set_method_escape(state.apop());
        int dest_bci = s.get_dest();
        assert(_methodBlocks->is_block_start(dest_bci), "branch destination must start a block");
        assert(s.next_bci() == limit_bci, "branch must end block");
        successors.push(_methodBlocks->block_containing(dest_bci));
        break;
      }
      case Bytecodes::_goto_w:
      {
        int dest_bci = s.get_far_dest();
        assert(_methodBlocks->is_block_start(dest_bci), "branch destination must start a block");
        assert(s.next_bci() == limit_bci, "branch must end block");
        successors.push(_methodBlocks->block_containing(dest_bci));
        fall_through = false;
        break;
      }
      case Bytecodes::_jsr_w:
      {
        int dest_bci = s.get_far_dest();
        assert(_methodBlocks->is_block_start(dest_bci), "branch destination must start a block");
        assert(s.next_bci() == limit_bci, "branch must end block");
        state.apush(empty_map);
        successors.push(_methodBlocks->block_containing(dest_bci));
        fall_through = false;
        break;
      }
      case Bytecodes::_breakpoint:
        break;
      default:
        ShouldNotReachHere();
        break;
    }
  }
  if (fall_through) {
    int fall_through_bci = s.cur_bci();
    if (fall_through_bci < _method->code_size()) {
      assert(_methodBlocks->is_block_start(fall_through_bci), "must fall through to block start.");
      successors.push(_methodBlocks->block_containing(fall_through_bci));
    }
  }
}
void BCEscapeAnalyzer::merge_block_states(StateInfo *blockstates, ciBlock *dest, StateInfo *s_state) {
  StateInfo *d_state = blockstates + dest->index();
  int nlocals = _method->max_locals();
  if (dest->is_handler())
    return;
  if (!d_state->_initialized ) {
    for (int i = 0; i < nlocals; i++) {
      d_state->_vars[i] = s_state->_vars[i];
    }
    for (int i = 0; i < s_state->_stack_height; i++) {
      d_state->_stack[i] = s_state->_stack[i];
    }
    d_state->_stack_height = s_state->_stack_height;
    d_state->_max_stack = s_state->_max_stack;
    d_state->_initialized = true;
  } else if (!dest->processed()) {
    assert(d_state->_stack_height == s_state->_stack_height, "computed stack heights must match");
    for (int i = 0; i < nlocals; i++) {
      d_state->_vars[i].set_union(s_state->_vars[i]);
    }
    for (int i = 0; i < s_state->_stack_height; i++) {
      d_state->_stack[i].set_union(s_state->_stack[i]);
    }
  } else {
    assert(d_state->_stack_height == s_state->_stack_height, "computed stack heights must match");
    ArgumentMap extra_vars;
    for (int i = 0; i < nlocals; i++) {
      ArgumentMap t;
      t = s_state->_vars[i];
      t.set_difference(d_state->_vars[i]);
      extra_vars.set_union(t);
    }
    for (int i = 0; i < s_state->_stack_height; i++) {
      ArgumentMap t;
      t.clear();
      t = s_state->_stack[i];
      t.set_difference(d_state->_stack[i]);
      extra_vars.set_union(t);
    }
    set_global_escape(extra_vars, true);
  }
}
void BCEscapeAnalyzer::iterate_blocks(Arena *arena) {
  int numblocks = _methodBlocks->num_blocks();
  int stkSize   = _method->max_stack();
  int numLocals = _method->max_locals();
  StateInfo state;
  int datacount = (numblocks + 1) * (stkSize + numLocals);
  int datasize = datacount * sizeof(ArgumentMap);
  StateInfo *blockstates = (StateInfo *) arena->Amalloc(numblocks * sizeof(StateInfo));
  ArgumentMap *statedata  = (ArgumentMap *) arena->Amalloc(datasize);
  for (int i = 0; i < datacount; i++) ::new ((void*)&statedata[i]) ArgumentMap();
  ArgumentMap *dp = statedata;
  state._vars = dp;
  dp += numLocals;
  state._stack = dp;
  dp += stkSize;
  state._initialized = false;
  state._max_stack = stkSize;
  for (int i = 0; i < numblocks; i++) {
    blockstates[i]._vars = dp;
    dp += numLocals;
    blockstates[i]._stack = dp;
    dp += stkSize;
    blockstates[i]._initialized = false;
    blockstates[i]._stack_height = 0;
    blockstates[i]._max_stack  = stkSize;
  }
  GrowableArray<ciBlock *> worklist(arena, numblocks / 4, 0, NULL);
  GrowableArray<ciBlock *> successors(arena, 4, 0, NULL);
  _methodBlocks->clear_processed();
  ArgumentMap allVars;   // all oop arguments to method
  ciSignature* sig = method()->signature();
  int j = 0;
  ciBlock* first_blk = _methodBlocks->block_containing(0);
  int fb_i = first_blk->index();
  if (!method()->is_static()) {
    blockstates[fb_i]._vars[j].set(j);
    allVars.add(j);
    j++;
  }
  for (int i = 0; i < sig->count(); i++) {
    ciType* t = sig->type_at(i);
    if (!t->is_primitive_type()) {
      blockstates[fb_i]._vars[j].set(j);
      allVars.add(j);
    }
    j += t->size();
  }
  blockstates[fb_i]._initialized = true;
  assert(j == _arg_size, "just checking");
  ArgumentMap unknown_map;
  unknown_map.add_unknown();
  worklist.push(first_blk);
  while(worklist.length() > 0) {
    ciBlock *blk = worklist.pop();
    StateInfo *blkState = blockstates + blk->index();
    if (blk->is_handler() || blk->is_ret_target()) {
      for (int i = 0; i < numLocals; i++) {
        state._vars[i] = allVars;
      }
      if (blk->is_handler()) {
        state._stack_height = 1;
      } else {
        state._stack_height = blkState->_stack_height;
      }
      for (int i = 0; i < state._stack_height; i++) {
        state._stack[i] = allVars;
      }
    } else {
      for (int i = 0; i < numLocals; i++) {
        state._vars[i] = blkState->_vars[i];
      }
      for (int i = 0; i < blkState->_stack_height; i++) {
        state._stack[i] = blkState->_stack[i];
      }
      state._stack_height = blkState->_stack_height;
    }
    iterate_one_block(blk, state, successors);
    if (blk->has_handler()) {
      DEBUG_ONLY(int handler_count = 0;)
      int blk_start = blk->start_bci();
      int blk_end = blk->limit_bci();
      for (int i = 0; i < numblocks; i++) {
        ciBlock *b = _methodBlocks->block(i);
        if (b->is_handler()) {
          int ex_start = b->ex_start_bci();
          int ex_end = b->ex_limit_bci();
          if ((ex_start >= blk_start && ex_start < blk_end) ||
              (ex_end > blk_start && ex_end <= blk_end)) {
            successors.push(b);
          }
          DEBUG_ONLY(handler_count++;)
        }
      }
      assert(handler_count > 0, "must find at least one handler");
    }
    while(successors.length() > 0) {
      ciBlock *succ = successors.pop();
      merge_block_states(blockstates, succ, &state);
      if (!succ->processed())
        worklist.push(succ);
    }
  }
}
void BCEscapeAnalyzer::do_analysis() {
  Arena* arena = CURRENT_ENV->arena();
  _methodBlocks = _method->get_method_blocks();
  iterate_blocks(arena);
}
vmIntrinsics::ID BCEscapeAnalyzer::known_intrinsic() {
  vmIntrinsics::ID iid = method()->intrinsic_id();
  if (iid == vmIntrinsics::_getClass ||
      iid ==  vmIntrinsics::_fillInStackTrace ||
      iid == vmIntrinsics::_hashCode) {
    return iid;
  } else {
    return vmIntrinsics::_none;
  }
}
void BCEscapeAnalyzer::compute_escape_for_intrinsic(vmIntrinsics::ID iid) {
  ArgumentMap arg;
  arg.clear();
  switch (iid) {
    case vmIntrinsics::_getClass:
      _return_local = false;
      _return_allocated = false;
      break;
    case vmIntrinsics::_fillInStackTrace:
      arg.set(0); // 'this'
      set_returned(arg);
      break;
    case vmIntrinsics::_hashCode:
      break;
  default:
    assert(false, "unexpected intrinsic");
  }
}
void BCEscapeAnalyzer::initialize() {
  int i;
  methodData()->clear_escape_info();
  ciSignature* sig = method()->signature();
  int j = 0;
  if (!method()->is_static()) {
    _arg_local.set(0);
    _arg_stack.set(0);
    j++;
  }
  for (i = 0; i < sig->count(); i++) {
    ciType* t = sig->type_at(i);
    if (!t->is_primitive_type()) {
      _arg_local.set(j);
      _arg_stack.set(j);
    }
    j += t->size();
  }
  assert(j == _arg_size, "just checking");
  ciType *rt = _method->return_type();
  if (rt->is_primitive_type()) {
    _return_local = false;
    _return_allocated = false;
  } else {
    _return_local = true;
    _return_allocated = true;
  }
  _allocated_escapes = false;
  _unknown_modified = false;
}
void BCEscapeAnalyzer::clear_escape_info() {
  ciSignature* sig = method()->signature();
  int arg_count = sig->count();
  ArgumentMap var;
  if (!method()->is_static()) {
    arg_count++;  // allow for "this"
  }
  for (int i = 0; i < arg_count; i++) {
    set_arg_modified(i, OFFSET_ANY, 4);
    var.clear();
    var.set(i);
    set_modified(var, OFFSET_ANY, 4);
    set_global_escape(var);
  }
  _arg_local.Clear();
  _arg_stack.Clear();
  _arg_returned.Clear();
  _return_local = false;
  _return_allocated = false;
  _allocated_escapes = true;
  _unknown_modified = true;
}
void BCEscapeAnalyzer::compute_escape_info() {
  int i;
  assert(!methodData()->has_escape_info(), "do not overwrite escape info");
  vmIntrinsics::ID iid = known_intrinsic();
  if (iid == vmIntrinsics::_none && (method()->is_abstract() || method()->is_native() || !method()->holder()->is_initialized()
      || _level > MaxBCEAEstimateLevel
      || method()->code_size() > MaxBCEAEstimateSize)) {
    if (BCEATraceLevel >= 1) {
      tty->print("Skipping method because: ");
      if (method()->is_abstract())
        tty->print_cr("method is abstract.");
      else if (method()->is_native())
        tty->print_cr("method is native.");
      else if (!method()->holder()->is_initialized())
        tty->print_cr("class of method is not initialized.");
      else if (_level > MaxBCEAEstimateLevel)
        tty->print_cr("level (%d) exceeds MaxBCEAEstimateLevel (%d).",
                      _level, (int) MaxBCEAEstimateLevel);
      else if (method()->code_size() > MaxBCEAEstimateSize)
        tty->print_cr("code size (%d) exceeds MaxBCEAEstimateSize (%d).",
                      method()->code_size(), (int) MaxBCEAEstimateSize);
      else
        ShouldNotReachHere();
    }
    clear_escape_info();
    return;
  }
  if (BCEATraceLevel >= 1) {
    tty->print("[EA] estimating escape information for");
    if (iid != vmIntrinsics::_none)
      tty->print(" intrinsic");
    method()->print_short_name();
    tty->print_cr(" (%d bytes)", method()->code_size());
  }
  initialize();
  if (_arg_local.Size() == 0 && !_return_allocated) {
    clear_escape_info();
    methodData()->set_eflag(MethodData::allocated_escapes);
    methodData()->set_eflag(MethodData::unknown_modified);
    methodData()->set_eflag(MethodData::estimated);
    return;
  }
  if (iid != vmIntrinsics::_none)
    compute_escape_for_intrinsic(iid);
  else {
    do_analysis();
  }
  if (!has_dependencies() && !methodData()->is_empty()) {
    for (i = 0; i < _arg_size; i++) {
      if (_arg_local.test(i)) {
        assert(_arg_stack.test(i), "inconsistent escape info");
        methodData()->set_arg_local(i);
        methodData()->set_arg_stack(i);
      } else if (_arg_stack.test(i)) {
        methodData()->set_arg_stack(i);
      }
      if (_arg_returned.test(i)) {
        methodData()->set_arg_returned(i);
      }
      methodData()->set_arg_modified(i, _arg_modified[i]);
    }
    if (_return_local) {
      methodData()->set_eflag(MethodData::return_local);
    }
    if (_return_allocated) {
      methodData()->set_eflag(MethodData::return_allocated);
    }
    if (_allocated_escapes) {
      methodData()->set_eflag(MethodData::allocated_escapes);
    }
    if (_unknown_modified) {
      methodData()->set_eflag(MethodData::unknown_modified);
    }
    methodData()->set_eflag(MethodData::estimated);
  }
}
void BCEscapeAnalyzer::read_escape_info() {
  assert(methodData()->has_escape_info(), "no escape info available");
  for (int i = 0; i < _arg_size; i++) {
    if (methodData()->is_arg_local(i))
      _arg_local.set(i);
    if (methodData()->is_arg_stack(i))
      _arg_stack.set(i);
    if (methodData()->is_arg_returned(i))
      _arg_returned.set(i);
    _arg_modified[i] = methodData()->arg_modified(i);
  }
  _return_local = methodData()->eflag_set(MethodData::return_local);
  _return_allocated = methodData()->eflag_set(MethodData::return_allocated);
  _allocated_escapes = methodData()->eflag_set(MethodData::allocated_escapes);
  _unknown_modified = methodData()->eflag_set(MethodData::unknown_modified);
}
#ifndef PRODUCT
void BCEscapeAnalyzer::dump() {
  tty->print("[EA] estimated escape information for");
  method()->print_short_name();
  tty->print_cr(has_dependencies() ? " (not stored)" : "");
  tty->print("     non-escaping args:      ");
  _arg_local.print_on(tty);
  tty->print("     stack-allocatable args: ");
  _arg_stack.print_on(tty);
  if (_return_local) {
    tty->print("     returned args:          ");
    _arg_returned.print_on(tty);
  } else if (is_return_allocated()) {
    tty->print_cr("     return allocated value");
  } else {
    tty->print_cr("     return non-local value");
  }
  tty->print("     modified args: ");
  for (int i = 0; i < _arg_size; i++) {
    if (_arg_modified[i] == 0)
      tty->print("    0");
    else
      tty->print("    0x%x", _arg_modified[i]);
  }
  tty->cr();
  tty->print("     flags: ");
  if (_return_allocated)
    tty->print(" return_allocated");
  if (_allocated_escapes)
    tty->print(" allocated_escapes");
  if (_unknown_modified)
    tty->print(" unknown_modified");
  tty->cr();
}
#endif
BCEscapeAnalyzer::BCEscapeAnalyzer(ciMethod* method, BCEscapeAnalyzer* parent)
    : _conservative(method == NULL || !EstimateArgEscape)
    , _arena(CURRENT_ENV->arena())
    , _method(method)
    , _methodData(method ? method->method_data() : NULL)
    , _arg_size(method ? method->arg_size() : 0)
    , _arg_local(_arena)
    , _arg_stack(_arena)
    , _arg_returned(_arena)
    , _dirty(_arena)
    , _return_local(false)
    , _return_allocated(false)
    , _allocated_escapes(false)
    , _unknown_modified(false)
    , _dependencies(_arena, 4, 0, NULL)
    , _parent(parent)
    , _level(parent == NULL ? 0 : parent->level() + 1) {
  if (!_conservative) {
    _arg_local.Clear();
    _arg_stack.Clear();
    _arg_returned.Clear();
    _dirty.Clear();
    Arena* arena = CURRENT_ENV->arena();
    _arg_modified = (uint *) arena->Amalloc(_arg_size * sizeof(uint));
    Copy::zero_to_bytes(_arg_modified, _arg_size * sizeof(uint));
    if (methodData() == NULL)
      return;
    bool printit = _method->should_print_assembly();
    if (methodData()->has_escape_info()) {
      TRACE_BCEA(2, tty->print_cr("[EA] Reading previous results for %s.%s",
                                  method->holder()->name()->as_utf8(),
                                  method->name()->as_utf8()));
      read_escape_info();
    } else {
      TRACE_BCEA(2, tty->print_cr("[EA] computing results for %s.%s",
                                  method->holder()->name()->as_utf8(),
                                  method->name()->as_utf8()));
      compute_escape_info();
      methodData()->update_escape_info();
    }
#ifndef PRODUCT
    if (BCEATraceLevel >= 3) {
      dump();
    }
#endif
  }
}
void BCEscapeAnalyzer::copy_dependencies(Dependencies *deps) {
  if (ciEnv::current()->jvmti_can_hotswap_or_post_breakpoint()) {
    deps->assert_evol_method(method());
  }
  for (int i = 0; i < _dependencies.length(); i+=2) {
    ciKlass *k = _dependencies.at(i)->as_klass();
    ciMethod *m = _dependencies.at(i+1)->as_method();
    deps->assert_unique_concrete_method(k, m);
  }
}
C:\hotspot-69087d08d473\src\share\vm/ci/bcEscapeAnalyzer.hpp
#ifndef SHARE_VM_CI_BCESCAPEANALYZER_HPP
#define SHARE_VM_CI_BCESCAPEANALYZER_HPP
#ifdef COMPILER2
#include "ci/ciObject.hpp"
#include "ci/ciMethod.hpp"
#include "ci/ciMethodData.hpp"
#include "code/dependencies.hpp"
#include "libadt/vectset.hpp"
#include "memory/allocation.hpp"
#include "utilities/growableArray.hpp"
#endif
class  ciMethodBlocks;
class  ciBlock;
class BCEscapeAnalyzer : public ResourceObj {
 private:
  Arena*            _arena;        // ciEnv arena
  bool              _conservative; // If true, return maximally
  ciMethod*         _method;
  ciMethodData*     _methodData;
  int               _arg_size;
  VectorSet         _arg_local;
  VectorSet         _arg_stack;
  VectorSet         _arg_returned;
  VectorSet         _dirty;
  enum{ ARG_OFFSET_MAX = 31};
  uint              *_arg_modified;
  bool              _return_local;
  bool              _return_allocated;
  bool              _allocated_escapes;
  bool              _unknown_modified;
  GrowableArray<ciMetadata *> _dependencies;
  ciMethodBlocks   *_methodBlocks;
  BCEscapeAnalyzer* _parent;
  int               _level;
 public:
  class  ArgumentMap;
  class  StateInfo;
 private:
  bool is_argument(int i)    { return i >= 0 && i < _arg_size; }
  void set_returned(ArgumentMap vars);
  bool is_argument(ArgumentMap vars);
  bool is_arg_stack(ArgumentMap vars);
  bool returns_all(ArgumentMap vars);
  void clear_bits(ArgumentMap vars, VectorSet &bs);
  void set_method_escape(ArgumentMap vars);
  void set_global_escape(ArgumentMap vars, bool merge = false);
  void set_dirty(ArgumentMap vars);
  void set_modified(ArgumentMap vars, int offs, int size);
  bool is_recursive_call(ciMethod* callee);
  void add_dependence(ciKlass *klass, ciMethod *meth);
  void propagate_dependencies(ciMethod *meth);
  void invoke(StateInfo &state, Bytecodes::Code code, ciMethod* target, ciKlass* holder);
  void iterate_one_block(ciBlock *blk, StateInfo &state, GrowableArray<ciBlock *> &successors);
  void iterate_blocks(Arena *);
  void merge_block_states(StateInfo *blockstates, ciBlock *dest, StateInfo *s_state);
  void initialize();
  void clear_escape_info();
  void compute_escape_info();
  vmIntrinsics::ID known_intrinsic();
  void compute_escape_for_intrinsic(vmIntrinsics::ID iid);
  void do_analysis();
  void read_escape_info();
  bool contains(uint arg_set1, uint arg_set2);
 public:
  BCEscapeAnalyzer(ciMethod* method, BCEscapeAnalyzer* parent = NULL);
  ciMethod*         method() const               { return _method; }
  ciMethodData*     methodData() const           { return _methodData; }
  BCEscapeAnalyzer* parent() const               { return _parent; }
  int               level() const                { return _level; }
  GrowableArray<ciMetadata *>* dependencies()    { return &_dependencies; }
  bool              has_dependencies() const     { return !_dependencies.is_empty(); }
  bool is_arg_local(int i) const {
    return !_conservative && _arg_local.test(i);
  }
  bool is_arg_stack(int i) const {
    return !_conservative && _arg_stack.test(i);
  }
  bool is_arg_returned(int i) const {
    return !_conservative && _arg_returned.test(i); }
  bool is_return_local() const {
    return !_conservative && _return_local;
  }
  bool is_return_allocated() const {
    return !_conservative && _return_allocated && !_allocated_escapes;
  }
  enum {OFFSET_ANY = -1};
  bool is_arg_modified(int arg, int offset, int size_in_bytes);
  void set_arg_modified(int arg, int offset, int size_in_bytes);
  bool has_non_arg_side_affects()    { return _unknown_modified; }
  void copy_dependencies(Dependencies *deps);
#ifndef PRODUCT
  void dump();
#endif
};
#endif // SHARE_VM_CI_BCESCAPEANALYZER_HPP
C:\hotspot-69087d08d473\src\share\vm/ci/ciArray.cpp
#include "precompiled.hpp"
#include "ci/ciArray.hpp"
#include "ci/ciArrayKlass.hpp"
#include "ci/ciConstant.hpp"
#include "ci/ciKlass.hpp"
#include "ci/ciUtilities.hpp"
#include "oops/objArrayOop.hpp"
#include "oops/typeArrayOop.hpp"
static BasicType fixup_element_type(BasicType bt) {
  if (bt == T_ARRAY)    return T_OBJECT;
  if (bt == T_BOOLEAN)  return T_BYTE;
  return bt;
}
ciConstant ciArray::element_value_impl(BasicType elembt,
                                       arrayOop ary,
                                       int index) {
  if (ary == NULL)
    return ciConstant();
  assert(ary->is_array(), "");
  if (index < 0 || index >= ary->length())
    return ciConstant();
  ArrayKlass* ak = (ArrayKlass*) ary->klass();
  BasicType abt = ak->element_type();
  if (fixup_element_type(elembt) !=
      fixup_element_type(abt))
    return ciConstant();
  switch (elembt) {
  case T_ARRAY:
  case T_OBJECT:
    {
      assert(ary->is_objArray(), "");
      objArrayOop objary = (objArrayOop) ary;
      oop elem = objary->obj_at(index);
      ciEnv* env = CURRENT_ENV;
      ciObject* box = env->get_object(elem);
      return ciConstant(T_OBJECT, box);
    }
  }
  assert(ary->is_typeArray(), "");
  typeArrayOop tary = (typeArrayOop) ary;
  jint value = 0;
  switch (elembt) {
  case T_LONG:          return ciConstant(tary->long_at(index));
  case T_FLOAT:         return ciConstant(tary->float_at(index));
  case T_DOUBLE:        return ciConstant(tary->double_at(index));
  default:              return ciConstant();
  case T_BYTE:          value = tary->byte_at(index);           break;
  case T_BOOLEAN:       value = tary->byte_at(index) & 1;       break;
  case T_SHORT:         value = tary->short_at(index);          break;
  case T_CHAR:          value = tary->char_at(index);           break;
  case T_INT:           value = tary->int_at(index);            break;
  }
  return ciConstant(elembt, value);
}
ciConstant ciArray::element_value(int index) {
  BasicType elembt = element_basic_type();
  GUARDED_VM_ENTRY(
    return element_value_impl(elembt, get_arrayOop(), index);
  )
}
ciConstant ciArray::element_value_by_offset(intptr_t element_offset) {
  BasicType elembt = element_basic_type();
  intptr_t shift  = exact_log2(type2aelembytes(elembt));
  intptr_t header = arrayOopDesc::base_offset_in_bytes(elembt);
  intptr_t index = (element_offset - header) >> shift;
  intptr_t offset = header + ((intptr_t)index << shift);
  if (offset != element_offset || index != (jint)index)
    return ciConstant();
  return element_value((jint) index);
}
void ciArray::print_impl(outputStream* st) {
  st->print(" length=%d type=", length());
  klass()->print(st);
}
C:\hotspot-69087d08d473\src\share\vm/ci/ciArray.hpp
#ifndef SHARE_VM_CI_CIARRAY_HPP
#define SHARE_VM_CI_CIARRAY_HPP
#include "ci/ciArrayKlass.hpp"
#include "ci/ciConstant.hpp"
#include "ci/ciObject.hpp"
#include "oops/arrayOop.hpp"
#include "oops/objArrayOop.hpp"
#include "oops/typeArrayOop.hpp"
class ciArray : public ciObject {
private:
  int _length;
protected:
  ciArray(    arrayHandle h_a) : ciObject(h_a), _length(h_a()->length()) {}
  ciArray( objArrayHandle h_a) : ciObject(h_a), _length(h_a()->length()) {}
  ciArray(typeArrayHandle h_a) : ciObject(h_a), _length(h_a()->length()) {}
  ciArray(ciKlass* klass, int len) : ciObject(klass), _length(len) {}
  arrayOop get_arrayOop() const { return (arrayOop)get_oop(); }
  const char* type_string() { return "ciArray"; }
  void print_impl(outputStream* st);
  ciConstant element_value_impl(BasicType elembt, arrayOop ary, int index);
public:
  int length() { return _length; }
  ciArrayKlass* array_type()         { return klass()->as_array_klass(); }
  ciType*       element_type()       { return array_type()->element_type(); }
  BasicType     element_basic_type() { return element_type()->basic_type(); }
  ciConstant element_value(int index);
  ciConstant element_value_by_offset(intptr_t element_offset);
  bool is_array()        { return true; }
  bool is_java_object()  { return true; }
};
#endif // SHARE_VM_CI_CIARRAY_HPP
C:\hotspot-69087d08d473\src\share\vm/ci/ciArrayKlass.cpp
#include "precompiled.hpp"
#include "ci/ciArrayKlass.hpp"
#include "ci/ciObjArrayKlass.hpp"
#include "ci/ciTypeArrayKlass.hpp"
#include "ci/ciUtilities.hpp"
ciArrayKlass::ciArrayKlass(KlassHandle h_k) : ciKlass(h_k) {
  assert(get_Klass()->oop_is_array(), "wrong type");
  _dimension = get_ArrayKlass()->dimension();
}
ciArrayKlass::ciArrayKlass(ciSymbol* name, int dimension, BasicType bt)
  : ciKlass(name, bt) {
  _dimension = dimension;
}
ciType* ciArrayKlass::element_type() {
  if (is_type_array_klass()) {
    return ciType::make(as_type_array_klass()->element_type());
  } else {
    return as_obj_array_klass()->element_klass()->as_klass();
  }
}
ciType* ciArrayKlass::base_element_type() {
  if (is_type_array_klass()) {
    return ciType::make(as_type_array_klass()->element_type());
  } else {
    ciKlass* ek = as_obj_array_klass()->base_element_klass();
    if (ek->is_type_array_klass()) {
      return ciType::make(ek->as_type_array_klass()->element_type());
    }
    return ek;
  }
}
bool ciArrayKlass::is_leaf_type() {
  if (is_type_array_klass()) {
    return true;
  } else {
    return as_obj_array_klass()->base_element_klass()->is_leaf_type();
  }
}
ciArrayKlass* ciArrayKlass::make(ciType* element_type) {
  if (element_type->is_primitive_type()) {
    return ciTypeArrayKlass::make(element_type->basic_type());
  } else {
    return ciObjArrayKlass::make(element_type->as_klass());
  }
}
C:\hotspot-69087d08d473\src\share\vm/ci/ciArrayKlass.hpp
#ifndef SHARE_VM_CI_CIARRAYKLASS_HPP
#define SHARE_VM_CI_CIARRAYKLASS_HPP
#include "ci/ciKlass.hpp"
class ciArrayKlass : public ciKlass {
  CI_PACKAGE_ACCESS
private:
  jint _dimension;
protected:
  ciArrayKlass(KlassHandle h_k);
  ciArrayKlass(ciSymbol* name, int dimension, BasicType bt);
  ArrayKlass* get_ArrayKlass() {
    return (ArrayKlass*)get_Klass();
  }
  const char* type_string() { return "ciArrayKlass"; }
public:
  jint dimension() { return _dimension; }
  ciType* element_type();       // JLS calls this the "component type"
  ciType* base_element_type();  // JLS calls this the "element type"
  bool is_leaf_type();          // No subtypes of this array type.
  ciInstance* component_mirror() {
    return element_type()->java_mirror();
  }
  bool is_array_klass() const { return true; }
  bool is_java_klass() const  { return true; }
  static ciArrayKlass* make(ciType* element_type);
};
#endif // SHARE_VM_CI_CIARRAYKLASS_HPP
C:\hotspot-69087d08d473\src\share\vm/ci/ciBaseObject.cpp
#include "precompiled.hpp"
#include "ci/ciBaseObject.hpp"
#include "ci/ciUtilities.hpp"
#include "gc_interface/collectedHeap.inline.hpp"
#include "oops/oop.inline2.hpp"
void ciBaseObject::set_ident(uint id) {
  assert((_ident >> FLAG_BITS) == 0, "must only initialize once");
  assert( id < ((uint)1 << (BitsPerInt-FLAG_BITS)), "id too big");
  _ident = _ident + (id << FLAG_BITS);
}
uint ciBaseObject::ident() {
  uint id = _ident >> FLAG_BITS;
  assert(id != 0, "must be initialized");
  return id;
}
C:\hotspot-69087d08d473\src\share\vm/ci/ciBaseObject.hpp
#ifndef SHARE_VM_CI_CIBASEOBJECT_HPP
#define SHARE_VM_CI_CIBASEOBJECT_HPP
#include "ci/ciClassList.hpp"
#include "memory/allocation.hpp"
#include "runtime/handles.hpp"
#include "runtime/jniHandles.hpp"
class ciBaseObject : public ResourceObj {
  CI_PACKAGE_ACCESS
  friend class ciEnv;
protected:
  uint     _ident;
  enum { FLAG_BITS   = 1 };
  enum {
         SCAVENGABLE_FLAG = 1
       };
protected:
  ciBaseObject(): _ident(0) {}
  virtual const char* type_string() { return "ciBaseObject"; }
  void set_ident(uint id);
public:
  uint ident();
  virtual bool is_symbol() const       { return false; }
  virtual bool is_object() const       { return false; }
  virtual bool is_metadata() const     { return false; }
  ciSymbol* as_symbol() {
    assert(is_symbol(), "must be");
    return (ciSymbol*)this;
  }
  ciObject* as_object() {
    assert(is_object(), "must be");
    return (ciObject*)this;
  }
  ciMetadata* as_metadata() {
    assert(is_metadata(), "must be");
    return (ciMetadata*)this;
  }
};
#endif // SHARE_VM_CI_CIBASEOBJECT_HPP
C:\hotspot-69087d08d473\src\share\vm/ci/ciCallProfile.hpp
#ifndef SHARE_VM_CI_CICALLPROFILE_HPP
#define SHARE_VM_CI_CICALLPROFILE_HPP
#include "ci/ciClassList.hpp"
#include "memory/allocation.hpp"
class ciCallProfile : StackObj {
private:
  friend class ciMethod;
  friend class ciMethodHandle;
  enum { MorphismLimit = 2 }; // Max call site's morphism we care about
  int  _limit;                // number of receivers have been determined
  int  _morphism;             // determined call site's morphism
  int  _count;                // # times has this call been executed
  int  _receiver_count[MorphismLimit + 1]; // # times receivers have been seen
  ciMethod* _method[MorphismLimit + 1];    // receivers methods
  ciKlass*  _receiver[MorphismLimit + 1];  // receivers (exact)
  ciCallProfile() {
    _limit = 0;
    _morphism    = 0;
    _count = -1;
    _receiver_count[0] = -1;
    _method[0]   = NULL;
    _receiver[0] = NULL;
  }
  void add_receiver(ciKlass* receiver, int receiver_count);
public:
  bool      has_receiver(int i) const { return _limit > i; }
  int       morphism() const          { return _morphism; }
  int       count() const             { return _count; }
  int       receiver_count(int i)  {
    assert(i < _limit, "out of Call Profile MorphismLimit");
    return _receiver_count[i];
  }
  float     receiver_prob(int i)  {
    assert(i < _limit, "out of Call Profile MorphismLimit");
    return (float)_receiver_count[i]/(float)_count;
  }
  ciMethod* method(int i)          {
    assert(i < _limit, "out of Call Profile MorphismLimit");
    return _method[i];
  }
  ciKlass*  receiver(int i)        {
    assert(i < _limit, "out of Call Profile MorphismLimit");
    return _receiver[i];
  }
  ciCallProfile rescale(double scale) {
    assert(scale >= 0 && scale <= 1.0, "out of range");
    ciCallProfile call = *this;
    call._count = (int)(call._count * scale);
    for (int i = 0; i < _morphism; i++) {
      call._receiver_count[i] = (int)(call._receiver_count[i] * scale);
    }
    return call;
  }
};
#endif // SHARE_VM_CI_CICALLPROFILE_HPP
C:\hotspot-69087d08d473\src\share\vm/ci/ciCallSite.cpp
#include "precompiled.hpp"
#include "ci/ciCallSite.hpp"
#include "ci/ciUtilities.hpp"
bool ciCallSite::is_constant_call_site() {
  return klass()->is_subclass_of(CURRENT_ENV->ConstantCallSite_klass());
}
bool ciCallSite::is_mutable_call_site() {
  return klass()->is_subclass_of(CURRENT_ENV->MutableCallSite_klass());
}
bool ciCallSite::is_volatile_call_site() {
  return klass()->is_subclass_of(CURRENT_ENV->VolatileCallSite_klass());
}
ciMethodHandle* ciCallSite::get_target() const {
  VM_ENTRY_MARK;
  oop method_handle_oop = java_lang_invoke_CallSite::target(get_oop());
  return CURRENT_ENV->get_object(method_handle_oop)->as_method_handle();
}
void ciCallSite::print() {
  Unimplemented();
}
C:\hotspot-69087d08d473\src\share\vm/ci/ciCallSite.hpp
#ifndef SHARE_VM_CI_CICALLSITE_HPP
#define SHARE_VM_CI_CICALLSITE_HPP
#include "ci/ciInstance.hpp"
class ciCallSite : public ciInstance {
public:
  ciCallSite(instanceHandle h_i) : ciInstance(h_i) {}
  bool is_call_site() const { return true; }
  bool is_constant_call_site();
  bool is_mutable_call_site();
  bool is_volatile_call_site();
  ciMethodHandle* get_target() const;
  void print();
};
#endif // SHARE_VM_CI_CICALLSITE_HPP
C:\hotspot-69087d08d473\src\share\vm/ci/ciClassList.hpp
#ifndef SHARE_VM_CI_CICLASSLIST_HPP
#define SHARE_VM_CI_CICLASSLIST_HPP
class ciEnv;
class ciObjectFactory;
class ciConstantPoolCache;
class ciField;
class ciConstant;
class ciFlags;
class ciExceptionHandler;
class ciCallProfile;
class ciSignature;
class ciBytecodeStream;
class ciSignatureStream;
class ciExceptionHandlerStream;
class ciTypeFlow;
class ciBaseObject;
class ciObject;
class   ciNullObject;
class   ciInstance;
class     ciCallSite;
class     ciMemberName;
class     ciMethodHandle;
class     ciMethodType;
class     ciArray;
class       ciObjArray;
class       ciTypeArray;
class   ciSymbol;
class   ciMetadata;
class   ciMethod;
class   ciMethodData;
class     ciReceiverTypeData;  // part of ciMethodData
class   ciType;
class    ciReturnAddress;
class    ciKlass;
class     ciInstanceKlass;
class     ciArrayKlass;
class       ciObjArrayKlass;
class       ciTypeArrayKlass;
#define CI_PACKAGE_ACCESS \
friend class ciObjectFactory; \
friend class VMStructs;
#define CI_PACKAGE_ACCESS_TO           \
friend class ciObjectFactory;          \
friend class VMStructs;                \
friend class ciCallSite;               \
friend class ciConstantPoolCache;      \
friend class ciField;                  \
friend class ciConstant;               \
friend class ciFlags;                  \
friend class ciExceptionHandler;       \
friend class ciCallProfile;            \
friend class ciSignature;              \
friend class ciBytecodeStream;         \
friend class ciSignatureStream;        \
friend class ciExceptionHandlerStream; \
friend class ciObject;                 \
friend class ciNullObject;             \
friend class ciInstance;               \
friend class ciMemberName;             \
friend class ciMethod;                 \
friend class ciMethodData;             \
friend class ciMethodHandle;           \
friend class ciMethodType;             \
friend class ciReceiverTypeData;       \
friend class ciTypeEntries;            \
friend class ciSpeculativeTrapData;    \
friend class ciSymbol;                 \
friend class ciArray;                  \
friend class ciObjArray;               \
friend class ciMetadata;               \
friend class ciReplay;                 \
friend class ciTypeArray;              \
friend class ciType;                   \
friend class ciReturnAddress;          \
friend class ciKlass;                  \
friend class ciInstanceKlass;          \
friend class ciArrayKlass;             \
friend class ciObjArrayKlass;          \
friend class ciTypeArrayKlass;         \
#endif // SHARE_VM_CI_CICLASSLIST_HPP
C:\hotspot-69087d08d473\src\share\vm/ci/ciConstant.cpp
#include "precompiled.hpp"
#include "ci/ciConstant.hpp"
#include "ci/ciUtilities.hpp"
#include "memory/allocation.hpp"
#include "memory/allocation.inline.hpp"
void ciConstant::print() {
  tty->print("<ciConstant type=%s value=",
             basictype_to_str(basic_type()));
  switch (basic_type()) {
  case T_BOOLEAN:
    tty->print("%s", bool_to_str(_value._int != 0));
    break;
  case T_CHAR:
  case T_BYTE:
  case T_SHORT:
  case T_INT:
    tty->print("%d", _value._int);
    break;
  case T_LONG:
    tty->print(INT64_FORMAT, (int64_t)(_value._long));
    break;
  case T_FLOAT:
    tty->print("%f", _value._float);
    break;
  case T_DOUBLE:
    tty->print("%lf", _value._double);
    break;
  case T_OBJECT:
  case T_ARRAY:
    _value._object->print();
    break;
  default:
    tty->print("ILLEGAL");
    break;
  }
  tty->print(">");
}
C:\hotspot-69087d08d473\src\share\vm/ci/ciConstant.hpp
#ifndef SHARE_VM_CI_CICONSTANT_HPP
#define SHARE_VM_CI_CICONSTANT_HPP
#include "ci/ciClassList.hpp"
#include "ci/ciNullObject.hpp"
class ciConstant VALUE_OBJ_CLASS_SPEC {
  friend class VMStructs;
private:
  friend class ciEnv;
  friend class ciField;
  BasicType _type;
  union {
    jint      _int;
    jlong     _long;
    jfloat    _float;
    jdouble   _double;
    ciObject* _object;
  } _value;
public:
  ciConstant() {
    _type = T_ILLEGAL; _value._long = -1;
  }
  ciConstant(BasicType type, jint value) {
    assert(type != T_LONG && type != T_DOUBLE && type != T_FLOAT,
           "using the wrong ciConstant constructor");
    _type = type; _value._int = value;
  }
  ciConstant(jlong value) {
    _type = T_LONG; _value._long = value;
  }
  ciConstant(jfloat value) {
    _type = T_FLOAT; _value._float = value;
  }
  ciConstant(jdouble value) {
    _type = T_DOUBLE; _value._double = value;
  }
  ciConstant(BasicType type, ciObject* p) {
    _type = type; _value._object = p;
  }
  BasicType basic_type() const { return _type; }
  jboolean  as_boolean() {
    assert(basic_type() == T_BOOLEAN, "wrong type");
    return (jboolean)_value._int;
  }
  jchar     as_char() {
    assert(basic_type() == T_CHAR, "wrong type");
    return (jchar)_value._int;
  }
  jbyte     as_byte() {
    assert(basic_type() == T_BYTE, "wrong type");
    return (jbyte)_value._int;
  }
  jshort    as_short() {
    assert(basic_type() == T_SHORT, "wrong type");
    return (jshort)_value._int;
  }
  jint      as_int() {
    assert(basic_type() == T_BOOLEAN || basic_type() == T_CHAR  ||
           basic_type() == T_BYTE    || basic_type() == T_SHORT ||
           basic_type() == T_INT, "wrong type");
    return _value._int;
  }
  jlong     as_long() {
    assert(basic_type() == T_LONG, "wrong type");
    return _value._long;
  }
  jfloat    as_float() {
    assert(basic_type() == T_FLOAT, "wrong type");
    return _value._float;
  }
  jdouble   as_double() {
    assert(basic_type() == T_DOUBLE, "wrong type");
    return _value._double;
  }
  ciObject* as_object() const {
    assert(basic_type() == T_OBJECT || basic_type() == T_ARRAY, "wrong type");
    return _value._object;
  }
  bool      is_null_or_zero() const {
    if (!is_java_primitive(basic_type())) {
      return as_object()->is_null_object();
    } else if (type2size[basic_type()] == 1) {
      return (_value._int == 0);
    } else if (type2size[basic_type()] == 2) {
      return (_value._long == 0);
    } else {
      return false;
    }
  }
  void print();
};
#endif // SHARE_VM_CI_CICONSTANT_HPP
C:\hotspot-69087d08d473\src\share\vm/ci/ciConstantPoolCache.cpp
#include "precompiled.hpp"
#include "ci/ciConstantPoolCache.hpp"
#include "ci/ciUtilities.hpp"
#include "memory/allocation.hpp"
#include "memory/allocation.inline.hpp"
ciConstantPoolCache::ciConstantPoolCache(Arena* arena,
                                 int expected_size) {
  _elements =
    new (arena) GrowableArray<void*>(arena, expected_size, 0, 0);
  _keys = new (arena) GrowableArray<intptr_t>(arena, expected_size, 0, 0);
}
void* ciConstantPoolCache::get(int index) {
  ASSERT_IN_VM;
  int pos = find(index);
  if (pos >= _keys->length() ||
      _keys->at(pos) != index) {
    return NULL;
  }
  return _elements->at(pos);
}
int ciConstantPoolCache::find(int key) {
  int min = 0;
  int max = _keys->length()-1;
  while (max >= min) {
    int mid = (max + min) / 2;
    int value = _keys->at(mid);
    if (value < key) {
      min = mid + 1;
    } else if (value > key) {
      max = mid - 1;
    } else {
      return mid;
    }
  }
  return min;
}
void ciConstantPoolCache::insert(int index, void* elem) {
  int i;
  int pos = find(index);
  for (i = _keys->length()-1; i >= pos; i--) {
    _keys->at_put_grow(i+1, _keys->at(i));
    _elements->at_put_grow(i+1, _elements->at(i));
  }
  _keys->at_put_grow(pos, index);
  _elements->at_put_grow(pos, elem);
}
void ciConstantPoolCache::print() {
  Unimplemented();
}
C:\hotspot-69087d08d473\src\share\vm/ci/ciConstantPoolCache.hpp
#ifndef SHARE_VM_CI_CICONSTANTPOOLCACHE_HPP
#define SHARE_VM_CI_CICONSTANTPOOLCACHE_HPP
#include "memory/resourceArea.hpp"
#include "utilities/growableArray.hpp"
class ciConstantPoolCache : public ResourceObj {
private:
  GrowableArray<intptr_t>*   _keys;
  GrowableArray<void*>* _elements;
  int find(int index);
public:
  ciConstantPoolCache(Arena* arena, int expected_size);
  void* get(int index);
  void insert(int index, void* element);
  void print();
};
#endif // SHARE_VM_CI_CICONSTANTPOOLCACHE_HPP
C:\hotspot-69087d08d473\src\share\vm/ci/ciEnv.cpp
#include "precompiled.hpp"
#include "ci/ciConstant.hpp"
#include "ci/ciEnv.hpp"
#include "ci/ciField.hpp"
#include "ci/ciInstance.hpp"
#include "ci/ciInstanceKlass.hpp"
#include "ci/ciMethod.hpp"
#include "ci/ciNullObject.hpp"
#include "ci/ciReplay.hpp"
#include "ci/ciUtilities.hpp"
#include "classfile/systemDictionary.hpp"
#include "classfile/vmSymbols.hpp"
#include "code/scopeDesc.hpp"
#include "compiler/compileBroker.hpp"
#include "compiler/compileLog.hpp"
#include "compiler/compilerOracle.hpp"
#include "gc_interface/collectedHeap.inline.hpp"
#include "interpreter/linkResolver.hpp"
#include "jfr/jfrEvents.hpp"
#include "memory/allocation.inline.hpp"
#include "memory/oopFactory.hpp"
#include "memory/universe.inline.hpp"
#include "oops/methodData.hpp"
#include "oops/objArrayKlass.hpp"
#include "oops/oop.inline.hpp"
#include "oops/oop.inline2.hpp"
#include "prims/jvmtiExport.hpp"
#include "runtime/init.hpp"
#include "runtime/reflection.hpp"
#include "runtime/sharedRuntime.hpp"
#include "runtime/thread.inline.hpp"
#include "utilities/dtrace.hpp"
#include "utilities/macros.hpp"
#ifdef COMPILER1
#include "c1/c1_Runtime1.hpp"
#endif
#ifdef COMPILER2
#include "opto/runtime.hpp"
#endif
ciObject*              ciEnv::_null_object_instance;
#define WK_KLASS_DEFN(name, ignore_s, ignore_o) ciInstanceKlass* ciEnv::_##name = NULL;
WK_KLASSES_DO(WK_KLASS_DEFN)
#undef WK_KLASS_DEFN
ciSymbol*        ciEnv::_unloaded_cisymbol = NULL;
ciInstanceKlass* ciEnv::_unloaded_ciinstance_klass = NULL;
ciObjArrayKlass* ciEnv::_unloaded_ciobjarrayklass = NULL;
jobject ciEnv::_ArrayIndexOutOfBoundsException_handle = NULL;
jobject ciEnv::_ArrayStoreException_handle = NULL;
jobject ciEnv::_ClassCastException_handle = NULL;
#ifndef PRODUCT
static bool firstEnv = true;
#endif /* PRODUCT */
ciEnv::ciEnv(CompileTask* task, int system_dictionary_modification_counter)
  : _ciEnv_arena(mtCompiler) {
  VM_ENTRY_MARK;
  thread->set_env(this);
  assert(ciEnv::current() == this, "sanity");
  _oop_recorder = NULL;
  _debug_info = NULL;
  _dependencies = NULL;
  _failure_reason = NULL;
  _compilable = MethodCompilable;
  _break_at_compile = false;
  _compiler_data = NULL;
#ifndef PRODUCT
  assert(!firstEnv, "not initialized properly");
#endif /* !PRODUCT */
  _system_dictionary_modification_counter = system_dictionary_modification_counter;
  _num_inlined_bytecodes = 0;
  assert(task == NULL || thread->task() == task, "sanity");
  _task = task;
  _log = NULL;
  _name_buffer = NULL;
  _name_buffer_len = 0;
  _arena   = &_ciEnv_arena;
  _factory = new (_arena) ciObjectFactory(_arena, 128);
  assert(Universe::is_fully_initialized(), "should be complete");
  oop o = Universe::null_ptr_exception_instance();
  assert(o != NULL, "should have been initialized");
  _NullPointerException_instance = get_object(o)->as_instance();
  o = Universe::arithmetic_exception_instance();
  assert(o != NULL, "should have been initialized");
  _ArithmeticException_instance = get_object(o)->as_instance();
  _ArrayIndexOutOfBoundsException_instance = NULL;
  _ArrayStoreException_instance = NULL;
  _ClassCastException_instance = NULL;
  _the_null_string = NULL;
  _the_min_jint_string = NULL;
  _jvmti_can_hotswap_or_post_breakpoint = false;
  _jvmti_can_access_local_variables = false;
  _jvmti_can_post_on_exceptions = false;
  _jvmti_can_pop_frame = false;
}
ciEnv::ciEnv(Arena* arena) : _ciEnv_arena(mtCompiler) {
  ASSERT_IN_VM;
  CompilerThread* current_thread = CompilerThread::current();
  assert(current_thread->env() == NULL, "must be");
  current_thread->set_env(this);
  assert(ciEnv::current() == this, "sanity");
  _oop_recorder = NULL;
  _debug_info = NULL;
  _dependencies = NULL;
  _failure_reason = NULL;
  _compilable = MethodCompilable_never;
  _break_at_compile = false;
  _compiler_data = NULL;
#ifndef PRODUCT
  assert(firstEnv, "must be first");
  firstEnv = false;
#endif /* !PRODUCT */
  _system_dictionary_modification_counter = 0;
  _num_inlined_bytecodes = 0;
  _task = NULL;
  _log = NULL;
  _name_buffer = NULL;
  _name_buffer_len = 0;
  _arena   = arena;
  _factory = new (_arena) ciObjectFactory(_arena, 128);
  assert(Universe::is_fully_initialized(), "must be");
  _NullPointerException_instance = NULL;
  _ArithmeticException_instance = NULL;
  _ArrayIndexOutOfBoundsException_instance = NULL;
  _ArrayStoreException_instance = NULL;
  _ClassCastException_instance = NULL;
  _the_null_string = NULL;
  _the_min_jint_string = NULL;
  _jvmti_can_hotswap_or_post_breakpoint = false;
  _jvmti_can_access_local_variables = false;
  _jvmti_can_post_on_exceptions = false;
  _jvmti_can_pop_frame = false;
}
ciEnv::~ciEnv() {
  CompilerThread* current_thread = CompilerThread::current();
  _factory->remove_symbols();
  GUARDED_VM_ENTRY(current_thread->set_env(NULL);)
}
void ciEnv::cache_jvmti_state() {
  VM_ENTRY_MARK;
  MutexLocker mu(JvmtiThreadState_lock);
  _jvmti_can_hotswap_or_post_breakpoint = JvmtiExport::can_hotswap_or_post_breakpoint();
  _jvmti_can_access_local_variables     = JvmtiExport::can_access_local_variables();
  _jvmti_can_post_on_exceptions         = JvmtiExport::can_post_on_exceptions();
  _jvmti_can_pop_frame                  = JvmtiExport::can_pop_frame();
}
bool ciEnv::should_retain_local_variables() const {
  return _jvmti_can_access_local_variables || _jvmti_can_pop_frame;
}
bool ciEnv::jvmti_state_changed() const {
  if (!_jvmti_can_access_local_variables &&
      JvmtiExport::can_access_local_variables()) {
    return true;
  }
  if (!_jvmti_can_hotswap_or_post_breakpoint &&
      JvmtiExport::can_hotswap_or_post_breakpoint()) {
    return true;
  }
  if (!_jvmti_can_post_on_exceptions &&
      JvmtiExport::can_post_on_exceptions()) {
    return true;
  }
  if (!_jvmti_can_pop_frame &&
      JvmtiExport::can_pop_frame()) {
    return true;
  }
  return false;
}
void ciEnv::cache_dtrace_flags() {
  _dtrace_extended_probes = ExtendedDTraceProbes;
  if (_dtrace_extended_probes) {
    _dtrace_monitor_probes  = true;
    _dtrace_method_probes   = true;
    _dtrace_alloc_probes    = true;
  } else {
    _dtrace_monitor_probes  = DTraceMonitorProbes;
    _dtrace_method_probes   = DTraceMethodProbes;
    _dtrace_alloc_probes    = DTraceAllocProbes;
  }
}
ciInstance* ciEnv::get_or_create_exception(jobject& handle, Symbol* name) {
  VM_ENTRY_MARK;
  if (handle == NULL) {
    Klass* k = SystemDictionary::find(name, Handle(), Handle(), THREAD);
    jobject objh = NULL;
    if (!HAS_PENDING_EXCEPTION && k != NULL) {
      oop obj = InstanceKlass::cast(k)->allocate_instance(THREAD);
      if (!HAS_PENDING_EXCEPTION)
        objh = JNIHandles::make_global(obj);
    }
    if (HAS_PENDING_EXCEPTION) {
      CLEAR_PENDING_EXCEPTION;
    } else {
      handle = objh;
    }
  }
  oop obj = JNIHandles::resolve(handle);
  return obj == NULL? NULL: get_object(obj)->as_instance();
}
ciInstance* ciEnv::ArrayIndexOutOfBoundsException_instance() {
  if (_ArrayIndexOutOfBoundsException_instance == NULL) {
    _ArrayIndexOutOfBoundsException_instance
          = get_or_create_exception(_ArrayIndexOutOfBoundsException_handle,
          vmSymbols::java_lang_ArrayIndexOutOfBoundsException());
  }
  return _ArrayIndexOutOfBoundsException_instance;
}
ciInstance* ciEnv::ArrayStoreException_instance() {
  if (_ArrayStoreException_instance == NULL) {
    _ArrayStoreException_instance
          = get_or_create_exception(_ArrayStoreException_handle,
          vmSymbols::java_lang_ArrayStoreException());
  }
  return _ArrayStoreException_instance;
}
ciInstance* ciEnv::ClassCastException_instance() {
  if (_ClassCastException_instance == NULL) {
    _ClassCastException_instance
          = get_or_create_exception(_ClassCastException_handle,
          vmSymbols::java_lang_ClassCastException());
  }
  return _ClassCastException_instance;
}
ciInstance* ciEnv::the_null_string() {
  if (_the_null_string == NULL) {
    VM_ENTRY_MARK;
    _the_null_string = get_object(Universe::the_null_string())->as_instance();
  }
  return _the_null_string;
}
ciInstance* ciEnv::the_min_jint_string() {
  if (_the_min_jint_string == NULL) {
    VM_ENTRY_MARK;
    _the_min_jint_string = get_object(Universe::the_min_jint_string())->as_instance();
  }
  return _the_min_jint_string;
}
ciMethod* ciEnv::get_method_from_handle(Method* method) {
  VM_ENTRY_MARK;
  return get_metadata(method)->as_method();
}
int ciEnv::array_element_offset_in_bytes(ciArray* a_h, ciObject* o_h) {
  VM_ENTRY_MARK;
  objArrayOop a = (objArrayOop)a_h->get_oop();
  assert(a->is_objArray(), "");
  int length = a->length();
  oop o = o_h->get_oop();
  for (int i = 0; i < length; i++) {
    if (a->obj_at(i) == o)  return i;
  }
  return -1;
}
bool ciEnv::check_klass_accessibility(ciKlass* accessing_klass,
                                      Klass* resolved_klass) {
  if (accessing_klass == NULL || !accessing_klass->is_loaded()) {
    return true;
  }
  if (accessing_klass->is_obj_array_klass()) {
    accessing_klass = accessing_klass->as_obj_array_klass()->base_element_klass();
  }
  if (!accessing_klass->is_instance_klass()) {
    return true;
  }
  if (resolved_klass->oop_is_objArray()) {
    resolved_klass = ObjArrayKlass::cast(resolved_klass)->bottom_klass();
  }
  if (resolved_klass->oop_is_instance()) {
    return Reflection::verify_class_access(accessing_klass->get_Klass(),
                                           resolved_klass,
                                           true);
  }
  return true;
}
ciKlass* ciEnv::get_klass_by_name_impl(ciKlass* accessing_klass,
                                       constantPoolHandle cpool,
                                       ciSymbol* name,
                                       bool require_local) {
  ASSERT_IN_VM;
  EXCEPTION_CONTEXT;
  Symbol* sym = name->get_symbol();
  if (sym->byte_at(0) == 'L' &&
    sym->byte_at(sym->utf8_length()-1) == ';') {
    TempNewSymbol strippedsym = SymbolTable::new_symbol(sym->as_utf8()+1,
                    sym->utf8_length()-2,
                    KILL_COMPILE_ON_FATAL_(_unloaded_ciinstance_klass));
    ciSymbol* strippedname = get_symbol(strippedsym);
    return get_klass_by_name_impl(accessing_klass, cpool, strippedname, require_local);
  }
  ciKlass* unloaded_klass = check_get_unloaded_klass(accessing_klass, name);
  if (unloaded_klass != NULL) {
    if (require_local)  return NULL;
    return unloaded_klass;
  }
  Handle loader(THREAD, (oop)NULL);
  Handle domain(THREAD, (oop)NULL);
  if (accessing_klass != NULL) {
    loader = Handle(THREAD, accessing_klass->loader());
    domain = Handle(THREAD, accessing_klass->protection_domain());
  }
  ciKlass* fail_type;
  if (sym->byte_at(0) == '[') {
    fail_type = _unloaded_ciobjarrayklass;
  } else {
    fail_type = _unloaded_ciinstance_klass;
  }
  KlassHandle found_klass;
  {
    ttyUnlocker ttyul;  // release tty lock to avoid ordering problems
    MutexLocker ml(Compile_lock);
    Klass* kls;
    if (!require_local) {
      kls = SystemDictionary::find_constrained_instance_or_array_klass(sym, loader,
                                                                       KILL_COMPILE_ON_FATAL_(fail_type));
    } else {
      kls = SystemDictionary::find_instance_or_array_klass(sym, loader, domain,
                                                           KILL_COMPILE_ON_FATAL_(fail_type));
    }
    found_klass = KlassHandle(THREAD, kls);
  }
  if (sym->byte_at(0) == '[' &&
      (sym->byte_at(1) == '[' || sym->byte_at(1) == 'L')) {
    TempNewSymbol elem_sym = SymbolTable::new_symbol(sym->as_utf8()+1,
                                                 sym->utf8_length()-1,
                                                 KILL_COMPILE_ON_FATAL_(fail_type));
    ciKlass* elem_klass =
      get_klass_by_name_impl(accessing_klass,
                             cpool,
                             get_symbol(elem_sym),
                             require_local);
    if (elem_klass != NULL && elem_klass->is_loaded()) {
      return ciObjArrayKlass::make_impl(elem_klass);
    }
  }
  if (found_klass() == NULL && !cpool.is_null() && cpool->has_preresolution()) {
    for (int i = cpool->length() - 1; i >= 1; i--) {
      if (cpool->tag_at(i).is_klass()) {
        Klass* kls = cpool->resolved_klass_at(i);
        if (kls->name() == sym) {
          found_klass = KlassHandle(THREAD, kls);
          break;
        }
      }
    }
  }
  if (found_klass() != NULL) {
    return get_klass(found_klass());
  }
  if (require_local)  return NULL;
  return get_unloaded_klass(accessing_klass, name);
}
ciKlass* ciEnv::get_klass_by_name(ciKlass* accessing_klass,
                                  ciSymbol* klass_name,
                                  bool require_local) {
  GUARDED_VM_ENTRY(return get_klass_by_name_impl(accessing_klass,
                                                 constantPoolHandle(),
                                                 klass_name,
                                                 require_local);)
}
ciKlass* ciEnv::get_klass_by_index_impl(constantPoolHandle cpool,
                                        int index,
                                        bool& is_accessible,
                                        ciInstanceKlass* accessor) {
  EXCEPTION_CONTEXT;
  KlassHandle klass; // = NULL;
  Symbol* klass_name = NULL;
  if (cpool->tag_at(index).is_symbol()) {
    klass_name = cpool->symbol_at(index);
  } else {
    klass = KlassHandle(THREAD, ConstantPool::klass_at_if_loaded(cpool, index));
  if (klass.is_null()) {
    {
        MonitorLockerEx ml(cpool->lock());
      constantTag tag = cpool->tag_at(index);
      if (tag.is_klass()) {
        klass = KlassHandle(THREAD, cpool->resolved_klass_at(index));
      } else {
        assert(cpool->tag_at(index).is_unresolved_klass(), "wrong tag");
        klass_name = cpool->unresolved_klass_at(index);
      }
    }
  }
  }
  if (klass.is_null()) {
    ciKlass* k = get_klass_by_name_impl(accessor,
                                        cpool,
                                        get_symbol(klass_name),
                                        false);
    if (!k->is_loaded()) {
      is_accessible = false;
    } else if (k->loader() != accessor->loader() &&
               get_klass_by_name_impl(accessor, cpool, k->name(), true) == NULL) {
      is_accessible = false;
    } else {
      is_accessible = check_klass_accessibility(accessor, k->get_Klass());
    }
    return k;
  }
  ciSymbol* name = get_symbol(klass()->name());
  ciKlass* unloaded_klass = check_get_unloaded_klass(accessor, name);
  if (unloaded_klass != NULL) {
    is_accessible = false;
    return unloaded_klass;
  }
  is_accessible = true;
  return get_klass(klass());
}
ciKlass* ciEnv::get_klass_by_index(constantPoolHandle cpool,
                                   int index,
                                   bool& is_accessible,
                                   ciInstanceKlass* accessor) {
  GUARDED_VM_ENTRY(return get_klass_by_index_impl(cpool, index, is_accessible, accessor);)
}
ciConstant ciEnv::get_constant_by_index_impl(constantPoolHandle cpool,
                                             int pool_index, int cache_index,
                                             ciInstanceKlass* accessor) {
  bool ignore_will_link;
  EXCEPTION_CONTEXT;
  int index = pool_index;
  if (cache_index >= 0) {
    assert(index < 0, "only one kind of index at a time");
    oop obj = cpool->resolved_references()->obj_at(cache_index);
    if (obj != NULL) {
      ciObject* ciobj = get_object(obj);
      if (ciobj->is_array()) {
        return ciConstant(T_ARRAY, ciobj);
      } else {
        assert(ciobj->is_instance(), "should be an instance");
        return ciConstant(T_OBJECT, ciobj);
      }
    }
    index = cpool->object_to_cp_index(cache_index);
  }
  constantTag tag = cpool->tag_at(index);
  if (tag.is_int()) {
    return ciConstant(T_INT, (jint)cpool->int_at(index));
  } else if (tag.is_long()) {
    return ciConstant((jlong)cpool->long_at(index));
  } else if (tag.is_float()) {
    return ciConstant((jfloat)cpool->float_at(index));
  } else if (tag.is_double()) {
    return ciConstant((jdouble)cpool->double_at(index));
  } else if (tag.is_string()) {
    oop string = NULL;
    assert(cache_index >= 0, "should have a cache index");
    if (cpool->is_pseudo_string_at(index)) {
      string = cpool->pseudo_string_at(index, cache_index);
    } else {
      string = cpool->string_at(index, cache_index, THREAD);
      if (HAS_PENDING_EXCEPTION) {
        CLEAR_PENDING_EXCEPTION;
        record_out_of_memory_failure();
        return ciConstant();
      }
    }
    ciObject* constant = get_object(string);
    if (constant->is_array()) {
      return ciConstant(T_ARRAY, constant);
    } else {
      assert (constant->is_instance(), "must be an instance, or not? ");
      return ciConstant(T_OBJECT, constant);
    }
  } else if (tag.is_klass() || tag.is_unresolved_klass()) {
    ciKlass* klass = get_klass_by_index_impl(cpool, index, ignore_will_link, accessor);
    if (HAS_PENDING_EXCEPTION) {
      CLEAR_PENDING_EXCEPTION;
      record_out_of_memory_failure();
      return ciConstant();
    }
    assert (klass->is_instance_klass() || klass->is_array_klass(),
            "must be an instance or array klass ");
    return ciConstant(T_OBJECT, klass->java_mirror());
  } else if (tag.is_method_type()) {
    ciSymbol* signature = get_symbol(cpool->method_type_signature_at(index));
    ciObject* ciobj = get_unloaded_method_type_constant(signature);
    return ciConstant(T_OBJECT, ciobj);
  } else if (tag.is_method_handle()) {
    int ref_kind        = cpool->method_handle_ref_kind_at(index);
    int callee_index    = cpool->method_handle_klass_index_at(index);
    ciKlass* callee     = get_klass_by_index_impl(cpool, callee_index, ignore_will_link, accessor);
    ciSymbol* name      = get_symbol(cpool->method_handle_name_ref_at(index));
    ciSymbol* signature = get_symbol(cpool->method_handle_signature_ref_at(index));
    ciObject* ciobj     = get_unloaded_method_handle_constant(callee, name, signature, ref_kind);
    return ciConstant(T_OBJECT, ciobj);
  } else {
    ShouldNotReachHere();
    return ciConstant();
  }
}
ciConstant ciEnv::get_constant_by_index(constantPoolHandle cpool,
                                        int pool_index, int cache_index,
                                        ciInstanceKlass* accessor) {
  GUARDED_VM_ENTRY(return get_constant_by_index_impl(cpool, pool_index, cache_index, accessor);)
}
ciField* ciEnv::get_field_by_index_impl(ciInstanceKlass* accessor,
                                        int index) {
  ciConstantPoolCache* cache = accessor->field_cache();
  if (cache == NULL) {
    ciField* field = new (arena()) ciField(accessor, index);
    return field;
  } else {
    ciField* field = (ciField*)cache->get(index);
    if (field == NULL) {
      field = new (arena()) ciField(accessor, index);
      cache->insert(index, field);
    }
    return field;
  }
}
ciField* ciEnv::get_field_by_index(ciInstanceKlass* accessor,
                                   int index) {
  GUARDED_VM_ENTRY(return get_field_by_index_impl(accessor, index);)
}
Method* ciEnv::lookup_method(InstanceKlass*  accessor,
                               InstanceKlass*  holder,
                               Symbol*       name,
                               Symbol*       sig,
                               Bytecodes::Code bc) {
  EXCEPTION_CONTEXT;
  KlassHandle h_accessor(THREAD, accessor);
  KlassHandle h_holder(THREAD, holder);
  LinkResolver::check_klass_accessability(h_accessor, h_holder, KILL_COMPILE_ON_FATAL_(NULL));
  methodHandle dest_method;
  switch (bc) {
  case Bytecodes::_invokestatic:
    dest_method =
      LinkResolver::resolve_static_call_or_null(h_holder, name, sig, h_accessor);
    break;
  case Bytecodes::_invokespecial:
    dest_method =
      LinkResolver::resolve_special_call_or_null(h_holder, name, sig, h_accessor);
    break;
  case Bytecodes::_invokeinterface:
    dest_method =
      LinkResolver::linktime_resolve_interface_method_or_null(h_holder, name, sig,
                                                              h_accessor, true);
    break;
  case Bytecodes::_invokevirtual:
    dest_method =
      LinkResolver::linktime_resolve_virtual_method_or_null(h_holder, name, sig,
                                                            h_accessor, true);
    break;
  default: ShouldNotReachHere();
  }
  return dest_method();
}
ciMethod* ciEnv::get_method_by_index_impl(constantPoolHandle cpool,
                                          int index, Bytecodes::Code bc,
                                          ciInstanceKlass* accessor) {
  if (bc == Bytecodes::_invokedynamic) {
    ConstantPoolCacheEntry* cpce = cpool->invokedynamic_cp_cache_entry_at(index);
    bool is_resolved = !cpce->is_f1_null();
    if (is_resolved) {
      Method* adapter = cpce->f1_as_method();
      return get_method(adapter);
    }
    ciInstanceKlass* holder    = get_instance_klass(SystemDictionary::MethodHandle_klass());
    ciSymbol*        name      = ciSymbol::invokeBasic_name();
    ciSymbol*        signature = get_symbol(cpool->signature_ref_at(index));
    return get_unloaded_method(holder, name, signature, accessor);
  } else {
    const int holder_index = cpool->klass_ref_index_at(index);
    bool holder_is_accessible;
    ciKlass* holder = get_klass_by_index_impl(cpool, holder_index, holder_is_accessible, accessor);
    ciInstanceKlass* declared_holder = get_instance_klass_for_declared_method_holder(holder);
    Symbol* name_sym = cpool->name_ref_at(index);
    Symbol* sig_sym  = cpool->signature_ref_at(index);
    if (cpool->has_preresolution()
        || (holder == ciEnv::MethodHandle_klass() &&
            MethodHandles::is_signature_polymorphic_name(holder->get_Klass(), name_sym))) {
      switch (bc) {
      case Bytecodes::_invokevirtual:
      case Bytecodes::_invokeinterface:
      case Bytecodes::_invokespecial:
      case Bytecodes::_invokestatic:
        {
          Method* m = ConstantPool::method_at_if_loaded(cpool, index);
          if (m != NULL) {
            return get_method(m);
          }
        }
        break;
      }
    }
    if (holder_is_accessible) {  // Our declared holder is loaded.
      InstanceKlass* lookup = declared_holder->get_instanceKlass();
      Method* m = lookup_method(accessor->get_instanceKlass(), lookup, name_sym, sig_sym, bc);
      if (m != NULL &&
          (bc == Bytecodes::_invokestatic
           ?  m->method_holder()->is_not_initialized()
           : !m->method_holder()->is_loaded())) {
        m = NULL;
      }
#ifdef ASSERT
      if (m != NULL && ReplayCompiles && !ciReplay::is_loaded(m)) {
        m = NULL;
      }
#endif
      if (m != NULL) {
        return get_method(m);
      }
    }
    ciSymbol* name      = get_symbol(name_sym);
    ciSymbol* signature = get_symbol(sig_sym);
    return get_unloaded_method(declared_holder, name, signature, accessor);
  }
}
ciInstanceKlass* ciEnv::get_instance_klass_for_declared_method_holder(ciKlass* method_holder) {
  guarantee(method_holder != NULL, "no method holder");
  if (method_holder->is_instance_klass()) {
    return method_holder->as_instance_klass();
  } else if (method_holder->is_array_klass()) {
    return current()->Object_klass();
  } else {
    ShouldNotReachHere();
  }
  return NULL;
}
ciMethod* ciEnv::get_method_by_index(constantPoolHandle cpool,
                                     int index, Bytecodes::Code bc,
                                     ciInstanceKlass* accessor) {
  GUARDED_VM_ENTRY(return get_method_by_index_impl(cpool, index, bc, accessor);)
}
char *ciEnv::name_buffer(int req_len) {
  if (_name_buffer_len < req_len) {
    if (_name_buffer == NULL) {
      _name_buffer = (char*)arena()->Amalloc(sizeof(char)*req_len);
      _name_buffer_len = req_len;
    } else {
      _name_buffer =
        (char*)arena()->Arealloc(_name_buffer, _name_buffer_len, req_len);
      _name_buffer_len = req_len;
    }
  }
  return _name_buffer;
}
bool ciEnv::is_in_vm() {
  return JavaThread::current()->thread_state() == _thread_in_vm;
}
bool ciEnv::system_dictionary_modification_counter_changed() {
  return _system_dictionary_modification_counter != SystemDictionary::number_of_modifications();
}
void ciEnv::validate_compile_task_dependencies(ciMethod* target) {
  if (failing())  return;  // no need for further checks
  for (Dependencies::DepStream deps(dependencies()); deps.next(); ) {
    if (deps.is_klass_type())  continue;  // skip klass dependencies
    Klass* witness = deps.check_dependency();
    if (witness != NULL) {
      record_failure("invalid non-klass dependency");
      return;
    }
  }
  bool counter_changed = system_dictionary_modification_counter_changed();
  bool verify_deps = trueInDebug;
  if (!counter_changed && !verify_deps)  return;
  int klass_violations = 0;
  for (Dependencies::DepStream deps(dependencies()); deps.next(); ) {
    if (!deps.is_klass_type())  continue;  // skip non-klass dependencies
    Klass* witness = deps.check_dependency();
    if (witness != NULL) {
      klass_violations++;
      if (!counter_changed) {
        deps.print_dependency(witness);
      } else if (xtty == NULL) {
        break;
      }
    }
  }
  if (klass_violations != 0) {
#ifdef ASSERT
    if (!counter_changed && !PrintCompilation) {
      _task->print_line();
    }
#endif
    assert(counter_changed, "failed dependencies, but counter didn't change");
    record_failure("concurrent class loading");
  }
}
void ciEnv::register_method(ciMethod* target,
                            int entry_bci,
                            CodeOffsets* offsets,
                            int orig_pc_offset,
                            CodeBuffer* code_buffer,
                            int frame_words,
                            OopMapSet* oop_map_set,
                            ExceptionHandlerTable* handler_table,
                            ImplicitExceptionTable* inc_table,
                            AbstractCompiler* compiler,
                            int comp_level,
                            bool has_unsafe_access,
                            bool has_wide_vectors,
                            RTMState  rtm_state) {
  VM_ENTRY_MARK;
  nmethod* nm = NULL;
  {
    MutexLocker locker(MethodCompileQueue_lock, THREAD);
    MutexLocker ml(Compile_lock);
    No_Safepoint_Verifier nsv;
    if (!failing() && jvmti_state_changed()) {
      record_failure("Jvmti state change invalidated dependencies");
    }
    if (!failing() &&
        ( (!dtrace_extended_probes() && ExtendedDTraceProbes) ||
          (!dtrace_method_probes() && DTraceMethodProbes) ||
          (!dtrace_alloc_probes() && DTraceAllocProbes) )) {
      record_failure("DTrace flags change invalidated dependencies");
    }
    if (!failing()) {
      if (log() != NULL) {
        dependencies()->log_all_dependencies();
      }
      dependencies()->encode_content_bytes();
      validate_compile_task_dependencies(target);
    }
    methodHandle method(THREAD, target->get_Method());
#if INCLUDE_RTM_OPT
    if (!failing() && (rtm_state != NoRTM) &&
        (method()->method_data() != NULL) &&
        (method()->method_data()->rtm_state() != rtm_state)) {
      record_failure("RTM state change invalidated rtm code");
    }
#endif
    if (failing()) {
      MethodData* mdo = method()->method_data();
      if (mdo != NULL) {
        mdo->inc_decompile_count();
      }
      code_buffer->free_blob();
      return;
    }
    assert(offsets->value(CodeOffsets::Deopt) != -1, "must have deopt entry");
    assert(offsets->value(CodeOffsets::Exceptions) != -1, "must have exception entry");
    nm =  nmethod::new_nmethod(method,
                               compile_id(),
                               entry_bci,
                               offsets,
                               orig_pc_offset,
                               debug_info(), dependencies(), code_buffer,
                               frame_words, oop_map_set,
                               handler_table, inc_table,
                               compiler, comp_level);
    code_buffer->free_blob();
    if (nm != NULL) {
      nm->set_has_unsafe_access(has_unsafe_access);
      nm->set_has_wide_vectors(has_wide_vectors);
#if INCLUDE_RTM_OPT
      nm->set_rtm_state(rtm_state);
#endif
      if (task() != NULL) {
        task()->set_code(nm);
      }
      if (entry_bci == InvocationEntryBci) {
        if (TieredCompilation) {
          nmethod* old = method->code();
          if (TraceMethodReplacement && old != NULL) {
            ResourceMark rm;
            char *method_name = method->name_and_sig_as_C_string();
            tty->print_cr("Replacing method %s", method_name);
          }
          if (old != NULL) {
            old->make_not_entrant();
          }
        }
        if (TraceNMethodInstalls) {
          ResourceMark rm;
          char *method_name = method->name_and_sig_as_C_string();
          ttyLocker ttyl;
          tty->print_cr("Installing method (%d) %s ",
                        comp_level,
                        method_name);
        }
        method->set_code(method, nm);
      } else {
        if (TraceNMethodInstalls) {
          ResourceMark rm;
          char *method_name = method->name_and_sig_as_C_string();
          ttyLocker ttyl;
          tty->print_cr("Installing osr method (%d) %s @ %d",
                        comp_level,
                        method_name,
                        entry_bci);
        }
        method->method_holder()->add_osr_nmethod(nm);
      }
    }
  }  // safepoints are allowed again
  if (nm != NULL) {
    nm->post_compiled_method_load_event();
  } else {
    record_failure("code cache is full");
    CompileBroker::handle_full_code_cache();
  }
}
ciKlass* ciEnv::find_system_klass(ciSymbol* klass_name) {
  VM_ENTRY_MARK;
  return get_klass_by_name_impl(NULL, constantPoolHandle(), klass_name, false);
}
int ciEnv::comp_level() {
  if (task() == NULL)  return CompLevel_highest_tier;
  return task()->comp_level();
}
uint ciEnv::compile_id() {
  if (task() == NULL)  return 0;
  return task()->compile_id();
}
void ciEnv::notice_inlined_method(ciMethod* method) {
  _num_inlined_bytecodes += method->code_size_for_inlining();
}
int ciEnv::num_inlined_bytecodes() const {
  return _num_inlined_bytecodes;
}
void ciEnv::record_failure(const char* reason) {
  if (_failure_reason == NULL) {
    _failure_reason = reason;
  }
}
void ciEnv::record_method_not_compilable(const char* reason, bool all_tiers) {
  int new_compilable =
    all_tiers ? MethodCompilable_never : MethodCompilable_not_at_tier ;
  if (new_compilable > _compilable) {
    if (log() != NULL) {
      if (all_tiers) {
        log()->elem("method_not_compilable");
      } else {
        log()->elem("method_not_compilable_at_tier level='%d'",
                    current()->task()->comp_level());
      }
    }
    _compilable = new_compilable;
    _failure_reason = NULL;
    record_failure(reason);
  }
}
void ciEnv::record_out_of_memory_failure() {
  record_method_not_compilable("out of memory");
}
ciInstance* ciEnv::unloaded_ciinstance() {
  GUARDED_VM_ENTRY(return _factory->get_unloaded_object_constant();)
}
void ciEnv::dump_compile_data(outputStream* out) {
  CompileTask* task = this->task();
  Method* method = task->method();
  int entry_bci = task->osr_bci();
  int comp_level = task->comp_level();
  out->print("compile %s %s %s %d %d",
                method->klass_name()->as_quoted_ascii(),
                method->name()->as_quoted_ascii(),
                method->signature()->as_quoted_ascii(),
                entry_bci, comp_level);
  if (compiler_data() != NULL) {
    if (is_c2_compile(comp_level)) { // C2 or Shark
#ifdef COMPILER2
      ((Compile*)compiler_data())->dump_inline_data(out);
#endif
    } else if (is_c1_compile(comp_level)) { // C1
#ifdef COMPILER1
      ((Compilation*)compiler_data())->dump_inline_data(out);
#endif
    }
  }
  out->cr();
}
void ciEnv::dump_replay_data_unsafe(outputStream* out) {
  ResourceMark rm;
#if INCLUDE_JVMTI
  out->print_cr("JvmtiExport can_access_local_variables %d",     _jvmti_can_access_local_variables);
  out->print_cr("JvmtiExport can_hotswap_or_post_breakpoint %d", _jvmti_can_hotswap_or_post_breakpoint);
  out->print_cr("JvmtiExport can_post_on_exceptions %d",         _jvmti_can_post_on_exceptions);
#endif // INCLUDE_JVMTI
  GrowableArray<ciMetadata*>* objects = _factory->get_ci_metadata();
  out->print_cr("# %d ciObject found", objects->length());
  for (int i = 0; i < objects->length(); i++) {
    objects->at(i)->dump_replay_data(out);
  }
  dump_compile_data(out);
  out->flush();
}
void ciEnv::dump_replay_data(outputStream* out) {
  GUARDED_VM_ENTRY(
    MutexLocker ml(Compile_lock);
    dump_replay_data_unsafe(out);
  )
}
void ciEnv::dump_replay_data(int compile_id) {
  static char buffer[O_BUFLEN];
  int ret = jio_snprintf(buffer, O_BUFLEN, "replay_pid%p_compid%d.log", os::current_process_id(), compile_id);
  if (ret > 0) {
    int fd = open(buffer, O_RDWR | O_CREAT | O_TRUNC, 0666);
    if (fd != -1) {
      FILE* replay_data_file = os::open(fd, "w");
      if (replay_data_file != NULL) {
        fileStream replay_data_stream(replay_data_file, /*need_close=*/true);
        dump_replay_data(&replay_data_stream);
        tty->print_cr("# Compiler replay data is saved as: %s", buffer);
      } else {
        tty->print_cr("# Can't open file to dump replay data.");
      }
    }
  }
}
void ciEnv::dump_inline_data(int compile_id) {
  static char buffer[O_BUFLEN];
  int ret = jio_snprintf(buffer, O_BUFLEN, "inline_pid%p_compid%d.log", os::current_process_id(), compile_id);
  if (ret > 0) {
    int fd = open(buffer, O_RDWR | O_CREAT | O_TRUNC, 0666);
    if (fd != -1) {
      FILE* inline_data_file = os::open(fd, "w");
      if (inline_data_file != NULL) {
        fileStream replay_data_stream(inline_data_file, /*need_close=*/true);
        GUARDED_VM_ENTRY(
          MutexLocker ml(Compile_lock);
          dump_compile_data(&replay_data_stream);
        )
        replay_data_stream.flush();
        tty->print("# Compiler inline data is saved as: ");
        tty->print_cr("%s", buffer);
      } else {
        tty->print_cr("# Can't open file to dump inline data.");
      }
    }
  }
}
C:\hotspot-69087d08d473\src\share\vm/ci/ciEnv.hpp
#ifndef SHARE_VM_CI_CIENV_HPP
#define SHARE_VM_CI_CIENV_HPP
#include "ci/ciClassList.hpp"
#include "ci/ciObjectFactory.hpp"
#include "classfile/systemDictionary.hpp"
#include "code/debugInfoRec.hpp"
#include "code/dependencies.hpp"
#include "code/exceptionHandlerTable.hpp"
#include "compiler/oopMap.hpp"
#include "runtime/thread.hpp"
class CompileTask;
class ciEnv : StackObj {
  CI_PACKAGE_ACCESS_TO
  friend class CompileBroker;
  friend class Dependencies;  // for get_object, during logging
private:
  Arena*           _arena;       // Alias for _ciEnv_arena except in init_shared_objects()
  Arena            _ciEnv_arena;
  int              _system_dictionary_modification_counter;
  ciObjectFactory* _factory;
  OopRecorder*     _oop_recorder;
  DebugInformationRecorder* _debug_info;
  Dependencies*    _dependencies;
  const char*      _failure_reason;
  int              _compilable;
  bool             _break_at_compile;
  int              _num_inlined_bytecodes;
  CompileTask*     _task;           // faster access to CompilerThread::task
  CompileLog*      _log;            // faster access to CompilerThread::log
  void*            _compiler_data;  // compiler-specific stuff, if any
  char* _name_buffer;
  int   _name_buffer_len;
  bool  _jvmti_can_hotswap_or_post_breakpoint;
  bool  _jvmti_can_access_local_variables;
  bool  _jvmti_can_post_on_exceptions;
  bool  _jvmti_can_pop_frame;
  bool  _dtrace_extended_probes;
  bool  _dtrace_monitor_probes;
  bool  _dtrace_method_probes;
  bool  _dtrace_alloc_probes;
  static ciObject*              _null_object_instance;
#define WK_KLASS_DECL(name, ignore_s, ignore_o) static ciInstanceKlass* _##name;
  WK_KLASSES_DO(WK_KLASS_DECL)
#undef WK_KLASS_DECL
  static ciSymbol*        _unloaded_cisymbol;
  static ciInstanceKlass* _unloaded_ciinstance_klass;
  static ciObjArrayKlass* _unloaded_ciobjarrayklass;
  static jobject _ArrayIndexOutOfBoundsException_handle;
  static jobject _ArrayStoreException_handle;
  static jobject _ClassCastException_handle;
  ciInstance* _NullPointerException_instance;
  ciInstance* _ArithmeticException_instance;
  ciInstance* _ArrayIndexOutOfBoundsException_instance;
  ciInstance* _ArrayStoreException_instance;
  ciInstance* _ClassCastException_instance;
  ciInstance* _the_null_string;      // The Java string "null"
  ciInstance* _the_min_jint_string; // The Java string "-2147483648"
  ciKlass* get_klass_by_name(ciKlass* accessing_klass,
                             ciSymbol* klass_name,
                             bool require_local);
  ciKlass*   get_klass_by_index(constantPoolHandle cpool,
                                int klass_index,
                                bool& is_accessible,
                                ciInstanceKlass* loading_klass);
  ciConstant get_constant_by_index(constantPoolHandle cpool,
                                   int pool_index, int cache_index,
                                   ciInstanceKlass* accessor);
  ciField*   get_field_by_index(ciInstanceKlass* loading_klass,
                                int field_index);
  ciMethod*  get_method_by_index(constantPoolHandle cpool,
                                 int method_index, Bytecodes::Code bc,
                                 ciInstanceKlass* loading_klass);
  ciKlass* get_klass_by_name_impl(ciKlass* accessing_klass,
                                  constantPoolHandle cpool,
                                  ciSymbol* klass_name,
                                  bool require_local);
  ciKlass*   get_klass_by_index_impl(constantPoolHandle cpool,
                                     int klass_index,
                                     bool& is_accessible,
                                     ciInstanceKlass* loading_klass);
  ciConstant get_constant_by_index_impl(constantPoolHandle cpool,
                                        int pool_index, int cache_index,
                                        ciInstanceKlass* loading_klass);
  ciField*   get_field_by_index_impl(ciInstanceKlass* loading_klass,
                                     int field_index);
  ciMethod*  get_method_by_index_impl(constantPoolHandle cpool,
                                      int method_index, Bytecodes::Code bc,
                                      ciInstanceKlass* loading_klass);
  bool       check_klass_accessibility(ciKlass* accessing_klass,
                                      Klass* resolved_klass);
  Method*    lookup_method(InstanceKlass*  accessor,
                           InstanceKlass*  holder,
                           Symbol*         name,
                           Symbol*         sig,
                           Bytecodes::Code bc);
  ciObject* get_object(oop o) {
    if (o == NULL) {
      return _null_object_instance;
    } else {
      return _factory->get(o);
    }
  }
  ciSymbol* get_symbol(Symbol* o) {
    if (o == NULL) {
      ShouldNotReachHere();
      return NULL;
    } else {
      return _factory->get_symbol(o);
    }
  }
  ciMetadata* get_metadata(Metadata* o) {
    if (o == NULL) {
      return NULL;
    } else {
      return _factory->get_metadata(o);
    }
  }
  void ensure_metadata_alive(ciMetadata* m) {
    _factory->ensure_metadata_alive(m);
  }
  ciInstance* get_instance(oop o) {
    if (o == NULL) return NULL;
    return get_object(o)->as_instance();
  }
  ciObjArrayKlass* get_obj_array_klass(Klass* o) {
    if (o == NULL) return NULL;
    return get_metadata(o)->as_obj_array_klass();
  }
  ciTypeArrayKlass* get_type_array_klass(Klass* o) {
    if (o == NULL) return NULL;
    return get_metadata(o)->as_type_array_klass();
  }
  ciKlass* get_klass(Klass* o) {
    if (o == NULL) return NULL;
    return get_metadata(o)->as_klass();
  }
  ciInstanceKlass* get_instance_klass(Klass* o) {
    if (o == NULL) return NULL;
    return get_metadata(o)->as_instance_klass();
  }
  ciMethod* get_method(Method* o) {
    if (o == NULL) return NULL;
    return get_metadata(o)->as_method();
  }
  ciMethodData* get_method_data(MethodData* o) {
    if (o == NULL) return NULL;
    return get_metadata(o)->as_method_data();
  }
  ciMethod* get_method_from_handle(Method* method);
  ciInstance* get_or_create_exception(jobject& handle, Symbol* name);
  ciMethod* get_unloaded_method(ciInstanceKlass* holder,
                                ciSymbol*        name,
                                ciSymbol*        signature,
                                ciInstanceKlass* accessor) {
    return _factory->get_unloaded_method(holder, name, signature, accessor);
  }
  ciKlass* get_unloaded_klass(ciKlass*  accessing_klass,
                              ciSymbol* name) {
    return _factory->get_unloaded_klass(accessing_klass, name, true);
  }
  ciInstance* get_unloaded_klass_mirror(ciKlass* type) {
    return _factory->get_unloaded_klass_mirror(type);
  }
  ciInstance* get_unloaded_method_handle_constant(ciKlass*  holder,
                                                  ciSymbol* name,
                                                  ciSymbol* signature,
                                                  int       ref_kind) {
    return _factory->get_unloaded_method_handle_constant(holder, name, signature, ref_kind);
  }
  ciInstance* get_unloaded_method_type_constant(ciSymbol* signature) {
    return _factory->get_unloaded_method_type_constant(signature);
  }
  ciKlass *check_get_unloaded_klass(ciKlass*  accessing_klass, ciSymbol* name) {
    return _factory->get_unloaded_klass(accessing_klass, name, false);
  }
  ciReturnAddress* get_return_address(int bci) {
    return _factory->get_return_address(bci);
  }
  ciMethodData* get_empty_methodData() {
    return _factory->get_empty_methodData();
  }
  char* name_buffer(int req_len);
  static bool is_in_vm();
  void validate_compile_task_dependencies(ciMethod* target);
public:
  enum {
    MethodCompilable,
    MethodCompilable_not_at_tier,
    MethodCompilable_never
  };
  ciEnv(CompileTask* task, int system_dictionary_modification_counter);
  ciEnv(Arena* arena);
  ~ciEnv();
  OopRecorder* oop_recorder() { return _oop_recorder; }
  void set_oop_recorder(OopRecorder* r) { _oop_recorder = r; }
  DebugInformationRecorder* debug_info() { return _debug_info; }
  void set_debug_info(DebugInformationRecorder* i) { _debug_info = i; }
  Dependencies* dependencies() { return _dependencies; }
  void set_dependencies(Dependencies* d) { _dependencies = d; }
  bool failing() { return _failure_reason != NULL; }
  const char* failure_reason() { return _failure_reason; }
  int compilable() { return _compilable; }
  const char* retry_message() const {
    switch (_compilable) {
      case ciEnv::MethodCompilable_not_at_tier:
        return "retry at different tier";
      case ciEnv::MethodCompilable_never:
        return "not retryable";
      case ciEnv::MethodCompilable:
        return NULL;
      default:
        ShouldNotReachHere();
        return NULL;
    }
  }
  bool break_at_compile() { return _break_at_compile; }
  void set_break_at_compile(bool z) { _break_at_compile = z; }
  void  cache_jvmti_state();
  bool  jvmti_state_changed() const;
  bool  should_retain_local_variables() const;
  bool  jvmti_can_hotswap_or_post_breakpoint() const { return _jvmti_can_hotswap_or_post_breakpoint; }
  bool  jvmti_can_post_on_exceptions()         const { return _jvmti_can_post_on_exceptions; }
  void  cache_dtrace_flags();
  bool  dtrace_extended_probes() const { return _dtrace_extended_probes; }
  bool  dtrace_monitor_probes()  const { return _dtrace_monitor_probes; }
  bool  dtrace_method_probes()   const { return _dtrace_method_probes; }
  bool  dtrace_alloc_probes()    const { return _dtrace_alloc_probes; }
  CompileTask* task() { return _task; }
  int comp_level();   // task()->comp_level()
  uint compile_id();  // task()->compile_id()
  void register_method(ciMethod*                 target,
                       int                       entry_bci,
                       CodeOffsets*              offsets,
                       int                       orig_pc_offset,
                       CodeBuffer*               code_buffer,
                       int                       frame_words,
                       OopMapSet*                oop_map_set,
                       ExceptionHandlerTable*    handler_table,
                       ImplicitExceptionTable*   inc_table,
                       AbstractCompiler*         compiler,
                       int                       comp_level,
                       bool                      has_unsafe_access,
                       bool                      has_wide_vectors,
                       RTMState                  rtm_state = NoRTM);
#define WK_KLASS_FUNC(name, ignore_s, ignore_o) \
  ciInstanceKlass* name() { \
    return _##name;\
  }
  WK_KLASSES_DO(WK_KLASS_FUNC)
#undef WK_KLASS_FUNC
  ciInstance* NullPointerException_instance() {
    assert(_NullPointerException_instance != NULL, "initialization problem");
    return _NullPointerException_instance;
  }
  ciInstance* ArithmeticException_instance() {
    assert(_ArithmeticException_instance != NULL, "initialization problem");
    return _ArithmeticException_instance;
  }
  ciInstance* ArrayIndexOutOfBoundsException_instance();
  ciInstance* ArrayStoreException_instance();
  ciInstance* ClassCastException_instance();
  ciInstance* the_null_string();
  ciInstance* the_min_jint_string();
  static ciSymbol* unloaded_cisymbol() {
    return _unloaded_cisymbol;
  }
  static ciObjArrayKlass* unloaded_ciobjarrayklass() {
    return _unloaded_ciobjarrayklass;
  }
  static ciInstanceKlass* unloaded_ciinstance_klass() {
    return _unloaded_ciinstance_klass;
  }
  ciInstance* unloaded_ciinstance();
  ciKlass*  find_system_klass(ciSymbol* klass_name);
  static ciInstanceKlass* get_instance_klass_for_declared_method_holder(ciKlass* klass);
  int       array_element_offset_in_bytes(ciArray* a, ciObject* o);
  Arena*    arena() { return _arena; }
  static ciEnv* current() { return CompilerThread::current()->env(); }
  static ciEnv* current(CompilerThread *thread) { return thread->env(); }
  void* compiler_data() { return _compiler_data; }
  void set_compiler_data(void* x) { _compiler_data = x; }
  void notice_inlined_method(ciMethod* method);
  int num_inlined_bytecodes() const;
  CompileLog* log() { return _log; }
  void set_log(CompileLog* log) { _log = log; }
  bool system_dictionary_modification_counter_changed();
  void record_failure(const char* reason);
  void record_method_not_compilable(const char* reason, bool all_tiers = true);
  void record_out_of_memory_failure();
  void metadata_do(void f(Metadata*)) { _factory->metadata_do(f); }
  void dump_replay_data(int compile_id);
  void dump_inline_data(int compile_id);
  void dump_replay_data(outputStream* out);
  void dump_replay_data_unsafe(outputStream* out);
  void dump_compile_data(outputStream* out);
};
#endif // SHARE_VM_CI_CIENV_HPP
C:\hotspot-69087d08d473\src\share\vm/ci/ciExceptionHandler.cpp
#include "precompiled.hpp"
#include "ci/ciExceptionHandler.hpp"
#include "ci/ciUtilities.hpp"
ciInstanceKlass* ciExceptionHandler::catch_klass() {
  VM_ENTRY_MARK;
  assert(!is_catch_all(), "bad index");
  if (_catch_klass == NULL) {
    bool will_link;
    assert(_loading_klass->get_instanceKlass()->is_linked(), "must be linked before accessing constant pool");
    constantPoolHandle cpool(_loading_klass->get_instanceKlass()->constants());
    ciKlass* k = CURRENT_ENV->get_klass_by_index(cpool,
                                                 _catch_klass_index,
                                                 will_link,
                                                 _loading_klass);
    if (!will_link && k->is_loaded()) {
      GUARDED_VM_ENTRY(
        k = CURRENT_ENV->get_unloaded_klass(_loading_klass, k->name());
      )
    }
    _catch_klass = k->as_instance_klass();
  }
  return _catch_klass;
}
void ciExceptionHandler::print() {
  tty->print("<ciExceptionHandler start=%d limit=%d"
             " handler_bci=%d ex_klass_index=%d",
             start(), limit(), handler_bci(), catch_klass_index());
  if (_catch_klass != NULL) {
    tty->print(" ex_klass=");
    _catch_klass->print();
  }
  tty->print(">");
}
C:\hotspot-69087d08d473\src\share\vm/ci/ciExceptionHandler.hpp
#ifndef SHARE_VM_CI_CIEXCEPTIONHANDLER_HPP
#define SHARE_VM_CI_CIEXCEPTIONHANDLER_HPP
#include "ci/ciClassList.hpp"
#include "ci/ciInstanceKlass.hpp"
class ciExceptionHandler : public ResourceObj {
private:
  friend class ciMethod;
  ciInstanceKlass* _loading_klass;
  int _start;
  int _limit;
  int _handler_bci;
  int _catch_klass_index;
  ciInstanceKlass* _catch_klass;
public:
  ciExceptionHandler(ciInstanceKlass* loading_klass,
                     int start, int limit,
                     int handler_bci, int klass_index) {
    _loading_klass = loading_klass;
    _start  = start;
    _limit  = limit;
    _handler_bci = handler_bci;
    _catch_klass_index = klass_index;
    _catch_klass = NULL;
  }
  int       start()             { return _start; }
  int       limit()             { return _limit; }
  int       handler_bci()       { return _handler_bci; }
  int       catch_klass_index() { return _catch_klass_index; }
  ciInstanceKlass* catch_klass();
  bool      is_catch_all() { return catch_klass_index() == 0; }
  bool      is_in_range(int bci) {
    return start() <= bci && bci < limit();
  }
  bool      catches(ciInstanceKlass *exc) {
    return is_catch_all() || exc->is_subtype_of(catch_klass());
  }
  bool      is_rethrow() { return handler_bci() == -1; }
  void      print();
};
#endif // SHARE_VM_CI_CIEXCEPTIONHANDLER_HPP
C:\hotspot-69087d08d473\src\share\vm/ci/ciField.cpp
#include "precompiled.hpp"
#include "ci/ciField.hpp"
#include "ci/ciInstanceKlass.hpp"
#include "ci/ciUtilities.hpp"
#include "classfile/systemDictionary.hpp"
#include "gc_interface/collectedHeap.inline.hpp"
#include "interpreter/linkResolver.hpp"
#include "memory/universe.inline.hpp"
#include "oops/oop.inline.hpp"
#include "oops/oop.inline2.hpp"
#include "runtime/fieldDescriptor.hpp"
ciField::ciField(ciInstanceKlass* klass, int index): _known_to_link_with_put(NULL), _known_to_link_with_get(NULL) {
  ASSERT_IN_VM;
  CompilerThread *thread = CompilerThread::current();
  assert(ciObjectFactory::is_initialized(), "not a shared field");
  assert(klass->get_instanceKlass()->is_linked(), "must be linked before using its constan-pool");
  constantPoolHandle cpool(thread, klass->get_instanceKlass()->constants());
  Symbol* name  = cpool->name_ref_at(index);
  _name = ciEnv::current(thread)->get_symbol(name);
  int nt_index = cpool->name_and_type_ref_index_at(index);
  int sig_index = cpool->signature_ref_index_at(nt_index);
  Symbol* signature = cpool->symbol_at(sig_index);
  _signature = ciEnv::current(thread)->get_symbol(signature);
  BasicType field_type = FieldType::basic_type(signature);
  if (field_type == T_OBJECT || field_type == T_ARRAY) {
    bool ignore;
    _type = ciEnv::current(thread)->get_klass_by_index(cpool, sig_index, ignore, klass);
  } else {
    _type = ciType::make(field_type);
  }
  _name = (ciSymbol*)ciEnv::current(thread)->get_symbol(name);
  int holder_index = cpool->klass_ref_index_at(index);
  bool holder_is_accessible;
  ciInstanceKlass* declared_holder =
    ciEnv::current(thread)->get_klass_by_index(cpool, holder_index,
                                               holder_is_accessible,
                                               klass)->as_instance_klass();
  if (!holder_is_accessible) {
    _holder = declared_holder;
    _offset = -1;
    _is_constant = false;
    return;
  }
  InstanceKlass* loaded_decl_holder = declared_holder->get_instanceKlass();
  fieldDescriptor field_desc;
  Klass* canonical_holder =
    loaded_decl_holder->find_field(name, signature, &field_desc);
  if (canonical_holder == NULL) {
    _holder = declared_holder;
    _offset = -1;
    _is_constant = false;
    return;
  }
  if (!Reflection::verify_field_access(klass->get_Klass(), declared_holder->get_Klass(), canonical_holder, field_desc.access_flags(), true)) {
    _holder = declared_holder;
    _offset = -1;
    _is_constant = false;
    return;
  }
  assert(canonical_holder == field_desc.field_holder(), "just checking");
  initialize_from(&field_desc);
}
ciField::ciField(fieldDescriptor *fd): _known_to_link_with_put(NULL), _known_to_link_with_get(NULL) {
  ASSERT_IN_VM;
  ciEnv* env = CURRENT_ENV;
  _name = env->get_symbol(fd->name());
  _signature = env->get_symbol(fd->signature());
  BasicType field_type = fd->field_type();
  if (field_type == T_OBJECT || field_type == T_ARRAY) {
    _type = NULL;  // must call compute_type on first access
  } else {
    _type = ciType::make(field_type);
  }
  initialize_from(fd);
  assert(is_shared() || ciObjectFactory::is_initialized(),
         "bootstrap classes must not create & cache unshared fields");
}
static bool trust_final_non_static_fields(ciInstanceKlass* holder) {
  if (holder == NULL)
    return false;
  if (holder->name() == ciSymbol::java_lang_System())
    return false;
  if (holder->is_in_package("java/lang/invoke") || holder->is_in_package("sun/invoke"))
    return true;
  if (holder->name() == ciSymbol::java_util_concurrent_atomic_AtomicIntegerFieldUpdater_Impl() ||
      holder->name() == ciSymbol::java_util_concurrent_atomic_AtomicLongFieldUpdater_CASUpdater() ||
      holder->name() == ciSymbol::java_util_concurrent_atomic_AtomicLongFieldUpdater_LockedUpdater() ||
      holder->name() == ciSymbol::java_util_concurrent_atomic_AtomicReferenceFieldUpdater_Impl()) {
    return true;
  }
  return TrustFinalNonStaticFields;
}
void ciField::initialize_from(fieldDescriptor* fd) {
  _flags = ciFlags(fd->access_flags());
  _offset = fd->offset();
  _holder = CURRENT_ENV->get_instance_klass(fd->field_holder());
  bool is_final = this->is_final();
  bool is_stable = FoldStableValues && this->is_stable();
  if (_holder->is_initialized() && ((is_final && !has_initialized_final_update()) || is_stable)) {
    if (!this->is_static()) {
      if (is_stable || trust_final_non_static_fields(_holder)) {
        _is_constant = true;
        return;
      }
      _is_constant = false;
      return;
    }
    KlassHandle k = _holder->get_Klass();
    assert( SystemDictionary::System_klass() != NULL, "Check once per vm");
    if( k() == SystemDictionary::System_klass() ) {
      if( _offset == java_lang_System::in_offset_in_bytes()  ||
          _offset == java_lang_System::out_offset_in_bytes() ||
          _offset == java_lang_System::err_offset_in_bytes() ) {
        _is_constant = false;
        return;
      }
    }
    Handle mirror = k->java_mirror();
    switch(type()->basic_type()) {
    case T_BYTE:
      _constant_value = ciConstant(type()->basic_type(), mirror->byte_field(_offset));
      break;
    case T_CHAR:
      _constant_value = ciConstant(type()->basic_type(), mirror->char_field(_offset));
      break;
    case T_SHORT:
      _constant_value = ciConstant(type()->basic_type(), mirror->short_field(_offset));
      break;
    case T_BOOLEAN:
      _constant_value = ciConstant(type()->basic_type(), mirror->bool_field(_offset));
      break;
    case T_INT:
      _constant_value = ciConstant(type()->basic_type(), mirror->int_field(_offset));
      break;
    case T_FLOAT:
      _constant_value = ciConstant(mirror->float_field(_offset));
      break;
    case T_DOUBLE:
      _constant_value = ciConstant(mirror->double_field(_offset));
      break;
    case T_LONG:
      _constant_value = ciConstant(mirror->long_field(_offset));
      break;
    case T_OBJECT:
    case T_ARRAY:
      {
        oop o = mirror->obj_field(_offset);
        if (o == NULL) {
          _constant_value = ciConstant(type()->basic_type(), ciNullObject::make());
        } else {
          _constant_value = ciConstant(type()->basic_type(), CURRENT_ENV->get_object(o));
          assert(_constant_value.as_object() == CURRENT_ENV->get_object(o), "check interning");
        }
      }
    }
    if (is_stable && _constant_value.is_null_or_zero()) {
      _is_constant = false;
    } else {
      _is_constant = true;
    }
  } else {
    _is_constant = false;
  }
}
ciType* ciField::compute_type() {
  GUARDED_VM_ENTRY(return compute_type_impl();)
}
ciType* ciField::compute_type_impl() {
  ciKlass* type = CURRENT_ENV->get_klass_by_name_impl(_holder, constantPoolHandle(), _signature, false);
  if (!type->is_primitive_type() && is_shared()) {
    bool type_is_also_shared = false;
    if (type->is_type_array_klass()) {
      type_is_also_shared = true;  // int[] etc. are explicitly bootstrapped
    } else if (type->is_instance_klass()) {
      type_is_also_shared = type->as_instance_klass()->is_shared();
    } else {
      type_is_also_shared = !ciObjectFactory::is_initialized();
    }
    if (!type_is_also_shared)
      return type;              // Bummer.
  }
  _type = type;
  return type;
}
bool ciField::will_link(ciInstanceKlass* accessing_klass,
                        Bytecodes::Code bc) {
  VM_ENTRY_MARK;
  assert(bc == Bytecodes::_getstatic || bc == Bytecodes::_putstatic ||
         bc == Bytecodes::_getfield  || bc == Bytecodes::_putfield,
         "unexpected bytecode");
  if (_offset == -1) {
    return false;
  }
  bool is_static = (bc == Bytecodes::_getstatic || bc == Bytecodes::_putstatic);
  if (is_static != this->is_static()) {
    return false;
  }
  bool is_put    = (bc == Bytecodes::_putfield  || bc == Bytecodes::_putstatic);
  if (is_put) {
    if (_known_to_link_with_put == accessing_klass) {
      return true;
    }
  } else {
    if (_known_to_link_with_get == accessing_klass) {
      return true;
    }
  }
  fieldDescriptor result;
  LinkResolver::resolve_field(result, _holder->get_instanceKlass(),
                              _name->get_symbol(), _signature->get_symbol(),
                              accessing_klass->get_Klass(), bc, true, false,
                              KILL_COMPILE_ON_FATAL_(false));
  if (accessing_klass->is_shared() || !is_shared()) {
    if (is_put) {
      _known_to_link_with_put = accessing_klass;
    } else {
      _known_to_link_with_get = accessing_klass;
    }
  }
  return true;
}
void ciField::print() {
  tty->print("<ciField name=");
  _holder->print_name();
  tty->print(".");
  _name->print_symbol();
  tty->print(" signature=");
  _signature->print_symbol();
  tty->print(" offset=%d type=", _offset);
  if (_type != NULL)
    _type->print_name();
  else
    tty->print("(reference)");
  tty->print(" flags=%04x", flags().as_int());
  tty->print(" is_constant=%s", bool_to_str(_is_constant));
  if (_is_constant && is_static()) {
    tty->print(" constant_value=");
    _constant_value.print();
  }
  tty->print(">");
}
void ciField::print_name_on(outputStream* st) {
  name()->print_symbol_on(st);
}
C:\hotspot-69087d08d473\src\share\vm/ci/ciField.hpp
#ifndef SHARE_VM_CI_CIFIELD_HPP
#define SHARE_VM_CI_CIFIELD_HPP
#include "ci/ciClassList.hpp"
#include "ci/ciConstant.hpp"
#include "ci/ciFlags.hpp"
#include "ci/ciInstance.hpp"
class ciField : public ResourceObj {
  CI_PACKAGE_ACCESS
  friend class ciEnv;
  friend class ciInstanceKlass;
  friend class NonStaticFieldFiller;
private:
  ciFlags          _flags;
  ciInstanceKlass* _holder;
  ciSymbol*        _name;
  ciSymbol*        _signature;
  ciType*          _type;
  int              _offset;
  bool             _is_constant;
  ciInstanceKlass* _known_to_link_with_put;
  ciInstanceKlass* _known_to_link_with_get;
  ciConstant       _constant_value;
  ciType* compute_type();
  ciType* compute_type_impl();
  ciField(ciInstanceKlass* klass, int index);
  ciField(fieldDescriptor* fd);
  void initialize_from(fieldDescriptor* fd);
public:
  ciFlags flags() { return _flags; }
  ciInstanceKlass* holder() { return _holder; }
  ciSymbol* name() { return _name; }
  ciSymbol* signature() { return _signature; }
  ciType* type() { return (_type == NULL) ? compute_type() : _type; }
  BasicType layout_type() { return type2field[(_type == NULL) ? T_OBJECT : _type->basic_type()]; }
  int size_in_bytes() { return type2aelembytes(layout_type()); }
  int offset() {
    assert(_offset >= 1, "illegal call to offset()");
    return _offset;
  }
  int offset_in_bytes() {
    return offset();
  }
  bool is_shared() {
    return _holder->is_shared() && !is_static();
  }
  bool is_constant() { return _is_constant; }
  ciConstant constant_value() {
    assert(is_static() && is_constant(), "illegal call to constant_value()");
    return _constant_value;
  }
  ciConstant constant_value_of(ciObject* object) {
    assert(!is_static() && is_constant(), "only if field is non-static constant");
    assert(object->is_instance(), "must be instance");
    return object->as_instance()->field_value(this);
  }
  bool will_link(ciInstanceKlass* accessing_klass,
                 Bytecodes::Code bc);
  bool is_public      () { return flags().is_public(); }
  bool is_private     () { return flags().is_private(); }
  bool is_protected   () { return flags().is_protected(); }
  bool is_static      () { return flags().is_static(); }
  bool is_final       () { return flags().is_final(); }
  bool is_stable      () { return flags().is_stable(); }
  bool is_volatile    () { return flags().is_volatile(); }
  bool is_transient   () { return flags().is_transient(); }
  bool has_initialized_final_update() { return flags().has_initialized_final_update(); }
  bool is_call_site_target() {
    ciInstanceKlass* callsite_klass = CURRENT_ENV->CallSite_klass();
    if (callsite_klass == NULL)
      return false;
    return (holder()->is_subclass_of(callsite_klass) && (name() == ciSymbol::target_name()));
  }
  void print();
  void print_name_on(outputStream* st);
};
#endif // SHARE_VM_CI_CIFIELD_HPP
C:\hotspot-69087d08d473\src\share\vm/ci/ciFlags.cpp
#include "precompiled.hpp"
#include "ci/ciFlags.hpp"
void ciFlags::print_klass_flags(outputStream* st) {
  if (is_public()) {
    st->print("public");
  } else {
    st->print("DEFAULT_ACCESS");
  }
  if (is_final()) {
    st->print(",final");
  }
  if (is_super()) {
    st->print(",super");
  }
  if (is_interface()) {
    st->print(",interface");
  }
  if (is_abstract()) {
    st->print(",abstract");
  }
}
void ciFlags::print_member_flags(outputStream* st) {
  if (is_public()) {
    st->print("public");
  } else if (is_private()) {
    st->print("private");
  } else if (is_protected()) {
    st->print("protected");
  } else {
    st->print("DEFAULT_ACCESS");
  }
  if (is_static()) {
    st->print(",static");
  }
  if (is_final()) {
    st->print(",final");
  }
  if (is_synchronized()) {
    st->print(",synchronized");
  }
  if (is_volatile()) {
    st->print(",volatile");
  }
  if (is_transient()) {
    st->print(",transient");
  }
  if (is_native()) {
    st->print(",native");
  }
  if (is_abstract()) {
    st->print(",abstract");
  }
  if (is_strict()) {
    st->print(",strict");
  }
}
void ciFlags::print(outputStream* st) {
  st->print(" flags=%x", _flags);
}
C:\hotspot-69087d08d473\src\share\vm/ci/ciFlags.hpp
#ifndef SHARE_VM_CI_CIFLAGS_HPP
#define SHARE_VM_CI_CIFLAGS_HPP
#include "ci/ciClassList.hpp"
#include "memory/allocation.hpp"
#include "prims/jvm.h"
#include "utilities/accessFlags.hpp"
class ciFlags VALUE_OBJ_CLASS_SPEC {
private:
  friend class ciInstanceKlass;
  friend class ciField;
  friend class ciMethod;
  jint _flags;
  ciFlags()                  { _flags = 0; }
  ciFlags(AccessFlags flags) { _flags = flags.as_int(); }
public:
  bool is_public               () const { return (_flags & JVM_ACC_PUBLIC                    ) != 0; }
  bool is_private              () const { return (_flags & JVM_ACC_PRIVATE                   ) != 0; }
  bool is_protected            () const { return (_flags & JVM_ACC_PROTECTED                 ) != 0; }
  bool is_static               () const { return (_flags & JVM_ACC_STATIC                    ) != 0; }
  bool is_final                () const { return (_flags & JVM_ACC_FINAL                     ) != 0; }
  bool is_synchronized         () const { return (_flags & JVM_ACC_SYNCHRONIZED              ) != 0; }
  bool is_super                () const { return (_flags & JVM_ACC_SUPER                     ) != 0; }
  bool is_volatile             () const { return (_flags & JVM_ACC_VOLATILE                  ) != 0; }
  bool is_transient            () const { return (_flags & JVM_ACC_TRANSIENT                 ) != 0; }
  bool is_native               () const { return (_flags & JVM_ACC_NATIVE                    ) != 0; }
  bool is_interface            () const { return (_flags & JVM_ACC_INTERFACE                 ) != 0; }
  bool is_abstract             () const { return (_flags & JVM_ACC_ABSTRACT                  ) != 0; }
  bool is_strict               () const { return (_flags & JVM_ACC_STRICT                    ) != 0; }
  bool is_stable               () const { return (_flags & JVM_ACC_FIELD_STABLE              ) != 0; }
  bool has_initialized_final_update() const { return (_flags & JVM_ACC_FIELD_INITIALIZED_FINAL_UPDATE) != 0; };
  jint   as_int()                      { return _flags; }
  void print_klass_flags(outputStream* st = tty);
  void print_member_flags(outputStream* st = tty);
  void print(outputStream* st = tty);
};
#endif // SHARE_VM_CI_CIFLAGS_HPP
C:\hotspot-69087d08d473\src\share\vm/ci/ciInstance.cpp
#include "precompiled.hpp"
#include "ci/ciConstant.hpp"
#include "ci/ciField.hpp"
#include "ci/ciInstance.hpp"
#include "ci/ciInstanceKlass.hpp"
#include "ci/ciUtilities.hpp"
#include "classfile/systemDictionary.hpp"
#include "oops/oop.inline.hpp"
ciType* ciInstance::java_mirror_type() {
  VM_ENTRY_MARK;
  oop m = get_oop();
  if (m == NULL || m->klass() != SystemDictionary::Class_klass()) {
    return NULL;
  }
  if (java_lang_Class::is_primitive(m)) {
    return ciType::make(java_lang_Class::primitive_type(m));
  } else {
    Klass* k = java_lang_Class::as_Klass(m);
    assert(k != NULL, "");
    return CURRENT_THREAD_ENV->get_klass(k);
  }
}
ciConstant ciInstance::field_value(ciField* field) {
  assert(is_loaded(), "invalid access - must be loaded");
  assert(field->holder()->is_loaded(), "invalid access - holder must be loaded");
  assert(klass()->is_subclass_of(field->holder()), "invalid access - must be subclass");
  VM_ENTRY_MARK;
  ciConstant result;
  Handle obj = get_oop();
  assert(!obj.is_null(), "bad oop");
  BasicType field_btype = field->type()->basic_type();
  int offset = field->offset();
  switch(field_btype) {
  case T_BYTE:
    return ciConstant(field_btype, obj->byte_field(offset));
    break;
  case T_CHAR:
    return ciConstant(field_btype, obj->char_field(offset));
    break;
  case T_SHORT:
    return ciConstant(field_btype, obj->short_field(offset));
    break;
  case T_BOOLEAN:
    return ciConstant(field_btype, obj->bool_field(offset));
    break;
  case T_INT:
    return ciConstant(field_btype, obj->int_field(offset));
    break;
  case T_FLOAT:
    return ciConstant(obj->float_field(offset));
    break;
  case T_DOUBLE:
    return ciConstant(obj->double_field(offset));
    break;
  case T_LONG:
    return ciConstant(obj->long_field(offset));
    break;
  case T_OBJECT:
  case T_ARRAY:
    {
      oop o = obj->obj_field(offset);
      if (o == NULL) {
        return ciConstant(field_btype, ciNullObject::make());
      } else {
        return ciConstant(field_btype, CURRENT_ENV->get_object(o));
      }
    }
  }
  ShouldNotReachHere();
  return ciConstant();
}
ciConstant ciInstance::field_value_by_offset(int field_offset) {
  ciInstanceKlass* ik = klass()->as_instance_klass();
  ciField* field = ik->get_field_by_offset(field_offset, false);
  if (field == NULL)
    return ciConstant();  // T_ILLEGAL
  return field_value(field);
}
void ciInstance::print_impl(outputStream* st) {
  st->print(" type=");
  klass()->print(st);
}
ciKlass* ciInstance::java_lang_Class_klass() {
  VM_ENTRY_MARK;
  return CURRENT_ENV->get_metadata(java_lang_Class::as_Klass(get_oop()))->as_klass();
}
C:\hotspot-69087d08d473\src\share\vm/ci/ciInstance.hpp
#ifndef SHARE_VM_CI_CIINSTANCE_HPP
#define SHARE_VM_CI_CIINSTANCE_HPP
#include "ci/ciObject.hpp"
#include "oops/instanceOop.hpp"
class ciInstance : public ciObject {
  CI_PACKAGE_ACCESS
protected:
  ciInstance(instanceHandle h_i) : ciObject(h_i) {
    assert(h_i()->is_instance(), "wrong type");
  }
  ciInstance(ciKlass* klass) : ciObject(klass) {}
  instanceOop get_instanceOop() { return (instanceOop)get_oop(); }
  const char* type_string() { return "ciInstance"; }
  void print_impl(outputStream* st);
public:
  ciType* java_mirror_type();
  bool is_instance()     { return true; }
  bool is_java_object()  { return true; }
  ciConstant field_value(ciField* field);
  ciConstant field_value_by_offset(int field_offset);
  ciKlass* java_lang_Class_klass();
};
#endif // SHARE_VM_CI_CIINSTANCE_HPP
C:\hotspot-69087d08d473\src\share\vm/ci/ciInstanceKlass.cpp
#include "precompiled.hpp"
#include "ci/ciField.hpp"
#include "ci/ciInstance.hpp"
#include "ci/ciInstanceKlass.hpp"
#include "ci/ciUtilities.hpp"
#include "classfile/systemDictionary.hpp"
#include "memory/allocation.hpp"
#include "memory/allocation.inline.hpp"
#include "oops/oop.inline.hpp"
#include "oops/fieldStreams.hpp"
#include "runtime/fieldDescriptor.hpp"
ciInstanceKlass::ciInstanceKlass(KlassHandle h_k) :
  ciKlass(h_k), _non_static_fields(NULL)
{
  assert(get_Klass()->oop_is_instance(), "wrong type");
  assert(get_instanceKlass()->is_loaded(), "must be at least loaded");
  InstanceKlass* ik = get_instanceKlass();
  AccessFlags access_flags = ik->access_flags();
  _flags = ciFlags(access_flags);
  _has_finalizer = access_flags.has_finalizer();
  _has_subklass = ik->subklass() != NULL;
  _init_state = ik->init_state();
  _nonstatic_field_size = ik->nonstatic_field_size();
  _has_nonstatic_fields = ik->has_nonstatic_fields();
  _has_default_methods = ik->has_default_methods();
  _is_anonymous = ik->is_anonymous();
  _nonstatic_fields = NULL; // initialized lazily by compute_nonstatic_fields:
  _implementor = NULL; // we will fill these lazily
  Thread *thread = Thread::current();
  if (ciObjectFactory::is_initialized()) {
    _loader = JNIHandles::make_local(thread, ik->class_loader());
    _protection_domain = JNIHandles::make_local(thread,
                                                ik->protection_domain());
    _is_shared = false;
  } else {
    Handle h_loader(thread, ik->class_loader());
    Handle h_protection_domain(thread, ik->protection_domain());
    _loader = JNIHandles::make_global(h_loader);
    _protection_domain = JNIHandles::make_global(h_protection_domain);
    _is_shared = true;
  }
  _super  = NULL;
  _java_mirror = NULL;
  if (is_shared()) {
    if (h_k() != SystemDictionary::Object_klass()) {
      super();
    }
  }
  _field_cache = NULL;
}
ciInstanceKlass::ciInstanceKlass(ciSymbol* name,
                                 jobject loader, jobject protection_domain)
  : ciKlass(name, T_OBJECT)
{
  assert(name->byte_at(0) != '[', "not an instance klass");
  _init_state = (InstanceKlass::ClassState)0;
  _nonstatic_field_size = -1;
  _has_nonstatic_fields = false;
  _nonstatic_fields = NULL;
  _is_anonymous = false;
  _loader = loader;
  _protection_domain = protection_domain;
  _is_shared = false;
  _super = NULL;
  _java_mirror = NULL;
  _field_cache = NULL;
}
void ciInstanceKlass::compute_shared_init_state() {
  GUARDED_VM_ENTRY(
    InstanceKlass* ik = get_instanceKlass();
    _init_state = ik->init_state();
  )
}
bool ciInstanceKlass::compute_shared_has_subklass() {
  GUARDED_VM_ENTRY(
    InstanceKlass* ik = get_instanceKlass();
    _has_subklass = ik->subklass() != NULL;
    return _has_subklass;
  )
}
oop ciInstanceKlass::loader() {
  ASSERT_IN_VM;
  return JNIHandles::resolve(_loader);
}
jobject ciInstanceKlass::loader_handle() {
  return _loader;
}
oop ciInstanceKlass::protection_domain() {
  ASSERT_IN_VM;
  return JNIHandles::resolve(_protection_domain);
}
jobject ciInstanceKlass::protection_domain_handle() {
  return _protection_domain;
}
ciConstantPoolCache* ciInstanceKlass::field_cache() {
  if (is_shared()) {
    return NULL;
  }
  if (_field_cache == NULL) {
    assert(!is_java_lang_Object(), "Object has no fields");
    Arena* arena = CURRENT_ENV->arena();
    _field_cache = new (arena) ciConstantPoolCache(arena, 5);
  }
  return _field_cache;
}
ciInstanceKlass* ciInstanceKlass::get_canonical_holder(int offset) {
  #ifdef ASSERT
  if (!(offset >= 0 && offset < layout_helper())) {
    tty->print("*** get_canonical_holder(%d) on ", offset);
    this->print();
    tty->print_cr(" ***");
  };
  assert(offset >= 0 && offset < layout_helper(), "offset must be tame");
  #endif
  if (offset < instanceOopDesc::base_offset_in_bytes()) {
    return CURRENT_ENV->Object_klass();
  }
  ciInstanceKlass* self = this;
  for (;;) {
    assert(self->is_loaded(), "must be loaded to have size");
    ciInstanceKlass* super = self->super();
    if (super == NULL || super->nof_nonstatic_fields() == 0 ||
        !super->contains_field_offset(offset)) {
      return self;
    } else {
      self = super;  // return super->get_canonical_holder(offset)
    }
  }
}
bool ciInstanceKlass::is_java_lang_Object() const {
  return equals(CURRENT_ENV->Object_klass());
}
bool ciInstanceKlass::uses_default_loader() const {
  return _loader == NULL;
}
BasicType ciInstanceKlass::box_klass_type() const {
  if (uses_default_loader() && is_loaded()) {
    return SystemDictionary::box_klass_type(get_Klass());
  } else {
    return T_OBJECT;
  }
}
bool ciInstanceKlass::is_box_klass() const {
  return is_java_primitive(box_klass_type());
}
bool ciInstanceKlass::is_boxed_value_offset(int offset) const {
  BasicType bt = box_klass_type();
  return is_java_primitive(bt) &&
         (offset == java_lang_boxing_object::value_offset_in_bytes(bt));
}
bool ciInstanceKlass::is_in_package(const char* packagename, int len) {
  if (!uses_default_loader())
    return false;
  GUARDED_VM_ENTRY(
    return is_in_package_impl(packagename, len);
  )
}
bool ciInstanceKlass::is_in_package_impl(const char* packagename, int len) {
  ASSERT_IN_VM;
  if (packagename[len - 1] == '/')
    len--;
  if (!name()->starts_with(packagename, len))
    return false;
  if ((len + 1) > name()->utf8_length())
    return false;
  if ((char) name()->byte_at(len) != '/')
    return false;
  if (name()->index_of_at(len+1, "/", 1) >= 0)
    return false;
  return true;
}
void ciInstanceKlass::print_impl(outputStream* st) {
  ciKlass::print_impl(st);
  GUARDED_VM_ENTRY(st->print(" loader=" INTPTR_FORMAT, p2i((address)loader()));)
  if (is_loaded()) {
    st->print(" loaded=true initialized=%s finalized=%s subklass=%s size=%d flags=",
              bool_to_str(is_initialized()),
              bool_to_str(has_finalizer()),
              bool_to_str(has_subklass()),
              layout_helper());
    _flags.print_klass_flags();
    if (_super) {
      st->print(" super=");
      _super->print_name();
    }
    if (_java_mirror) {
      st->print(" mirror=PRESENT");
    }
  } else {
    st->print(" loaded=false");
  }
}
ciInstanceKlass* ciInstanceKlass::super() {
  assert(is_loaded(), "must be loaded");
  if (_super == NULL && !is_java_lang_Object()) {
    GUARDED_VM_ENTRY(
      Klass* super_klass = get_instanceKlass()->super();
      _super = CURRENT_ENV->get_instance_klass(super_klass);
    )
  }
  return _super;
}
ciInstance* ciInstanceKlass::java_mirror() {
  if (is_shared()) {
    return ciKlass::java_mirror();
  }
  if (_java_mirror == NULL) {
    _java_mirror = ciKlass::java_mirror();
  }
  return _java_mirror;
}
ciInstanceKlass* ciInstanceKlass::unique_concrete_subklass() {
  if (!is_loaded())     return NULL; // No change if class is not loaded
  if (!is_abstract())   return NULL; // Only applies to abstract classes.
  if (!has_subklass())  return NULL; // Must have at least one subklass.
  VM_ENTRY_MARK;
  InstanceKlass* ik = get_instanceKlass();
  Klass* up = ik->up_cast_abstract();
  assert(up->oop_is_instance(), "must be InstanceKlass");
  if (ik == up) {
    return NULL;
  }
  return CURRENT_THREAD_ENV->get_instance_klass(up);
}
bool ciInstanceKlass::has_finalizable_subclass() {
  if (!is_loaded())     return true;
  VM_ENTRY_MARK;
  return Dependencies::find_finalizable_subclass(get_instanceKlass()) != NULL;
}
ciField* ciInstanceKlass::get_field_by_offset(int field_offset, bool is_static) {
  if (!is_static) {
    for (int i = 0, len = nof_nonstatic_fields(); i < len; i++) {
      ciField* field = _nonstatic_fields->at(i);
      int  field_off = field->offset_in_bytes();
      if (field_off == field_offset)
        return field;
      if (field_off > field_offset)
        break;
    }
    return NULL;
  }
  VM_ENTRY_MARK;
  InstanceKlass* k = get_instanceKlass();
  fieldDescriptor fd;
  if (!k->find_field_from_offset(field_offset, is_static, &fd)) {
    return NULL;
  }
  ciField* field = new (CURRENT_THREAD_ENV->arena()) ciField(&fd);
  return field;
}
ciField* ciInstanceKlass::get_field_by_name(ciSymbol* name, ciSymbol* signature, bool is_static) {
  VM_ENTRY_MARK;
  InstanceKlass* k = get_instanceKlass();
  fieldDescriptor fd;
  Klass* def = k->find_field(name->get_symbol(), signature->get_symbol(), is_static, &fd);
  if (def == NULL) {
    return NULL;
  }
  ciField* field = new (CURRENT_THREAD_ENV->arena()) ciField(&fd);
  return field;
}
class NonStaticFieldFiller: public FieldClosure {
  GrowableArray<ciField*>* _arr;
  ciEnv* _curEnv;
public:
  NonStaticFieldFiller(ciEnv* curEnv, GrowableArray<ciField*>* arr) :
    _curEnv(curEnv), _arr(arr)
  {}
  void do_field(fieldDescriptor* fd) {
    ciField* field = new (_curEnv->arena()) ciField(fd);
    _arr->append(field);
  }
};
GrowableArray<ciField*>* ciInstanceKlass::non_static_fields() {
  if (_non_static_fields == NULL) {
    VM_ENTRY_MARK;
    ciEnv* curEnv = ciEnv::current();
    InstanceKlass* ik = get_instanceKlass();
    int max_n_fields = ik->java_fields_count();
    Arena* arena = curEnv->arena();
    _non_static_fields =
      new (arena) GrowableArray<ciField*>(arena, max_n_fields, 0, NULL);
    NonStaticFieldFiller filler(curEnv, _non_static_fields);
    ik->do_nonstatic_fields(&filler);
  }
  return _non_static_fields;
}
static int sort_field_by_offset(ciField** a, ciField** b) {
  return (*a)->offset_in_bytes() - (*b)->offset_in_bytes();
}
int ciInstanceKlass::compute_nonstatic_fields() {
  assert(is_loaded(), "must be loaded");
  if (_nonstatic_fields != NULL)
    return _nonstatic_fields->length();
  if (!has_nonstatic_fields()) {
    Arena* arena = CURRENT_ENV->arena();
    _nonstatic_fields = new (arena) GrowableArray<ciField*>(arena, 0, 0, NULL);
    return 0;
  }
  assert(!is_java_lang_Object(), "bootstrap OK");
  int fsize = nonstatic_field_size() * heapOopSize;
  ciInstanceKlass* super = this->super();
  GrowableArray<ciField*>* super_fields = NULL;
  if (super != NULL && super->has_nonstatic_fields()) {
    int super_fsize  = super->nonstatic_field_size() * heapOopSize;
    int super_flen   = super->nof_nonstatic_fields();
    super_fields = super->_nonstatic_fields;
    assert(super_flen == 0 || super_fields != NULL, "first get nof_fields");
    if (fsize == super_fsize) {
      _nonstatic_fields = super_fields;
      return super_fields->length();
    }
  }
  GrowableArray<ciField*>* fields = NULL;
  GUARDED_VM_ENTRY({
      fields = compute_nonstatic_fields_impl(super_fields);
    });
  if (fields == NULL) {
    _nonstatic_fields = super_fields;
    return super_fields->length();
  }
  int flen = fields->length();
  fields->sort(sort_field_by_offset);
  _nonstatic_fields = fields;
  return flen;
}
GrowableArray<ciField*>*
ciInstanceKlass::compute_nonstatic_fields_impl(GrowableArray<ciField*>*
                                               super_fields) {
  ASSERT_IN_VM;
  Arena* arena = CURRENT_ENV->arena();
  int flen = 0;
  GrowableArray<ciField*>* fields = NULL;
  InstanceKlass* k = get_instanceKlass();
  for (JavaFieldStream fs(k); !fs.done(); fs.next()) {
    if (fs.access_flags().is_static())  continue;
    flen += 1;
  }
  if (flen == 0) {
    return NULL;  // return nothing if none are locally declared
  }
  if (super_fields != NULL) {
    flen += super_fields->length();
  }
  fields = new (arena) GrowableArray<ciField*>(arena, flen, 0, NULL);
  if (super_fields != NULL) {
    fields->appendAll(super_fields);
  }
  for (JavaFieldStream fs(k); !fs.done(); fs.next()) {
    if (fs.access_flags().is_static())  continue;
    fieldDescriptor& fd = fs.field_descriptor();
    ciField* field = new (arena) ciField(&fd);
    fields->append(field);
  }
  assert(fields->length() == flen, "sanity");
  return fields;
}
ciMethod* ciInstanceKlass::find_method(ciSymbol* name, ciSymbol* signature) {
  VM_ENTRY_MARK;
  InstanceKlass* k = get_instanceKlass();
  Symbol* name_sym = name->get_symbol();
  Symbol* sig_sym= signature->get_symbol();
  Method* m = k->find_method(name_sym, sig_sym);
  if (m == NULL)  return NULL;
  return CURRENT_THREAD_ENV->get_method(m);
}
bool ciInstanceKlass::is_leaf_type() {
  assert(is_loaded(), "must be loaded");
  if (is_shared()) {
    return is_final();  // approximately correct
  } else {
    return !_has_subklass && (nof_implementors() == 0);
  }
}
ciInstanceKlass* ciInstanceKlass::implementor() {
  ciInstanceKlass* impl = _implementor;
  if (impl == NULL) {
    {
      VM_ENTRY_MARK;
      Klass* k = get_instanceKlass()->implementor();
      if (k != NULL) {
        if (k == get_instanceKlass()) {
          impl = this;
        } else {
          impl = CURRENT_THREAD_ENV->get_instance_klass(k);
        }
      }
    }
    if (!is_shared()) {
      _implementor = impl;
    }
  }
  return impl;
}
ciInstanceKlass* ciInstanceKlass::host_klass() {
  assert(is_loaded(), "must be loaded");
  if (is_anonymous()) {
    VM_ENTRY_MARK
    Klass* host_klass = get_instanceKlass()->host_klass();
    return CURRENT_ENV->get_instance_klass(host_klass);
  }
  return NULL;
}
class StaticFinalFieldPrinter : public FieldClosure {
  outputStream* _out;
  const char*   _holder;
 public:
  StaticFinalFieldPrinter(outputStream* out, const char* holder) :
    _out(out),
    _holder(holder) {
  }
  void do_field(fieldDescriptor* fd) {
    if (fd->is_final() && !fd->has_initial_value()) {
      ResourceMark rm;
      oop mirror = fd->field_holder()->java_mirror();
      _out->print("staticfield %s %s %s ", _holder, fd->name()->as_quoted_ascii(), fd->signature()->as_quoted_ascii());
      switch (fd->field_type()) {
        case T_BYTE:    _out->print_cr("%d", mirror->byte_field(fd->offset()));   break;
        case T_BOOLEAN: _out->print_cr("%d", mirror->bool_field(fd->offset()));   break;
        case T_SHORT:   _out->print_cr("%d", mirror->short_field(fd->offset()));  break;
        case T_CHAR:    _out->print_cr("%d", mirror->char_field(fd->offset()));   break;
        case T_INT:     _out->print_cr("%d", mirror->int_field(fd->offset()));    break;
        case T_LONG:    _out->print_cr(INT64_FORMAT, (int64_t)(mirror->long_field(fd->offset())));   break;
        case T_FLOAT: {
          float f = mirror->float_field(fd->offset());
          _out->print_cr("%d", *(int*)&f);
          break;
        }
        case T_DOUBLE: {
          double d = mirror->double_field(fd->offset());
          _out->print_cr(INT64_FORMAT, *(int64_t*)&d);
          break;
        }
        case T_ARRAY: {
          oop value =  mirror->obj_field_acquire(fd->offset());
          if (value == NULL) {
            _out->print_cr("null");
          } else {
            typeArrayOop ta = (typeArrayOop)value;
            _out->print("%d", ta->length());
            if (value->is_objArray()) {
              objArrayOop oa = (objArrayOop)value;
              const char* klass_name  = value->klass()->name()->as_quoted_ascii();
              _out->print(" %s", klass_name);
            }
            _out->cr();
          }
          break;
        }
        case T_OBJECT: {
          oop value =  mirror->obj_field_acquire(fd->offset());
          if (value == NULL) {
            _out->print_cr("null");
          } else if (value->is_instance()) {
            if (value->is_a(SystemDictionary::String_klass())) {
              _out->print("\"");
              _out->print_raw(java_lang_String::as_quoted_ascii(value));
              _out->print_cr("\"");
            } else {
              const char* klass_name  = value->klass()->name()->as_quoted_ascii();
              _out->print_cr("%s", klass_name);
            }
          } else {
            ShouldNotReachHere();
          }
          break;
        }
        default:
          ShouldNotReachHere();
        }
    }
  }
};
void ciInstanceKlass::dump_replay_data(outputStream* out) {
  ResourceMark rm;
  InstanceKlass* ik = get_instanceKlass();
  ConstantPool*  cp = ik->constants();
  Klass* sub = ik->subklass();
  while (sub != NULL) {
    if (sub->oop_is_instance()) {
      out->print_cr("instanceKlass %s", sub->name()->as_quoted_ascii());
    }
    sub = sub->next_sibling();
  }
  out->print("ciInstanceKlass %s %d %d %d", ik->name()->as_quoted_ascii(),
             is_linked(), is_initialized(), cp->length());
  for (int index = 1; index < cp->length(); index++) {
    out->print(" %d", cp->tags()->at(index));
  }
  out->cr();
  if (is_initialized()) {
    StaticFinalFieldPrinter sffp(out, ik->name()->as_quoted_ascii());
    ik->do_local_static_fields(&sffp);
  }
}
C:\hotspot-69087d08d473\src\share\vm/ci/ciInstanceKlass.hpp
#ifndef SHARE_VM_CI_CIINSTANCEKLASS_HPP
#define SHARE_VM_CI_CIINSTANCEKLASS_HPP
#include "ci/ciConstantPoolCache.hpp"
#include "ci/ciFlags.hpp"
#include "ci/ciKlass.hpp"
#include "ci/ciSymbol.hpp"
class ciInstanceKlass : public ciKlass {
  CI_PACKAGE_ACCESS
  friend class ciBytecodeStream;
  friend class ciEnv;
  friend class ciExceptionHandler;
  friend class ciMethod;
  friend class ciField;
private:
  jobject                _loader;
  jobject                _protection_domain;
  InstanceKlass::ClassState _init_state;           // state of class
  bool                   _is_shared;
  bool                   _has_finalizer;
  bool                   _has_subklass;
  bool                   _has_nonstatic_fields;
  bool                   _has_default_methods;
  bool                   _is_anonymous;
  ciFlags                _flags;
  jint                   _nonstatic_field_size;
  jint                   _nonstatic_oop_map_size;
  ciInstanceKlass*       _super;
  ciInstance*            _java_mirror;
  ciConstantPoolCache*   _field_cache;  // cached map index->field
  GrowableArray<ciField*>* _nonstatic_fields;
  ciInstanceKlass*       _implementor;
  GrowableArray<ciField*>* _non_static_fields;
protected:
  ciInstanceKlass(KlassHandle h_k);
  ciInstanceKlass(ciSymbol* name, jobject loader, jobject protection_domain);
  InstanceKlass* get_instanceKlass() const {
    return (InstanceKlass*)get_Klass();
  }
  oop loader();
  jobject loader_handle();
  oop protection_domain();
  jobject protection_domain_handle();
  const char* type_string() { return "ciInstanceKlass"; }
  bool is_in_package_impl(const char* packagename, int len);
  void print_impl(outputStream* st);
  ciConstantPoolCache* field_cache();
  bool is_shared() { return _is_shared; }
  void compute_shared_init_state();
  bool compute_shared_has_subklass();
  int  compute_nonstatic_fields();
  GrowableArray<ciField*>* compute_nonstatic_fields_impl(GrowableArray<ciField*>* super_fields);
  void update_if_shared(InstanceKlass::ClassState expected) {
    if (_is_shared && _init_state != expected) {
      if (is_loaded()) compute_shared_init_state();
    }
  }
public:
  bool                   is_initialized() {
    update_if_shared(InstanceKlass::fully_initialized);
    return _init_state == InstanceKlass::fully_initialized;
  }
  bool                   is_being_initialized() {
    update_if_shared(InstanceKlass::being_initialized);
    return _init_state == InstanceKlass::being_initialized;
  }
  bool                   is_linked() {
    update_if_shared(InstanceKlass::linked);
    return _init_state >= InstanceKlass::linked;
  }
  ciFlags                flags()          {
    assert(is_loaded(), "must be loaded");
    return _flags;
  }
  bool                   has_finalizer()  {
    assert(is_loaded(), "must be loaded");
    return _has_finalizer; }
  bool                   has_subklass()   {
    assert(is_loaded(), "must be loaded");
    if (_is_shared && !_has_subklass) {
      if (flags().is_final()) {
        return false;
      } else {
        return compute_shared_has_subklass();
      }
    }
    return _has_subklass;
  }
  jint                   size_helper()  {
    return (Klass::layout_helper_size_in_bytes(layout_helper())
            >> LogHeapWordSize);
  }
  jint                   nonstatic_field_size()  {
    assert(is_loaded(), "must be loaded");
    return _nonstatic_field_size; }
  jint                   has_nonstatic_fields()  {
    assert(is_loaded(), "must be loaded");
    return _has_nonstatic_fields; }
  jint                   nonstatic_oop_map_size()  {
    assert(is_loaded(), "must be loaded");
    return _nonstatic_oop_map_size; }
  ciInstanceKlass*       super();
  jint                   nof_implementors() {
    ciInstanceKlass* impl;
    assert(is_loaded(), "must be loaded");
    impl = implementor();
    if (impl == NULL) {
      return 0;
    } else if (impl != this) {
      return 1;
    } else {
      return 2;
    }
  }
  bool has_default_methods()  {
    assert(is_loaded(), "must be loaded");
    return _has_default_methods;
  }
  bool is_anonymous() {
    return _is_anonymous;
  }
  ciInstanceKlass* get_canonical_holder(int offset);
  ciField* get_field_by_offset(int field_offset, bool is_static);
  ciField* get_field_by_name(ciSymbol* name, ciSymbol* signature, bool is_static);
  GrowableArray<ciField*>* non_static_fields();
  int nof_nonstatic_fields() {
    if (_nonstatic_fields == NULL)
      return compute_nonstatic_fields();
    else
      return _nonstatic_fields->length();
  }
  ciField* nonstatic_field_at(int i) {
    assert(_nonstatic_fields != NULL, "");
    return _nonstatic_fields->at(i);
  }
  ciInstanceKlass* unique_concrete_subklass();
  bool has_finalizable_subclass();
  bool contains_field_offset(int offset) {
    return instanceOopDesc::contains_field_offset(offset, nonstatic_field_size());
  }
  ciInstance*            java_mirror();
  bool is_public      () { return flags().is_public(); }
  bool is_final       () { return flags().is_final(); }
  bool is_super       () { return flags().is_super(); }
  bool is_interface   () { return flags().is_interface(); }
  bool is_abstract    () { return flags().is_abstract(); }
  ciMethod* find_method(ciSymbol* name, ciSymbol* signature);
  bool is_leaf_type();
  ciInstanceKlass* implementor();
  bool uses_default_loader() const;
  bool is_java_lang_Object() const;
  BasicType box_klass_type() const;
  bool is_box_klass() const;
  bool is_boxed_value_offset(int offset) const;
  bool is_in_package(const char* packagename) {
    return is_in_package(packagename, (int) strlen(packagename));
  }
  bool is_in_package(const char* packagename, int len);
  bool is_instance_klass() const { return true; }
  bool is_java_klass() const     { return true; }
  virtual ciKlass* exact_klass() {
    if (is_loaded() && is_final() && !is_interface()) {
      return this;
    }
    return NULL;
  }
  ciInstanceKlass* host_klass();
  virtual void dump_replay_data(outputStream* out);
};
#endif // SHARE_VM_CI_CIINSTANCEKLASS_HPP
C:\hotspot-69087d08d473\src\share\vm/ci/ciKlass.cpp
#include "precompiled.hpp"
#include "ci/ciKlass.hpp"
#include "ci/ciSymbol.hpp"
#include "ci/ciUtilities.hpp"
#include "oops/oop.inline.hpp"
ciKlass::ciKlass(KlassHandle h_k) : ciType(h_k) {
  assert(get_Klass()->is_klass(), "wrong type");
  Klass* k = get_Klass();
  _layout_helper = k->layout_helper();
  Symbol* klass_name = k->name();
  assert(klass_name != NULL, "wrong ciKlass constructor");
  _name = CURRENT_ENV->get_symbol(klass_name);
}
ciKlass::ciKlass(KlassHandle h_k, ciSymbol* name) : ciType(h_k) {
  assert(get_Klass()->is_klass(), "wrong type");
  _name = name;
  _layout_helper = Klass::_lh_neutral_value;
}
ciKlass::ciKlass(ciSymbol* name, BasicType bt) : ciType(bt) {
  _name = name;
  _layout_helper = Klass::_lh_neutral_value;
}
bool ciKlass::is_subtype_of(ciKlass* that) {
  assert(this->is_loaded(), err_msg("must be loaded: %s", this->name()->as_quoted_ascii()));
  assert(that->is_loaded(), err_msg("must be loaded: %s", that->name()->as_quoted_ascii()));
  if (this == that) {
    return true;
  }
  VM_ENTRY_MARK;
  Klass* this_klass = get_Klass();
  Klass* that_klass = that->get_Klass();
  bool result = this_klass->is_subtype_of(that_klass);
  return result;
}
bool ciKlass::is_subclass_of(ciKlass* that) {
  assert(this->is_loaded(), err_msg("must be loaded: %s", this->name()->as_quoted_ascii()));
  assert(that->is_loaded(), err_msg("must be loaded: %s", that->name()->as_quoted_ascii()));
  VM_ENTRY_MARK;
  Klass* this_klass = get_Klass();
  Klass* that_klass = that->get_Klass();
  bool result = this_klass->is_subclass_of(that_klass);
  return result;
}
juint ciKlass::super_depth() {
  assert(is_loaded(), "must be loaded");
  VM_ENTRY_MARK;
  Klass* this_klass = get_Klass();
  return this_klass->super_depth();
}
juint ciKlass::super_check_offset() {
  assert(is_loaded(), "must be loaded");
  VM_ENTRY_MARK;
  Klass* this_klass = get_Klass();
  return this_klass->super_check_offset();
}
ciKlass* ciKlass::super_of_depth(juint i) {
  assert(is_loaded(), "must be loaded");
  VM_ENTRY_MARK;
  Klass* this_klass = get_Klass();
  Klass* super = this_klass->primary_super_of_depth(i);
  return (super != NULL) ? CURRENT_THREAD_ENV->get_klass(super) : NULL;
}
bool ciKlass::can_be_primary_super() {
  assert(is_loaded(), "must be loaded");
  VM_ENTRY_MARK;
  Klass* this_klass = get_Klass();
  return this_klass->can_be_primary_super();
}
ciKlass*
ciKlass::least_common_ancestor(ciKlass* that) {
  assert(is_loaded() && that->is_loaded(), "must be loaded");
  if (this == that) {
    return this;
  }
  VM_ENTRY_MARK;
  Klass* this_klass = get_Klass();
  Klass* that_klass = that->get_Klass();
  Klass* lca        = this_klass->LCA(that_klass);
  if (lca == that_klass) {
    return that;
  }
  if (this_klass == lca) {
    return this;
  }
  ciKlass* result =
    CURRENT_THREAD_ENV->get_klass(lca);
  return result;
}
ciKlass* ciKlass::find_klass(ciSymbol* klass_name) {
  assert(is_loaded(), "cannot find_klass through an unloaded klass");
  return CURRENT_ENV->get_klass_by_name(this,
                                        klass_name, false);
}
ciInstance* ciKlass::java_mirror() {
  GUARDED_VM_ENTRY(
    if (!is_loaded())
      return ciEnv::current()->get_unloaded_klass_mirror(this);
    oop java_mirror = get_Klass()->java_mirror();
    return CURRENT_ENV->get_instance(java_mirror);
  )
}
jint ciKlass::modifier_flags() {
  assert(is_loaded(), "not loaded");
  GUARDED_VM_ENTRY(
    return get_Klass()->modifier_flags();
  )
}
jint ciKlass::access_flags() {
  assert(is_loaded(), "not loaded");
  GUARDED_VM_ENTRY(
    return get_Klass()->access_flags().as_int();
  )
}
void ciKlass::print_impl(outputStream* st) {
  st->print(" name=");
  print_name_on(st);
}
void ciKlass::print_name_on(outputStream* st) {
  name()->print_symbol_on(st);
}
C:\hotspot-69087d08d473\src\share\vm/ci/ciKlass.hpp
#ifndef SHARE_VM_CI_CIKLASS_HPP
#define SHARE_VM_CI_CIKLASS_HPP
#include "ci/ciType.hpp"
class ciKlass : public ciType {
  CI_PACKAGE_ACCESS
  friend class ciEnv;
  friend class ciField;
  friend class ciMethod;
  friend class ciMethodData;
  friend class ciObjArrayKlass;
  friend class ciReceiverTypeData;
private:
  ciSymbol* _name;
  jint _layout_helper;
protected:
  ciKlass(KlassHandle k_h, ciSymbol* name);
  ciKlass(ciSymbol* name, BasicType bt);
  Klass* get_Klass() const {
    Klass* k = (Klass*)_metadata;
    assert(k != NULL, "illegal use of unloaded klass");
    return k;
  }
  virtual oop loader()             { return NULL; }
  virtual jobject loader_handle()  { return NULL; }
  virtual oop protection_domain()             { return NULL; }
  virtual jobject protection_domain_handle()  { return NULL; }
  const char* type_string() { return "ciKlass"; }
  void print_impl(outputStream* st);
public:
  ciKlass(KlassHandle k_h);
  ciSymbol* name() const { return _name; }
  jint layout_helper() { return _layout_helper; }
  bool is_subtype_of(ciKlass* klass);
  bool is_subclass_of(ciKlass* klass);
  juint super_depth();
  juint super_check_offset();
  ciKlass* super_of_depth(juint i);
  bool can_be_primary_super();
  static juint primary_super_limit() { return Klass::primary_super_limit(); }
  virtual bool is_java_lang_Object() const  { return false; }
  ciKlass* least_common_ancestor(ciKlass* k);
  virtual bool is_interface() {
    return false;
  }
  virtual bool is_abstract() {
    return false;
  }
  virtual bool is_leaf_type() {
    return false;
  }
  ciKlass* find_klass(ciSymbol* klass_name);
  ciInstance*            java_mirror();
  jint                   modifier_flags();
  jint                   access_flags();
  bool is_klass() const { return true; }
  virtual ciKlass* exact_klass() = 0;
  void print_name_on(outputStream* st);
};
#endif // SHARE_VM_CI_CIKLASS_HPP
C:\hotspot-69087d08d473\src\share\vm/ci/ciMemberName.cpp
#include "precompiled.hpp"
#include "ci/ciClassList.hpp"
#include "ci/ciMemberName.hpp"
#include "ci/ciUtilities.hpp"
#include "classfile/javaClasses.hpp"
ciMethod* ciMemberName::get_vmtarget() const {
  VM_ENTRY_MARK;
  Metadata* vmtarget = java_lang_invoke_MemberName::vmtarget(get_oop());
  if (vmtarget->is_method())
    return CURRENT_ENV->get_method((Method*) vmtarget);
  assert(false, "");
  return NULL;
}
C:\hotspot-69087d08d473\src\share\vm/ci/ciMemberName.hpp
#ifndef SHARE_VM_CI_CIMEMBERNAME_HPP
#define SHARE_VM_CI_CIMEMBERNAME_HPP
#include "ci/ciCallProfile.hpp"
#include "ci/ciInstance.hpp"
class ciMemberName : public ciInstance {
public:
  ciMemberName(instanceHandle h_i) : ciInstance(h_i) {}
  bool is_member_name() const { return true; }
  ciMethod* get_vmtarget() const;
};
#endif // SHARE_VM_CI_CIMEMBERNAME_HPP
C:\hotspot-69087d08d473\src\share\vm/ci/ciMetadata.cpp
#include "precompiled.hpp"
#include "ci/ciObject.hpp"
#include "ci/ciUtilities.hpp"
#include "gc_interface/collectedHeap.inline.hpp"
#include "oops/oop.inline2.hpp"
void ciMetadata::print(outputStream* st) {
  st->print("<%s", type_string());
  GUARDED_VM_ENTRY(print_impl(st);)
  st->print(" ident=%d address=" INTPTR_FORMAT ">", ident(), p2i((address)this));
}
void ciMetadata::print_metadata(outputStream* st) {
  if (!is_loaded()) {
    st->print_cr("UNLOADED");
  } else {
    GUARDED_VM_ENTRY(_metadata->print_on(st);)
  }
}
C:\hotspot-69087d08d473\src\share\vm/ci/ciMetadata.hpp
#ifndef SHARE_VM_CI_CIMETADATA_HPP
#define SHARE_VM_CI_CIMETADATA_HPP
#include "ci/ciBaseObject.hpp"
#include "ci/ciClassList.hpp"
#include "memory/allocation.hpp"
#include "runtime/handles.hpp"
#include "runtime/jniHandles.hpp"
class ciMetadata: public ciBaseObject {
  CI_PACKAGE_ACCESS
  friend class ciEnv;
 protected:
  Metadata* _metadata;
  ciMetadata(): _metadata(NULL) {}
  ciMetadata(Metadata* o): _metadata(o) {}
  virtual bool is_classless() const         { return false; }
 public:
  bool is_loaded() const { return _metadata != NULL || is_classless(); }
  virtual bool is_metadata() const          { return true; }
  virtual bool is_type() const              { return false; }
  virtual bool is_cpcache() const           { return false; }
  virtual bool is_return_address() const    { return false; }
  virtual bool is_method() const            { return false; }
  virtual bool is_method_data() const       { return false; }
  virtual bool is_klass() const             { return false; }
  virtual bool is_instance_klass() const    { return false; }
  virtual bool is_array_klass() const       { return false; }
  virtual bool is_obj_array_klass() const   { return false; }
  virtual bool is_type_array_klass() const  { return false; }
  virtual void dump_replay_data(outputStream* st) { /* do nothing */ }
  ciMethod*                as_method() {
    assert(is_method(), "bad cast");
    return (ciMethod*)this;
  }
  ciMethodData*            as_method_data() {
    assert(is_method_data(), "bad cast");
    return (ciMethodData*)this;
  }
  ciSymbol*                as_symbol() {
    assert(is_symbol(), "bad cast");
    return (ciSymbol*)this;
  }
  ciType*                  as_type() {
    assert(is_type(), "bad cast");
    return (ciType*)this;
  }
  ciReturnAddress*         as_return_address() {
    assert(is_return_address(), "bad cast");
    return (ciReturnAddress*)this;
  }
  ciKlass*                 as_klass() {
    assert(is_klass(), "bad cast");
    return (ciKlass*)this;
  }
  ciInstanceKlass*         as_instance_klass() {
    assert(is_instance_klass(), "bad cast");
    return (ciInstanceKlass*)this;
  }
  ciArrayKlass*            as_array_klass() {
    assert(is_array_klass(), "bad cast");
    return (ciArrayKlass*)this;
  }
  ciObjArrayKlass*         as_obj_array_klass() {
    assert(is_obj_array_klass(), "bad cast");
    return (ciObjArrayKlass*)this;
  }
  ciTypeArrayKlass*        as_type_array_klass() {
    assert(is_type_array_klass(), "bad cast");
    return (ciTypeArrayKlass*)this;
  }
  Metadata* constant_encoding() { return _metadata; }
  bool equals(ciMetadata* obj) const { return (this == obj); }
  int hash() { return ident() * 31; } // ???
  void print(outputStream* st);
  virtual void print_impl(outputStream* st) {}
  virtual const char* type_string() { return "ciMetadata"; }
  void print()  { print(tty); }
  void print_metadata(outputStream* st = tty);
};
#endif // SHARE_VM_CI_CIMETADATA_HPP
C:\hotspot-69087d08d473\src\share\vm/ci/ciMethod.cpp
#include "precompiled.hpp"
#include "ci/ciCallProfile.hpp"
#include "ci/ciExceptionHandler.hpp"
#include "ci/ciInstanceKlass.hpp"
#include "ci/ciMethod.hpp"
#include "ci/ciMethodBlocks.hpp"
#include "ci/ciMethodData.hpp"
#include "ci/ciStreams.hpp"
#include "ci/ciSymbol.hpp"
#include "ci/ciReplay.hpp"
#include "ci/ciUtilities.hpp"
#include "classfile/systemDictionary.hpp"
#include "compiler/abstractCompiler.hpp"
#include "compiler/compilerOracle.hpp"
#include "compiler/methodLiveness.hpp"
#include "interpreter/interpreter.hpp"
#include "interpreter/linkResolver.hpp"
#include "interpreter/oopMapCache.hpp"
#include "memory/allocation.inline.hpp"
#include "memory/resourceArea.hpp"
#include "oops/generateOopMap.hpp"
#include "oops/oop.inline.hpp"
#include "prims/nativeLookup.hpp"
#include "runtime/deoptimization.hpp"
#include "utilities/bitMap.inline.hpp"
#include "utilities/xmlstream.hpp"
#ifdef COMPILER2
#include "ci/bcEscapeAnalyzer.hpp"
#include "ci/ciTypeFlow.hpp"
#include "oops/method.hpp"
#endif
#ifdef SHARK
#include "ci/ciTypeFlow.hpp"
#include "oops/method.hpp"
#endif
ciMethod::ciMethod(methodHandle h_m, ciInstanceKlass* holder) :
  ciMetadata(h_m()),
  _holder(holder)
{
  assert(h_m() != NULL, "no null method");
  _flags = ciFlags(h_m()->access_flags());
  _max_stack          = h_m()->max_stack();
  _max_locals         = h_m()->max_locals();
  _code_size          = h_m()->code_size();
  _intrinsic_id       = h_m()->intrinsic_id();
  _handler_count      = h_m()->exception_table_length();
  _size_of_parameters = h_m()->size_of_parameters();
  _uses_monitors      = h_m()->access_flags().has_monitor_bytecodes();
  _balanced_monitors  = !_uses_monitors || h_m()->access_flags().is_monitor_matching();
  _is_c1_compilable   = !h_m()->is_not_c1_compilable();
  _is_c2_compilable   = !h_m()->is_not_c2_compilable();
  _code               = NULL;
  _exception_handlers = NULL;
  _liveness           = NULL;
  _method_blocks = NULL;
#if defined(COMPILER2) || defined(SHARK)
  _flow               = NULL;
  _bcea               = NULL;
#endif // COMPILER2 || SHARK
  ciEnv *env = CURRENT_ENV;
  if (env->jvmti_can_hotswap_or_post_breakpoint() && can_be_compiled()) {
    MutexLocker locker(Compile_lock);
    if (Dependencies::check_evol_method(h_m()) != NULL) {
      _is_c1_compilable = false;
      _is_c2_compilable = false;
    }
  } else {
    CHECK_UNHANDLED_OOPS_ONLY(Thread::current()->clear_unhandled_oops());
  }
  if (h_m()->method_holder()->is_linked()) {
    _can_be_statically_bound = h_m()->can_be_statically_bound();
  } else {
    _can_be_statically_bound = false;
  }
  if (!_can_be_statically_bound && h_m()->is_private())
    _can_be_statically_bound = true;
  if (_can_be_statically_bound && h_m()->is_abstract())
    _can_be_statically_bound = false;
  _name = env->get_symbol(h_m()->name());
  ciSymbol* sig_symbol = env->get_symbol(h_m()->signature());
  constantPoolHandle cpool = h_m()->constants();
  _signature = new (env->arena()) ciSignature(_holder, cpool, sig_symbol);
  _method_data = NULL;
  if (ProfileInterpreter || TieredCompilation) {
    int invcnt = h_m()->interpreter_invocation_count();
    _interpreter_invocation_count = invcnt < 0 ? max_jint : invcnt ;
    _interpreter_throwout_count   = h_m()->interpreter_throwout_count();
  } else {
    _interpreter_invocation_count = 0;
    _interpreter_throwout_count = 0;
  }
  if (_interpreter_invocation_count == 0)
    _interpreter_invocation_count = 1;
  _instructions_size = -1;
#ifdef ASSERT
  if (ReplayCompiles) {
    ciReplay::initialize(this);
  }
#endif
}
ciMethod::ciMethod(ciInstanceKlass* holder,
                   ciSymbol*        name,
                   ciSymbol*        signature,
                   ciInstanceKlass* accessor) :
  ciMetadata((Metadata*)NULL),
  _name(                   name),
  _holder(                 holder),
  _intrinsic_id(           vmIntrinsics::_none),
  _liveness(               NULL),
  _can_be_statically_bound(false),
  _method_blocks(          NULL),
  _method_data(            NULL)
#if defined(COMPILER2) || defined(SHARK)
  ,
  _flow(                   NULL),
  _bcea(                   NULL),
  _instructions_size(-1)
#endif // COMPILER2 || SHARK
{
  _signature = new (CURRENT_ENV->arena()) ciSignature(accessor, constantPoolHandle(), signature);
}
void ciMethod::load_code() {
  VM_ENTRY_MARK;
  assert(is_loaded(), "only loaded methods have code");
  Method* me = get_Method();
  Arena* arena = CURRENT_THREAD_ENV->arena();
  _code = (address)arena->Amalloc(code_size());
  memcpy(_code, me->code_base(), code_size());
  if (me->number_of_breakpoints() > 0) {
    BreakpointInfo* bp = me->method_holder()->breakpoints();
    for (; bp != NULL; bp = bp->next()) {
      if (bp->match(me)) {
        code_at_put(bp->bci(), bp->orig_bytecode());
      }
    }
  }
  ExceptionTable exc_table(me);
  _exception_handlers =
    (ciExceptionHandler**)arena->Amalloc(sizeof(ciExceptionHandler*)
  if (_handler_count > 0) {
    for (int i=0; i<_handler_count; i++) {
      _exception_handlers[i] = new (arena) ciExceptionHandler(
                                holder(),
    }
  }
  _exception_handlers[_handler_count] =
    new (arena) ciExceptionHandler(holder(), 0, code_size(), -1, 0);
  if (CIPrintMethodCodes) {
    print_codes();
  }
}
bool    ciMethod::has_linenumber_table() const {
  check_is_loaded();
  VM_ENTRY_MARK;
  return get_Method()->has_linenumber_table();
}
u_char* ciMethod::compressed_linenumber_table() const {
  check_is_loaded();
  VM_ENTRY_MARK;
  return get_Method()->compressed_linenumber_table();
}
int ciMethod::line_number_from_bci(int bci) const {
  check_is_loaded();
  VM_ENTRY_MARK;
  return get_Method()->line_number_from_bci(bci);
}
int ciMethod::vtable_index() {
  check_is_loaded();
  assert(holder()->is_linked(), "must be linked");
  VM_ENTRY_MARK;
  return get_Method()->vtable_index();
}
#ifdef SHARK
int ciMethod::itable_index() {
  check_is_loaded();
  assert(holder()->is_linked(), "must be linked");
  VM_ENTRY_MARK;
  Method* m = get_Method();
  if (!m->has_itable_index())
    return Method::nonvirtual_vtable_index;
  return m->itable_index();
}
#endif // SHARK
address ciMethod::native_entry() {
  check_is_loaded();
  assert(flags().is_native(), "must be native method");
  VM_ENTRY_MARK;
  Method* method = get_Method();
  address entry = method->native_function();
  assert(entry != NULL, "must be valid entry point");
  return entry;
}
address ciMethod::interpreter_entry() {
  check_is_loaded();
  VM_ENTRY_MARK;
  methodHandle mh(THREAD, get_Method());
  return Interpreter::entry_for_method(mh);
}
bool ciMethod::has_balanced_monitors() {
  check_is_loaded();
  if (_balanced_monitors) return true;
  VM_ENTRY_MARK;
  methodHandle method(THREAD, get_Method());
  assert(method->has_monitor_bytecodes(), "should have checked this");
  if (method->guaranteed_monitor_matching()) {
    _balanced_monitors = true;
    return true;
  }
  {
    EXCEPTION_MARK;
    ResourceMark rm(THREAD);
    GeneratePairingInfo gpi(method);
    gpi.compute_map(CATCH);
    if (!gpi.monitor_safe()) {
      return false;
    }
    method->set_guaranteed_monitor_matching();
    _balanced_monitors = true;
  }
  return true;
}
ciTypeFlow* ciMethod::get_flow_analysis() {
#if defined(COMPILER2) || defined(SHARK)
  if (_flow == NULL) {
    ciEnv* env = CURRENT_ENV;
    _flow = new (env->arena()) ciTypeFlow(env, this);
    _flow->do_flow();
  }
  return _flow;
#else // COMPILER2 || SHARK
  ShouldNotReachHere();
  return NULL;
#endif // COMPILER2 || SHARK
}
ciTypeFlow* ciMethod::get_osr_flow_analysis(int osr_bci) {
#if defined(COMPILER2) || defined(SHARK)
  assert(osr_bci >= 0, "must supply valid OSR entry point");
  ciEnv* env = CURRENT_ENV;
  ciTypeFlow* flow = new (env->arena()) ciTypeFlow(env, this, osr_bci);
  flow->do_flow();
  return flow;
#else // COMPILER2 || SHARK
  ShouldNotReachHere();
  return NULL;
#endif // COMPILER2 || SHARK
}
MethodLivenessResult ciMethod::raw_liveness_at_bci(int bci) {
  check_is_loaded();
  if (_liveness == NULL) {
    Arena* arena = CURRENT_ENV->arena();
    _liveness = new (arena) MethodLiveness(arena, this);
    _liveness->compute_liveness();
  }
  return _liveness->get_liveness_at(bci);
}
MethodLivenessResult ciMethod::liveness_at_bci(int bci) {
  MethodLivenessResult result = raw_liveness_at_bci(bci);
  if (CURRENT_ENV->should_retain_local_variables() || DeoptimizeALot || CompileTheWorld) {
    result.at_put_range(0, result.size(), true);
  }
  return result;
}
BitMap ciMethod::live_local_oops_at_bci(int bci) {
  VM_ENTRY_MARK;
  InterpreterOopMap mask;
  OopMapCache::compute_one_oop_map(get_Method(), bci, &mask);
  int mask_size = max_locals();
  BitMap result(mask_size);
  result.clear();
  int i;
  for (i = 0; i < mask_size ; i++ ) {
    if (mask.is_oop(i)) result.set_bit(i);
  }
  return result;
}
#ifdef COMPILER1
const BitMap ciMethod::bci_block_start() {
  check_is_loaded();
  if (_liveness == NULL) {
    Arena* arena = CURRENT_ENV->arena();
    _liveness = new (arena) MethodLiveness(arena, this);
    _liveness->compute_liveness();
  }
  return _liveness->get_bci_block_start();
}
#endif // COMPILER1
ciCallProfile ciMethod::call_profile_at_bci(int bci) {
  ResourceMark rm;
  ciCallProfile result;
  if (method_data() != NULL && method_data()->is_mature()) {
    ciProfileData* data = method_data()->bci_to_data(bci);
    if (data != NULL && data->is_CounterData()) {
      int count = data->as_CounterData()->count();
      if (!data->is_ReceiverTypeData()) {
        result._receiver_count[0] = 0;  // that's a definite zero
      } else { // ReceiverTypeData is a subclass of CounterData
        ciReceiverTypeData* call = (ciReceiverTypeData*)data->as_ReceiverTypeData();
        int receivers_count_total = 0;
        int morphism = 0;
        for (uint i = 0; i < call->row_limit(); i++) {
          ciKlass* receiver = call->receiver(i);
          if (receiver == NULL)  continue;
          morphism++;
        }
        int epsilon = 0;
        if (TieredCompilation && ProfileInterpreter) {
          if (morphism == 1 && count > 0) {
            epsilon = count;
            count = 0;
          }
        }
        for (uint i = 0; i < call->row_limit(); i++) {
          ciKlass* receiver = call->receiver(i);
          if (receiver == NULL)  continue;
          int rcount = call->receiver_count(i) + epsilon;
          if (rcount == 0) rcount = 1; // Should be valid value
          receivers_count_total += rcount;
          result.add_receiver(receiver, rcount);
        }
        if (morphism > 0 && morphism == result._limit) {
           if ((morphism <  ciCallProfile::MorphismLimit) ||
               (morphism == ciCallProfile::MorphismLimit && count == 0)) {
#ifdef ASSERT
             if (count > 0) {
               this->print_short_name(tty);
               tty->print_cr(" @ bci:%d", bci);
               this->print_codes();
               assert(false, "this call site should not be polymorphic");
             }
#endif
             result._morphism = morphism;
           }
        }
        if (count >= 0) {
          count += receivers_count_total;
        }
      }
      result._count = count;
    }
  }
  return result;
}
void ciCallProfile::add_receiver(ciKlass* receiver, int receiver_count) {
  int i = _limit;
  for (; i > 0 && receiver_count > _receiver_count[i-1]; i--) {
    _receiver[i] = _receiver[i-1];
    _receiver_count[i] = _receiver_count[i-1];
  }
  _receiver[i] = receiver;
  _receiver_count[i] = receiver_count;
  if (_limit < MorphismLimit) _limit++;
}
void ciMethod::assert_virtual_call_type_ok(int bci) {
  assert(java_code_at_bci(bci) == Bytecodes::_invokevirtual ||
         java_code_at_bci(bci) == Bytecodes::_invokeinterface, err_msg("unexpected bytecode %s", Bytecodes::name(java_code_at_bci(bci))));
}
void ciMethod::assert_call_type_ok(int bci) {
  assert(java_code_at_bci(bci) == Bytecodes::_invokestatic ||
         java_code_at_bci(bci) == Bytecodes::_invokespecial ||
         java_code_at_bci(bci) == Bytecodes::_invokedynamic, err_msg("unexpected bytecode %s", Bytecodes::name(java_code_at_bci(bci))));
}
ciKlass* ciMethod::argument_profiled_type(int bci, int i) {
  if (MethodData::profile_parameters() && method_data() != NULL && method_data()->is_mature()) {
    ciProfileData* data = method_data()->bci_to_data(bci);
    if (data != NULL) {
      if (data->is_VirtualCallTypeData()) {
        assert_virtual_call_type_ok(bci);
        ciVirtualCallTypeData* call = (ciVirtualCallTypeData*)data->as_VirtualCallTypeData();
        if (i >= call->number_of_arguments()) {
          return NULL;
        }
        ciKlass* type = call->valid_argument_type(i);
        if (type != NULL && !call->argument_maybe_null(i)) {
          return type;
        }
      } else if (data->is_CallTypeData()) {
        assert_call_type_ok(bci);
        ciCallTypeData* call = (ciCallTypeData*)data->as_CallTypeData();
        if (i >= call->number_of_arguments()) {
          return NULL;
        }
        ciKlass* type = call->valid_argument_type(i);
        if (type != NULL && !call->argument_maybe_null(i)) {
          return type;
        }
      }
    }
  }
  return NULL;
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值