ssssssss59


void Parse::jump_switch_ranges(Node* key_val, SwitchRange *lo, SwitchRange *hi, int switch_depth) {
  Block* switch_block = block();
  if (switch_depth == 0) {
    assert(lo->lo() == min_jint, "initial range must exhaust Type::INT");
    assert(hi->hi() == max_jint, "initial range must exhaust Type::INT");
#ifdef ASSERT
    int successors_counted = 0;  // block occurrences in [hi..lo]
    int unique_successors = switch_block->num_successors();
    for (int i = 0; i < unique_successors; i++) {
      Block* target = switch_block->successor_at(i);
      int successors_found = 0;
      for (SwitchRange* p = lo; p <= hi; p++) {
        if (p->dest() == target->start())  successors_found++;
      }
      assert(successors_found > 0, "successor must be known");
      successors_counted += successors_found;
    }
    assert(successors_counted == (hi-lo)+1, "no unexpected successors");
#endif
    jint min_val = min_jint;
    jint max_val = max_jint;
    const TypeInt* ti = key_val->bottom_type()->isa_int();
    if (ti != NULL) {
      min_val = ti->_lo;
      max_val = ti->_hi;
      assert(min_val <= max_val, "invalid int type");
    }
    while (lo->hi() < min_val)  lo++;
    if (lo->lo() < min_val)  lo->setRange(min_val, lo->hi(), lo->dest(), lo->table_index());
    while (hi->lo() > max_val)  hi--;
    if (hi->hi() > max_val)  hi->setRange(hi->lo(), max_val, hi->dest(), hi->table_index());
  }
#ifndef PRODUCT
  if (switch_depth == 0) {
    _max_switch_depth = 0;
    _est_switch_depth = log2_intptr((hi-lo+1)-1)+1;
  }
#endif
  assert(lo <= hi, "must be a non-empty set of ranges");
  if (lo == hi) {
    jump_if_always_fork(lo->dest(), lo->table_index());
  } else {
    assert(lo->hi() == (lo+1)->lo()-1, "contiguous ranges");
    assert(hi->lo() == (hi-1)->hi()+1, "contiguous ranges");
    if (create_jump_tables(key_val, lo, hi)) return;
    int nr = hi - lo + 1;
    SwitchRange* mid = lo + nr/2;
    if (nr > 3 && !mid->is_singleton() && (mid-1)->is_singleton())  mid--;
    assert(lo < mid && mid <= hi, "good pivot choice");
    assert(nr != 2 || mid == hi,   "should pick higher of 2");
    assert(nr != 3 || mid == hi-1, "should pick middle of 3");
    Node *test_val = _gvn.intcon(mid->lo());
    if (mid->is_singleton()) {
      IfNode *iff_ne = jump_if_fork_int(key_val, test_val, BoolTest::ne);
      jump_if_false_fork(iff_ne, mid->dest(), mid->table_index());
      bool eq_test_only = (hi == lo+2 && hi->dest() == lo->dest());
      if (eq_test_only) {
        assert(mid == hi-1, "");
      }
      if (mid < hi && !eq_test_only) {
        IfNode *iff_le  = jump_if_fork_int(key_val, test_val, BoolTest::le);
        Node   *iftrue  = _gvn.transform( new (C) IfTrueNode(iff_le) );
        Node   *iffalse = _gvn.transform( new (C) IfFalseNode(iff_le) );
        { PreserveJVMState pjvms(this);
          set_control(iffalse);
          jump_switch_ranges(key_val, mid+1, hi, switch_depth+1);
        }
        set_control(iftrue);
      }
    } else {
      IfNode *iff_ge = jump_if_fork_int(key_val, test_val, BoolTest::ge);
      if (mid == hi) {
        jump_if_true_fork(iff_ge, mid->dest(), mid->table_index());
      } else {
        Node *iftrue  = _gvn.transform( new (C) IfTrueNode(iff_ge) );
        Node *iffalse = _gvn.transform( new (C) IfFalseNode(iff_ge) );
        { PreserveJVMState pjvms(this);
          set_control(iftrue);
          jump_switch_ranges(key_val, mid, hi, switch_depth+1);
        }
        set_control(iffalse);
      }
    }
    jump_switch_ranges(key_val, lo, mid-1, switch_depth+1);
  }
  if (switch_depth == 0) {
    int unique_successors = switch_block->num_successors();
    for (int i = 0; i < unique_successors; i++) {
      Block* target = switch_block->successor_at(i);
      target->next_path_num();
    }
  }
#ifndef PRODUCT
  _max_switch_depth = MAX2(switch_depth, _max_switch_depth);
  if (TraceOptoParse && Verbose && WizardMode && switch_depth == 0) {
    SwitchRange* r;
    int nsing = 0;
    for( r = lo; r <= hi; r++ ) {
      if( r->is_singleton() )  nsing++;
    }
    tty->print(">>> ");
    _method->print_short_name();
    tty->print_cr(" switch decision tree");
    tty->print_cr("    %d ranges (%d singletons), max_depth=%d, est_depth=%d",
                  (int) (hi-lo+1), nsing, _max_switch_depth, _est_switch_depth);
    if (_max_switch_depth > _est_switch_depth) {
      tty->print_cr("******** BAD SWITCH DEPTH ********");
    }
    tty->print("   ");
    for( r = lo; r <= hi; r++ ) {
      r->print();
    }
    tty->cr();
  }
#endif
}
void Parse::modf() {
  Node *f2 = pop();
  Node *f1 = pop();
  Node* c = make_runtime_call(RC_LEAF, OptoRuntime::modf_Type(),
                              CAST_FROM_FN_PTR(address, SharedRuntime::frem),
                              "frem", NULL, //no memory effects
                              f1, f2);
  Node* res = _gvn.transform(new (C) ProjNode(c, TypeFunc::Parms + 0));
  push(res);
}
void Parse::modd() {
  Node *d2 = pop_pair();
  Node *d1 = pop_pair();
  Node* c = make_runtime_call(RC_LEAF, OptoRuntime::Math_DD_D_Type(),
                              CAST_FROM_FN_PTR(address, SharedRuntime::drem),
                              "drem", NULL, //no memory effects
                              d1, top(), d2, top());
  Node* res_d   = _gvn.transform(new (C) ProjNode(c, TypeFunc::Parms + 0));
#ifdef ASSERT
  Node* res_top = _gvn.transform(new (C) ProjNode(c, TypeFunc::Parms + 1));
  assert(res_top == top(), "second value must be top");
#endif
  push_pair(res_d);
}
void Parse::l2f() {
  Node* f2 = pop();
  Node* f1 = pop();
  Node* c = make_runtime_call(RC_LEAF, OptoRuntime::l2f_Type(),
                              CAST_FROM_FN_PTR(address, SharedRuntime::l2f),
                              "l2f", NULL, //no memory effects
                              f1, f2);
  Node* res = _gvn.transform(new (C) ProjNode(c, TypeFunc::Parms + 0));
  push(res);
}
void Parse::do_irem() {
  zero_check_int(peek());
  if (stopped())  return;
  Node* b = pop();
  Node* a = pop();
  const Type *t = _gvn.type(b);
  if (t != Type::TOP) {
    const TypeInt *ti = t->is_int();
    if (ti->is_con()) {
      int divisor = ti->get_con();
      if (divisor > 0 &&
          (divisor & ~(divisor-1)) == divisor) {
        Node *mask = _gvn.intcon((divisor - 1));
        Node *zero = _gvn.intcon(0);
        IfNode *ifff = jump_if_fork_int(a, zero, BoolTest::lt);
        Node *iff = _gvn.transform( new (C) IfFalseNode(ifff) );
        Node *ift = _gvn.transform( new (C) IfTrueNode (ifff) );
        Node *reg = jump_if_join(ift, iff);
        Node *phi = PhiNode::make(reg, NULL, TypeInt::INT);
        Node *neg = _gvn.transform( new (C) SubINode(zero, a) );
        Node *andn= _gvn.transform( new (C) AndINode(neg, mask) );
        Node *negn= _gvn.transform( new (C) SubINode(zero, andn) );
        phi->init_req(1, negn);
        Node *andx = _gvn.transform( new (C) AndINode(a, mask) );
        phi->init_req(2, andx);
        push( _gvn.transform(phi) );
        return;
      }
    }
  }
  push( _gvn.transform( new (C) ModINode(control(),a,b) ) );
}
void Parse::do_jsr() {
  assert(bc() == Bytecodes::_jsr || bc() == Bytecodes::_jsr_w, "wrong bytecode");
  int return_bci = iter().next_bci();
  int jsr_bci    = (bc() == Bytecodes::_jsr) ? iter().get_dest() : iter().get_far_dest();
  profile_taken_branch(jsr_bci);
  Block* target = successor_for_bci(jsr_bci);
  const Type* ret_addr = target->peek();
  assert(ret_addr->singleton(), "must be a constant (cloned jsr body)");
  push(_gvn.makecon(ret_addr));
  merge(jsr_bci);
}
void Parse::do_ret() {
  assert(block()->num_successors() == 1, "a ret can only go one place now");
  Block* target = block()->successor_at(0);
  assert(!target->is_ready(), "our arrival must be expected");
  profile_ret(target->flow()->start());
  int pnum = target->next_path_num();
  merge_common(target, pnum);
}
static bool has_injected_profile(BoolTest::mask btest, Node* test, int& taken, int& not_taken) {
  if (btest != BoolTest::eq && btest != BoolTest::ne) {
    return false;
  }
  if (test->is_Cmp() &&
      test->in(1)->Opcode() == Op_ProfileBoolean) {
    ProfileBooleanNode* profile = (ProfileBooleanNode*)test->in(1);
    int false_cnt = profile->false_count();
    int  true_cnt = profile->true_count();
    taken     = (btest == BoolTest::eq) ? false_cnt :  true_cnt;
    not_taken = (btest == BoolTest::eq) ?  true_cnt : false_cnt;
    profile->consume();
    return true;
  }
  return false;
}
float Parse::dynamic_branch_prediction(float &cnt, BoolTest::mask btest, Node* test) {
  ResourceMark rm;
  cnt  = COUNT_UNKNOWN;
  int     taken = 0;
  int not_taken = 0;
  bool use_mdo = !has_injected_profile(btest, test, taken, not_taken);
  if (use_mdo) {
    ciMethodData* methodData = method()->method_data();
    if (!methodData->is_mature())  return PROB_UNKNOWN;
    ciProfileData* data = methodData->bci_to_data(bci());
    if (data == NULL) {
      return PROB_UNKNOWN;
    }
    if (!data->is_JumpData())  return PROB_UNKNOWN;
    taken = data->as_JumpData()->taken();
    not_taken = 0;
    if (data->is_BranchData()) {
      not_taken = data->as_BranchData()->not_taken();
    }
    taken = method()->scale_count(taken);
    not_taken = method()->scale_count(not_taken);
  }
  if (taken < 0 || not_taken < 0 || taken + not_taken < 40) {
    if (C->log() != NULL) {
      C->log()->elem("branch target_bci='%d' taken='%d' not_taken='%d'", iter().get_dest(), taken, not_taken);
    }
    return PROB_UNKNOWN;
  }
  float sum = taken + not_taken;
  if( block()->count() > 0 )
    sum = block()->count();
  cnt = sum / FreqCountInvocations;
  float prob;
  if( !taken )
    prob = (0+PROB_MIN) / 2;
  else if( !not_taken )
    prob = (1+PROB_MAX) / 2;
  else {                         // Compute probability of true path
    prob = (float)taken / (float)(taken + not_taken);
    if (prob > PROB_MAX)  prob = PROB_MAX;
    if (prob < PROB_MIN)   prob = PROB_MIN;
  }
  assert((cnt > 0.0f) && (prob > 0.0f),
         "Bad frequency assignment in if");
  if (C->log() != NULL) {
    const char* prob_str = NULL;
    if (prob >= PROB_MAX)  prob_str = (prob == PROB_MAX) ? "max" : "always";
    if (prob <= PROB_MIN)  prob_str = (prob == PROB_MIN) ? "min" : "never";
    char prob_str_buf[30];
    if (prob_str == NULL) {
      sprintf(prob_str_buf, "%g", prob);
      prob_str = prob_str_buf;
    }
    C->log()->elem("branch target_bci='%d' taken='%d' not_taken='%d' cnt='%g' prob='%s'",
                   iter().get_dest(), taken, not_taken, cnt, prob_str);
  }
  return prob;
}
float Parse::branch_prediction(float& cnt,
                               BoolTest::mask btest,
                               int target_bci,
                               Node* test) {
  float prob = dynamic_branch_prediction(cnt, btest, test);
  if (prob != PROB_UNKNOWN)  return prob;
  prob = PROB_FAIR;                   // Set default value
  if (btest == BoolTest::eq)          // Exactly equal test?
    prob = PROB_STATIC_INFREQUENT;    // Assume its relatively infrequent
  else if (btest == BoolTest::ne)
    prob = PROB_STATIC_FREQUENT;      // Assume its relatively frequent
  if (target_bci < bci()) {
    if (is_osr_parse()) {    // Could be a hot OSR'd loop; force deopt
      ciMethodData* methodData = method()->method_data();
      if (!methodData->is_empty()) {
        ciProfileData* data = methodData->bci_to_data(bci());
        if (data == NULL ||
            (data->as_BranchData()->taken() +  data->as_BranchData()->not_taken() == 0)) {
          return PROB_UNKNOWN;
        }
      }
    }
    prob = PROB_STATIC_FREQUENT;     // Likely to take backwards branch
  }
  assert(prob != PROB_UNKNOWN, "must have some guess at this point");
  return prob;
}
bool Parse::seems_never_taken(float prob) const {
  return prob < PROB_MIN;
}
bool Parse::seems_stable_comparison() const {
  if (C->too_many_traps(method(), bci(), Deoptimization::Reason_unstable_if)) {
    return false;
  }
  return true;
}
inline int Parse::repush_if_args() {
#ifndef PRODUCT
  if (PrintOpto && WizardMode) {
    tty->print("defending against excessive implicit null exceptions on %s @%d in ",
               Bytecodes::name(iter().cur_bc()), iter().cur_bci());
    method()->print_name(); tty->cr();
  }
#endif
  int bc_depth = - Bytecodes::depth(iter().cur_bc());
  assert(bc_depth == 1 || bc_depth == 2, "only two kinds of branches");
  DEBUG_ONLY(sync_jvms());   // argument(n) requires a synced jvms
  assert(argument(0) != NULL, "must exist");
  assert(bc_depth == 1 || argument(1) != NULL, "two must exist");
  inc_sp(bc_depth);
  return bc_depth;
}
void Parse::do_ifnull(BoolTest::mask btest, Node *c) {
  int target_bci = iter().get_dest();
  Block* branch_block = successor_for_bci(target_bci);
  Block* next_block   = successor_for_bci(iter().next_bci());
  float cnt;
  float prob = branch_prediction(cnt, btest, target_bci, c);
  if (prob == PROB_UNKNOWN) {
#ifndef PRODUCT
    if (PrintOpto && Verbose)
      tty->print_cr("Never-taken edge stops compilation at bci %d",bci());
#endif
    repush_if_args(); // to gather stats on loop
    profile_taken_branch(target_bci, !ProfileInterpreter);
    uncommon_trap(Deoptimization::Reason_unreached,
                  Deoptimization::Action_reinterpret,
                  NULL, "cold");
    if (C->eliminate_boxing()) {
      branch_block->next_path_num();
      next_block->next_path_num();
    }
    return;
  }
  explicit_null_checks_inserted++;
  Node   *tst = _gvn.transform( new (C) BoolNode( c, btest ) );
  assert(prob > 0.0f,"Bad probability in Parser");
  IfNode *iff = create_and_xform_if( control(), tst, prob, cnt );
  assert(iff->_prob > 0.0f,"Optimizer made bad probability in parser");
  { PreserveJVMState pjvms(this);
    Node* iftrue  = _gvn.transform( new (C) IfTrueNode (iff) );
    set_control(iftrue);
    if (stopped()) {            // Path is dead?
      explicit_null_checks_elided++;
      if (C->eliminate_boxing()) {
        branch_block->next_path_num();
      }
    } else {                    // Path is live.
      profile_taken_branch(target_bci);
      adjust_map_after_if(btest, c, prob, branch_block, next_block);
      if (!stopped()) {
        merge(target_bci);
      }
    }
  }
  Node* iffalse = _gvn.transform( new (C) IfFalseNode(iff) );
  set_control(iffalse);
  if (stopped()) {              // Path is dead?
    explicit_null_checks_elided++;
    if (C->eliminate_boxing()) {
      next_block->next_path_num();
    }
  } else  {                     // Path is live.
    profile_not_taken_branch();
    adjust_map_after_if(BoolTest(btest).negate(), c, 1.0-prob,
                        next_block, branch_block);
  }
}
void Parse::do_if(BoolTest::mask btest, Node* c) {
  int target_bci = iter().get_dest();
  Block* branch_block = successor_for_bci(target_bci);
  Block* next_block   = successor_for_bci(iter().next_bci());
  float cnt;
  float prob = branch_prediction(cnt, btest, target_bci, c);
  float untaken_prob = 1.0 - prob;
  if (prob == PROB_UNKNOWN) {
#ifndef PRODUCT
    if (PrintOpto && Verbose)
      tty->print_cr("Never-taken edge stops compilation at bci %d",bci());
#endif
    repush_if_args(); // to gather stats on loop
    profile_taken_branch(target_bci, !ProfileInterpreter);
    uncommon_trap(Deoptimization::Reason_unreached,
                  Deoptimization::Action_reinterpret,
                  NULL, "cold");
    if (C->eliminate_boxing()) {
      branch_block->next_path_num();
      next_block->next_path_num();
    }
    return;
  }
  assert(0.0f < prob && prob < 1.0f,"Bad probability in Parser");
  bool taken_if_true = true;
  if (!BoolTest(btest).is_canonical()) {
    btest         = BoolTest(btest).negate();
    taken_if_true = false;
  }
  assert(btest != BoolTest::eq, "!= is the only canonical exact test");
  Node* tst0 = new (C) BoolNode(c, btest);
  Node* tst = _gvn.transform(tst0);
  BoolTest::mask taken_btest   = BoolTest::illegal;
  BoolTest::mask untaken_btest = BoolTest::illegal;
  if (tst->is_Bool()) {
    if (tst != tst0) {
      btest = tst->as_Bool()->_test._test;
      if (!BoolTest(btest).is_canonical()) {
        tst   = _gvn.transform( tst->as_Bool()->negate(&_gvn) );
        btest = tst->as_Bool()->_test._test;
        assert(BoolTest(btest).is_canonical(), "sanity");
        taken_if_true = !taken_if_true;
      }
      c = tst->in(1);
    }
    BoolTest::mask neg_btest = BoolTest(btest).negate();
    taken_btest   = taken_if_true ?     btest : neg_btest;
    untaken_btest = taken_if_true ? neg_btest :     btest;
  }
  float true_prob = (taken_if_true ? prob : untaken_prob);
  IfNode* iff = create_and_map_if(control(), tst, true_prob, cnt);
  assert(iff->_prob > 0.0f,"Optimizer made bad probability in parser");
  Node* taken_branch   = new (C) IfTrueNode(iff);
  Node* untaken_branch = new (C) IfFalseNode(iff);
  if (!taken_if_true) {  // Finish conversion to canonical form
    Node* tmp      = taken_branch;
    taken_branch   = untaken_branch;
    untaken_branch = tmp;
  }
  { PreserveJVMState pjvms(this);
    taken_branch = _gvn.transform(taken_branch);
    set_control(taken_branch);
    if (stopped()) {
      if (C->eliminate_boxing()) {
        branch_block->next_path_num();
      }
    } else {
      profile_taken_branch(target_bci);
      adjust_map_after_if(taken_btest, c, prob, branch_block, next_block);
      if (!stopped()) {
        merge(target_bci);
      }
    }
  }
  untaken_branch = _gvn.transform(untaken_branch);
  set_control(untaken_branch);
  if (stopped()) {
    if (C->eliminate_boxing()) {
      next_block->next_path_num();
    }
  } else {
    profile_not_taken_branch();
    adjust_map_after_if(untaken_btest, c, untaken_prob,
                        next_block, branch_block);
  }
}
bool Parse::path_is_suitable_for_uncommon_trap(float prob) const {
  if (!UseInterpreter) {
    return false;
  }
  return (seems_never_taken(prob) && seems_stable_comparison());
}
void Parse::adjust_map_after_if(BoolTest::mask btest, Node* c, float prob,
                                Block* path, Block* other_path) {
  if (stopped() || !c->is_Cmp() || btest == BoolTest::illegal)
    return;                             // nothing to do
  bool is_fallthrough = (path == successor_for_bci(iter().next_bci()));
  if (path_is_suitable_for_uncommon_trap(prob)) {
    repush_if_args();
    uncommon_trap(Deoptimization::Reason_unstable_if,
                  Deoptimization::Action_reinterpret,
                  NULL,
                  (is_fallthrough ? "taken always" : "taken never"));
    return;
  }
  Node* val = c->in(1);
  Node* con = c->in(2);
  const Type* tcon = _gvn.type(con);
  const Type* tval = _gvn.type(val);
  bool have_con = tcon->singleton();
  if (tval->singleton()) {
    if (!have_con) {
      con  = val;
      tcon = tval;
      val  = c->in(2);
      tval = _gvn.type(val);
      btest = BoolTest(btest).commute();
      have_con = true;
    } else {
      have_con = false;
    }
  }
  if (!have_con)                        // remaining adjustments need a con
    return;
  sharpen_type_after_if(btest, con, tcon, val, tval);
}
static Node* extract_obj_from_klass_load(PhaseGVN* gvn, Node* n) {
  Node* ldk;
  if (n->is_DecodeNKlass()) {
    if (n->in(1)->Opcode() != Op_LoadNKlass) {
      return NULL;
    } else {
      ldk = n->in(1);
    }
  } else if (n->Opcode() != Op_LoadKlass) {
    return NULL;
  } else {
    ldk = n;
  }
  assert(ldk != NULL && ldk->is_Load(), "should have found a LoadKlass or LoadNKlass node");
  Node* adr = ldk->in(MemNode::Address);
  intptr_t off = 0;
  Node* obj = AddPNode::Ideal_base_and_offset(adr, gvn, off);
  if (obj == NULL || off != oopDesc::klass_offset_in_bytes()) // loading oopDesc::_klass?
    return NULL;
  const TypePtr* tp = gvn->type(obj)->is_ptr();
  if (tp == NULL || !(tp->isa_instptr() || tp->isa_aryptr())) // is obj a Java object ptr?
    return NULL;
  return obj;
}
void Parse::sharpen_type_after_if(BoolTest::mask btest,
                                  Node* con, const Type* tcon,
                                  Node* val, const Type* tval) {
  if (btest == BoolTest::eq && tcon->isa_klassptr()) {
    Node* obj = extract_obj_from_klass_load(&_gvn, val);
    const TypeOopPtr* con_type = tcon->isa_klassptr()->as_instance_type();
    if (obj != NULL && (con_type->isa_instptr() || con_type->isa_aryptr())) {
       const Type* obj_type = _gvn.type(obj);
       const TypeOopPtr* tboth = obj_type->join_speculative(con_type)->isa_oopptr();
       if (tboth != NULL && tboth->klass_is_exact() && tboth != obj_type &&
           tboth->higher_equal(obj_type)) {
          int obj_in_map = map()->find_edge(obj);
          JVMState* jvms = this->jvms();
          if (obj_in_map >= 0 &&
              (jvms->is_loc(obj_in_map) || jvms->is_stk(obj_in_map))) {
            TypeNode* ccast = new (C) CheckCastPPNode(control(), obj, tboth);
            const Type* tcc = ccast->as_Type()->type();
            assert(tcc != obj_type && tcc->higher_equal_speculative(obj_type), "must improve");
            _gvn.set_type_bottom(ccast);
            record_for_igvn(ccast);
            replace_in_map(obj, ccast);
          }
       }
    }
  }
  int val_in_map = map()->find_edge(val);
  if (val_in_map < 0)  return;          // replace_in_map would be useless
  {
    JVMState* jvms = this->jvms();
    if (!(jvms->is_loc(val_in_map) ||
          jvms->is_stk(val_in_map)))
      return;                           // again, it would be useless
  }
  assert(tcon->singleton(), "");
  ConstraintCastNode* ccast = NULL;
  Node* cast = NULL;
  switch (btest) {
  case BoolTest::eq:                    // Constant test?
    {
      const Type* tboth = tcon->join_speculative(tval);
      if (tboth == tval)  break;        // Nothing to gain.
      if (tcon->isa_int()) {
        ccast = new (C) CastIINode(val, tboth);
      } else if (tcon == TypePtr::NULL_PTR) {
        ccast = new (C) CastPPNode(val, tboth);
      } else {
        const TypeF* tf = tcon->isa_float_constant();
        const TypeD* td = tcon->isa_double_constant();
        if ((!tf || tf->_f != 0.0) &&
            (!td || td->_d != 0.0))
          cast = con;                   // Replace non-constant val by con.
      }
    }
    break;
  case BoolTest::ne:
    if (tcon == TypePtr::NULL_PTR) {
      cast = cast_not_null(val, false);
    }
    break;
  default:
    break;
  }
  if (ccast != NULL) {
    const Type* tcc = ccast->as_Type()->type();
    assert(tcc != tval && tcc->higher_equal_speculative(tval), "must improve");
    ccast->set_req(0, control());
    _gvn.set_type_bottom(ccast);
    record_for_igvn(ccast);
    cast = ccast;
  }
  if (cast != NULL) {                   // Here's the payoff.
    replace_in_map(val, cast);
  }
}
Node* Parse::optimize_cmp_with_klass(Node* c) {
  if (c->Opcode() == Op_CmpP &&
      (c->in(1)->Opcode() == Op_LoadKlass || c->in(1)->Opcode() == Op_DecodeNKlass) &&
      c->in(2)->is_Con()) {
    Node* load_klass = NULL;
    Node* decode = NULL;
    if (c->in(1)->Opcode() == Op_DecodeNKlass) {
      decode = c->in(1);
      load_klass = c->in(1)->in(1);
    } else {
      load_klass = c->in(1);
    }
    if (load_klass->in(2)->is_AddP()) {
      Node* addp = load_klass->in(2);
      Node* obj = addp->in(AddPNode::Address);
      const TypeOopPtr* obj_type = _gvn.type(obj)->is_oopptr();
      if (obj_type->speculative_type() != NULL) {
        ciKlass* k = obj_type->speculative_type();
        inc_sp(2);
        obj = maybe_cast_profiled_obj(obj, k);
        dec_sp(2);
        addp = basic_plus_adr(obj, addp->in(AddPNode::Offset));
        load_klass = load_klass->clone();
        load_klass->set_req(2, addp);
        load_klass = _gvn.transform(load_klass);
        if (decode != NULL) {
          decode = decode->clone();
          decode->set_req(1, load_klass);
          load_klass = _gvn.transform(decode);
        }
        c = c->clone();
        c->set_req(1, load_klass);
        c = _gvn.transform(c);
      }
    }
  }
  return c;
}
void Parse::do_one_bytecode() {
  Node *a, *b, *c, *d;          // Handy temps
  BoolTest::mask btest;
  int i;
  assert(!has_exceptions(), "bytecode entry state must be clear of throws");
  if (C->check_node_count(NodeLimitFudgeFactor * 5,
                          "out of nodes parsing method")) {
    return;
  }
#ifdef ASSERT
  if (TraceOptoParse) {
    tty->print(" @");
    dump_bci(bci());
    tty->cr();
  }
#endif
  switch (bc()) {
  case Bytecodes::_nop:
    break;
  case Bytecodes::_lconst_0:
    push_pair(longcon(0));
    break;
  case Bytecodes::_lconst_1:
    push_pair(longcon(1));
    break;
  case Bytecodes::_fconst_0:
    push(zerocon(T_FLOAT));
    break;
  case Bytecodes::_fconst_1:
    push(makecon(TypeF::ONE));
    break;
  case Bytecodes::_fconst_2:
    push(makecon(TypeF::make(2.0f)));
    break;
  case Bytecodes::_dconst_0:
    push_pair(zerocon(T_DOUBLE));
    break;
  case Bytecodes::_dconst_1:
    push_pair(makecon(TypeD::ONE));
    break;
  case Bytecodes::_iconst_m1:push(intcon(-1)); break;
  case Bytecodes::_iconst_0: push(intcon( 0)); break;
  case Bytecodes::_iconst_1: push(intcon( 1)); break;
  case Bytecodes::_iconst_2: push(intcon( 2)); break;
  case Bytecodes::_iconst_3: push(intcon( 3)); break;
  case Bytecodes::_iconst_4: push(intcon( 4)); break;
  case Bytecodes::_iconst_5: push(intcon( 5)); break;
  case Bytecodes::_bipush:   push(intcon(iter().get_constant_u1())); break;
  case Bytecodes::_sipush:   push(intcon(iter().get_constant_u2())); break;
  case Bytecodes::_aconst_null: push(null());  break;
  case Bytecodes::_ldc:
  case Bytecodes::_ldc_w:
  case Bytecodes::_ldc2_w:
    {
      ciConstant constant = iter().get_constant();
      if (constant.basic_type() == T_OBJECT &&
          !constant.as_object()->is_loaded()) {
        int index = iter().get_constant_pool_index();
        constantTag tag = iter().get_constant_pool_tag(index);
        uncommon_trap(Deoptimization::make_trap_request
                      (Deoptimization::Reason_unloaded,
                       Deoptimization::Action_reinterpret,
                       index),
                      NULL, tag.internal_name());
        break;
      }
      assert(constant.basic_type() != T_OBJECT || constant.as_object()->is_instance(),
             "must be java_mirror of klass");
      bool pushed = push_constant(constant, true);
      guarantee(pushed, "must be possible to push this constant");
    }
    break;
  case Bytecodes::_aload_0:
    push( local(0) );
    break;
  case Bytecodes::_aload_1:
    push( local(1) );
    break;
  case Bytecodes::_aload_2:
    push( local(2) );
    break;
  case Bytecodes::_aload_3:
    push( local(3) );
    break;
  case Bytecodes::_aload:
    push( local(iter().get_index()) );
    break;
  case Bytecodes::_fload_0:
  case Bytecodes::_iload_0:
    push( local(0) );
    break;
  case Bytecodes::_fload_1:
  case Bytecodes::_iload_1:
    push( local(1) );
    break;
  case Bytecodes::_fload_2:
  case Bytecodes::_iload_2:
    push( local(2) );
    break;
  case Bytecodes::_fload_3:
  case Bytecodes::_iload_3:
    push( local(3) );
    break;
  case Bytecodes::_fload:
  case Bytecodes::_iload:
    push( local(iter().get_index()) );
    break;
  case Bytecodes::_lload_0:
    push_pair_local( 0 );
    break;
  case Bytecodes::_lload_1:
    push_pair_local( 1 );
    break;
  case Bytecodes::_lload_2:
    push_pair_local( 2 );
    break;
  case Bytecodes::_lload_3:
    push_pair_local( 3 );
    break;
  case Bytecodes::_lload:
    push_pair_local( iter().get_index() );
    break;
  case Bytecodes::_dload_0:
    push_pair_local(0);
    break;
  case Bytecodes::_dload_1:
    push_pair_local(1);
    break;
  case Bytecodes::_dload_2:
    push_pair_local(2);
    break;
  case Bytecodes::_dload_3:
    push_pair_local(3);
    break;
  case Bytecodes::_dload:
    push_pair_local(iter().get_index());
    break;
  case Bytecodes::_fstore_0:
  case Bytecodes::_istore_0:
  case Bytecodes::_astore_0:
    set_local( 0, pop() );
    break;
  case Bytecodes::_fstore_1:
  case Bytecodes::_istore_1:
  case Bytecodes::_astore_1:
    set_local( 1, pop() );
    break;
  case Bytecodes::_fstore_2:
  case Bytecodes::_istore_2:
  case Bytecodes::_astore_2:
    set_local( 2, pop() );
    break;
  case Bytecodes::_fstore_3:
  case Bytecodes::_istore_3:
  case Bytecodes::_astore_3:
    set_local( 3, pop() );
    break;
  case Bytecodes::_fstore:
  case Bytecodes::_istore:
  case Bytecodes::_astore:
    set_local( iter().get_index(), pop() );
    break;
  case Bytecodes::_lstore_0:
    set_pair_local( 0, pop_pair() );
    break;
  case Bytecodes::_lstore_1:
    set_pair_local( 1, pop_pair() );
    break;
  case Bytecodes::_lstore_2:
    set_pair_local( 2, pop_pair() );
    break;
  case Bytecodes::_lstore_3:
    set_pair_local( 3, pop_pair() );
    break;
  case Bytecodes::_lstore:
    set_pair_local( iter().get_index(), pop_pair() );
    break;
  case Bytecodes::_dstore_0:
    set_pair_local( 0, dstore_rounding(pop_pair()) );
    break;
  case Bytecodes::_dstore_1:
    set_pair_local( 1, dstore_rounding(pop_pair()) );
    break;
  case Bytecodes::_dstore_2:
    set_pair_local( 2, dstore_rounding(pop_pair()) );
    break;
  case Bytecodes::_dstore_3:
    set_pair_local( 3, dstore_rounding(pop_pair()) );
    break;
  case Bytecodes::_dstore:
    set_pair_local( iter().get_index(), dstore_rounding(pop_pair()) );
    break;
  case Bytecodes::_pop:  dec_sp(1);   break;
  case Bytecodes::_pop2: dec_sp(2);   break;
  case Bytecodes::_swap:
    a = pop();
    b = pop();
    push(a);
    push(b);
    break;
  case Bytecodes::_dup:
    a = pop();
    push(a);
    push(a);
    break;
  case Bytecodes::_dup_x1:
    a = pop();
    b = pop();
    push( a );
    push( b );
    push( a );
    break;
  case Bytecodes::_dup_x2:
    a = pop();
    b = pop();
    c = pop();
    push( a );
    push( c );
    push( b );
    push( a );
    break;
  case Bytecodes::_dup2:
    a = pop();
    b = pop();
    push( b );
    push( a );
    push( b );
    push( a );
    break;
  case Bytecodes::_dup2_x1:
    a = pop();
    b = pop();
    c = pop();
    push( b );
    push( a );
    push( c );
    push( b );
    push( a );
    break;
  case Bytecodes::_dup2_x2:
    a = pop();
    b = pop();
    c = pop();
    d = pop();
    push( b );
    push( a );
    push( d );
    push( c );
    push( b );
    push( a );
    break;
  case Bytecodes::_arraylength: {
    Node *ary = null_check(peek(), T_ARRAY);
    if (stopped())  return;
    a = pop();
    push(load_array_length(a));
    break;
  }
  case Bytecodes::_baload: array_load(T_BYTE);   break;
  case Bytecodes::_caload: array_load(T_CHAR);   break;
  case Bytecodes::_iaload: array_load(T_INT);    break;
  case Bytecodes::_saload: array_load(T_SHORT);  break;
  case Bytecodes::_faload: array_load(T_FLOAT);  break;
  case Bytecodes::_aaload: array_load(T_OBJECT); break;
  case Bytecodes::_laload: {
    a = array_addressing(T_LONG, 0);
    if (stopped())  return;     // guaranteed null or range check
    dec_sp(2);                  // Pop array and index
    push_pair(make_load(control(), a, TypeLong::LONG, T_LONG, TypeAryPtr::LONGS, MemNode::unordered));
    break;
  }
  case Bytecodes::_daload: {
    a = array_addressing(T_DOUBLE, 0);
    if (stopped())  return;     // guaranteed null or range check
    dec_sp(2);                  // Pop array and index
    push_pair(make_load(control(), a, Type::DOUBLE, T_DOUBLE, TypeAryPtr::DOUBLES, MemNode::unordered));
    break;
  }
  case Bytecodes::_bastore: array_store(T_BYTE);  break;
  case Bytecodes::_castore: array_store(T_CHAR);  break;
  case Bytecodes::_iastore: array_store(T_INT);   break;
  case Bytecodes::_sastore: array_store(T_SHORT); break;
  case Bytecodes::_fastore: array_store(T_FLOAT); break;
  case Bytecodes::_aastore: {
    d = array_addressing(T_OBJECT, 1);
    if (stopped())  return;     // guaranteed null or range check
    array_store_check();
    c = pop();                  // Oop to store
    b = pop();                  // index (already used)
    a = pop();                  // the array itself
    const TypeOopPtr* elemtype  = _gvn.type(a)->is_aryptr()->elem()->make_oopptr();
    const TypeAryPtr* adr_type = TypeAryPtr::OOPS;
    Node* store = store_oop_to_array(control(), a, d, adr_type, c, elemtype, T_OBJECT, MemNode::release);
    break;
  }
  case Bytecodes::_lastore: {
    a = array_addressing(T_LONG, 2);
    if (stopped())  return;     // guaranteed null or range check
    c = pop_pair();
    dec_sp(2);                  // Pop array and index
    store_to_memory(control(), a, c, T_LONG, TypeAryPtr::LONGS, MemNode::unordered);
    break;
  }
  case Bytecodes::_dastore: {
    a = array_addressing(T_DOUBLE, 2);
    if (stopped())  return;     // guaranteed null or range check
    c = pop_pair();
    dec_sp(2);                  // Pop array and index
    c = dstore_rounding(c);
    store_to_memory(control(), a, c, T_DOUBLE, TypeAryPtr::DOUBLES, MemNode::unordered);
    break;
  }
  case Bytecodes::_getfield:
    do_getfield();
    break;
  case Bytecodes::_getstatic:
    do_getstatic();
    break;
  case Bytecodes::_putfield:
    do_putfield();
    break;
  case Bytecodes::_putstatic:
    do_putstatic();
    break;
  case Bytecodes::_irem:
    do_irem();
    break;
  case Bytecodes::_idiv:
    zero_check_int(peek());
    if (stopped())  return;
    b = pop();
    a = pop();
    push( _gvn.transform( new (C) DivINode(control(),a,b) ) );
    break;
  case Bytecodes::_imul:
    b = pop(); a = pop();
    push( _gvn.transform( new (C) MulINode(a,b) ) );
    break;
  case Bytecodes::_iadd:
    b = pop(); a = pop();
    push( _gvn.transform( new (C) AddINode(a,b) ) );
    break;
  case Bytecodes::_ineg:
    a = pop();
    push( _gvn.transform( new (C) SubINode(_gvn.intcon(0),a)) );
    break;
  case Bytecodes::_isub:
    b = pop(); a = pop();
    push( _gvn.transform( new (C) SubINode(a,b) ) );
    break;
  case Bytecodes::_iand:
    b = pop(); a = pop();
    push( _gvn.transform( new (C) AndINode(a,b) ) );
    break;
  case Bytecodes::_ior:
    b = pop(); a = pop();
    push( _gvn.transform( new (C) OrINode(a,b) ) );
    break;
  case Bytecodes::_ixor:
    b = pop(); a = pop();
    push( _gvn.transform( new (C) XorINode(a,b) ) );
    break;
  case Bytecodes::_ishl:
    b = pop(); a = pop();
    push( _gvn.transform( new (C) LShiftINode(a,b) ) );
    break;
  case Bytecodes::_ishr:
    b = pop(); a = pop();
    push( _gvn.transform( new (C) RShiftINode(a,b) ) );
    break;
  case Bytecodes::_iushr:
    b = pop(); a = pop();
    push( _gvn.transform( new (C) URShiftINode(a,b) ) );
    break;
  case Bytecodes::_fneg:
    a = pop();
    b = _gvn.transform(new (C) NegFNode (a));
    push(b);
    break;
  case Bytecodes::_fsub:
    b = pop();
    a = pop();
    c = _gvn.transform( new (C) SubFNode(a,b) );
    d = precision_rounding(c);
    push( d );
    break;
  case Bytecodes::_fadd:
    b = pop();
    a = pop();
    c = _gvn.transform( new (C) AddFNode(a,b) );
    d = precision_rounding(c);
    push( d );
    break;
  case Bytecodes::_fmul:
    b = pop();
    a = pop();
    c = _gvn.transform( new (C) MulFNode(a,b) );
    d = precision_rounding(c);
    push( d );
    break;
  case Bytecodes::_fdiv:
    b = pop();
    a = pop();
    c = _gvn.transform( new (C) DivFNode(0,a,b) );
    d = precision_rounding(c);
    push( d );
    break;
  case Bytecodes::_frem:
    if (Matcher::has_match_rule(Op_ModF)) {
      b = pop();
      a = pop();
      c = _gvn.transform( new (C) ModFNode(0,a,b) );
      d = precision_rounding(c);
      push( d );
    }
    else {
      modf();
    }
    break;
  case Bytecodes::_fcmpl:
    b = pop();
    a = pop();
    c = _gvn.transform( new (C) CmpF3Node( a, b));
    push(c);
    break;
  case Bytecodes::_fcmpg:
    b = pop();
    a = pop();
    c = _gvn.transform( new (C) CmpF3Node( b, a));
    c = _gvn.transform( new (C) SubINode(_gvn.intcon(0),c) );
    push(c);
    break;
  case Bytecodes::_f2i:
    a = pop();
    push(_gvn.transform(new (C) ConvF2INode(a)));
    break;
  case Bytecodes::_d2i:
    a = pop_pair();
    b = _gvn.transform(new (C) ConvD2INode(a));
    push( b );
    break;
  case Bytecodes::_f2d:
    a = pop();
    b = _gvn.transform( new (C) ConvF2DNode(a));
    push_pair( b );
    break;
  case Bytecodes::_d2f:
    a = pop_pair();
    b = _gvn.transform( new (C) ConvD2FNode(a));
    push( b );
    break;
  case Bytecodes::_l2f:
    if (Matcher::convL2FSupported()) {
      a = pop_pair();
      b = _gvn.transform( new (C) ConvL2FNode(a));
      c = _gvn.transform(b);
      push(c);
    } else {
      l2f();
    }
    break;
  case Bytecodes::_l2d:
    a = pop_pair();
    b = _gvn.transform( new (C) ConvL2DNode(a));
    c = _gvn.transform(b);
    push_pair(c);
    break;
  case Bytecodes::_f2l:
    a = pop();
    b = _gvn.transform( new (C) ConvF2LNode(a));
    push_pair(b);
    break;
  case Bytecodes::_d2l:
    a = pop_pair();
    b = _gvn.transform( new (C) ConvD2LNode(a));
    push_pair(b);
    break;
  case Bytecodes::_dsub:
    b = pop_pair();
    a = pop_pair();
    c = _gvn.transform( new (C) SubDNode(a,b) );
    d = dprecision_rounding(c);
    push_pair( d );
    break;
  case Bytecodes::_dadd:
    b = pop_pair();
    a = pop_pair();
    c = _gvn.transform( new (C) AddDNode(a,b) );
    d = dprecision_rounding(c);
    push_pair( d );
    break;
  case Bytecodes::_dmul:
    b = pop_pair();
    a = pop_pair();
    c = _gvn.transform( new (C) MulDNode(a,b) );
    d = dprecision_rounding(c);
    push_pair( d );
    break;
  case Bytecodes::_ddiv:
    b = pop_pair();
    a = pop_pair();
    c = _gvn.transform( new (C) DivDNode(0,a,b) );
    d = dprecision_rounding(c);
    push_pair( d );
    break;
  case Bytecodes::_dneg:
    a = pop_pair();
    b = _gvn.transform(new (C) NegDNode (a));
    push_pair(b);
    break;
  case Bytecodes::_drem:
    if (Matcher::has_match_rule(Op_ModD)) {
      b = pop_pair();
      a = pop_pair();
      c = _gvn.transform( new (C) ModDNode(0,a,b) );
      d = dprecision_rounding(c);
      push_pair( d );
    }
    else {
      modd();
    }
    break;
  case Bytecodes::_dcmpl:
    b = pop_pair();
    a = pop_pair();
    c = _gvn.transform( new (C) CmpD3Node( a, b));
    push(c);
    break;
  case Bytecodes::_dcmpg:
    b = pop_pair();
    a = pop_pair();
    c = _gvn.transform( new (C) CmpD3Node( b, a));
    c = _gvn.transform( new (C) SubINode(_gvn.intcon(0),c) );
    push(c);
    break;
  case Bytecodes::_land:
    b = pop_pair();
    a = pop_pair();
    c = _gvn.transform( new (C) AndLNode(a,b) );
    push_pair(c);
    break;
  case Bytecodes::_lor:
    b = pop_pair();
    a = pop_pair();
    c = _gvn.transform( new (C) OrLNode(a,b) );
    push_pair(c);
    break;
  case Bytecodes::_lxor:
    b = pop_pair();
    a = pop_pair();
    c = _gvn.transform( new (C) XorLNode(a,b) );
    push_pair(c);
    break;
  case Bytecodes::_lshl:
    b = pop();                  // the shift count
    a = pop_pair();             // value to be shifted
    c = _gvn.transform( new (C) LShiftLNode(a,b) );
    push_pair(c);
    break;
  case Bytecodes::_lshr:
    b = pop();                  // the shift count
    a = pop_pair();             // value to be shifted
    c = _gvn.transform( new (C) RShiftLNode(a,b) );
    push_pair(c);
    break;
  case Bytecodes::_lushr:
    b = pop();                  // the shift count
    a = pop_pair();             // value to be shifted
    c = _gvn.transform( new (C) URShiftLNode(a,b) );
    push_pair(c);
    break;
  case Bytecodes::_lmul:
    b = pop_pair();
    a = pop_pair();
    c = _gvn.transform( new (C) MulLNode(a,b) );
    push_pair(c);
    break;
  case Bytecodes::_lrem:
    assert(peek(0) == top(), "long word order");
    zero_check_long(peek(1));
    if (stopped())  return;
    b = pop_pair();
    a = pop_pair();
    c = _gvn.transform( new (C) ModLNode(control(),a,b) );
    push_pair(c);
    break;
  case Bytecodes::_ldiv:
    assert(peek(0) == top(), "long word order");
    zero_check_long(peek(1));
    if (stopped())  return;
    b = pop_pair();
    a = pop_pair();
    c = _gvn.transform( new (C) DivLNode(control(),a,b) );
    push_pair(c);
    break;
  case Bytecodes::_ladd:
    b = pop_pair();
    a = pop_pair();
    c = _gvn.transform( new (C) AddLNode(a,b) );
    push_pair(c);
    break;
  case Bytecodes::_lsub:
    b = pop_pair();
    a = pop_pair();
    c = _gvn.transform( new (C) SubLNode(a,b) );
    push_pair(c);
    break;
  case Bytecodes::_lcmp:
    if( UseLoopSafepoints ) {
      switch( iter().next_bc() ) {
      case Bytecodes::_ifgt:
      case Bytecodes::_iflt:
      case Bytecodes::_ifge:
      case Bytecodes::_ifle:
      case Bytecodes::_ifne:
      case Bytecodes::_ifeq:
        maybe_add_safepoint(iter().next_get_dest());
      }
    }
    b = pop_pair();
    a = pop_pair();
    c = _gvn.transform( new (C) CmpL3Node( a, b ));
    push(c);
    break;
  case Bytecodes::_lneg:
    a = pop_pair();
    b = _gvn.transform( new (C) SubLNode(longcon(0),a));
    push_pair(b);
    break;
  case Bytecodes::_l2i:
    a = pop_pair();
    push( _gvn.transform( new (C) ConvL2INode(a)));
    break;
  case Bytecodes::_i2l:
    a = pop();
    b = _gvn.transform( new (C) ConvI2LNode(a));
    push_pair(b);
    break;
  case Bytecodes::_i2b:
    a = pop();
    a = _gvn.transform( new (C) LShiftINode(a,_gvn.intcon(24)) );
    a = _gvn.transform( new (C) RShiftINode(a,_gvn.intcon(24)) );
    push( a );
    break;
  case Bytecodes::_i2s:
    a = pop();
    a = _gvn.transform( new (C) LShiftINode(a,_gvn.intcon(16)) );
    a = _gvn.transform( new (C) RShiftINode(a,_gvn.intcon(16)) );
    push( a );
    break;
  case Bytecodes::_i2c:
    a = pop();
    push( _gvn.transform( new (C) AndINode(a,_gvn.intcon(0xFFFF)) ) );
    break;
  case Bytecodes::_i2f:
    a = pop();
    b = _gvn.transform( new (C) ConvI2FNode(a) ) ;
    c = precision_rounding(b);
    push (b);
    break;
  case Bytecodes::_i2d:
    a = pop();
    b = _gvn.transform( new (C) ConvI2DNode(a));
    push_pair(b);
    break;
  case Bytecodes::_iinc:        // Increment local
    i = iter().get_index();     // Get local index
    set_local( i, _gvn.transform( new (C) AddINode( _gvn.intcon(iter().get_iinc_con()), local(i) ) ) );
    break;
  case Bytecodes::_return:
    return_current(NULL);
    break;
  case Bytecodes::_ireturn:
  case Bytecodes::_areturn:
  case Bytecodes::_freturn:
    return_current(pop());
    break;
  case Bytecodes::_lreturn:
    return_current(pop_pair());
    break;
  case Bytecodes::_dreturn:
    return_current(pop_pair());
    break;
  case Bytecodes::_athrow:
    null_check(peek());
    if (stopped())  return;
    if (BailoutToInterpreterForThrows) {
      uncommon_trap(Deoptimization::Reason_unhandled,
                    Deoptimization::Action_make_not_compilable);
      return;
    }
    if (env()->jvmti_can_post_on_exceptions()) {
      uncommon_trap_if_should_post_on_exceptions(Deoptimization::Reason_unhandled, false);
    }
    add_exception_state(make_exception_state(peek()));
    break;
  case Bytecodes::_goto:   // fall through
  case Bytecodes::_goto_w: {
    int target_bci = (bc() == Bytecodes::_goto) ? iter().get_dest() : iter().get_far_dest();
    maybe_add_safepoint(target_bci);
    profile_taken_branch(target_bci);
    merge(target_bci);
    Block *target_block = block()->successor_for_bci(target_bci);
    if (target_block->pred_count() != 1)  break;
    ciMethodData* methodData = method()->method_data();
    if (!methodData->is_mature())  break;
    ciProfileData* data = methodData->bci_to_data(bci());
    assert( data->is_JumpData(), "" );
    int taken = ((ciJumpData*)data)->taken();
    taken = method()->scale_count(taken);
    target_block->set_count(taken);
    break;
  }
  case Bytecodes::_ifnull:    btest = BoolTest::eq; goto handle_if_null;
  case Bytecodes::_ifnonnull: btest = BoolTest::ne; goto handle_if_null;
  handle_if_null:
    maybe_add_safepoint(iter().get_dest());
    a = null();
    b = pop();
    c = _gvn.transform( new (C) CmpPNode(b, a) );
    do_ifnull(btest, c);
    break;
  case Bytecodes::_if_acmpeq: btest = BoolTest::eq; goto handle_if_acmp;
  case Bytecodes::_if_acmpne: btest = BoolTest::ne; goto handle_if_acmp;
  handle_if_acmp:
    maybe_add_safepoint(iter().get_dest());
    a = pop();
    b = pop();
    c = _gvn.transform( new (C) CmpPNode(b, a) );
    c = optimize_cmp_with_klass(c);
    do_if(btest, c);
    break;
  case Bytecodes::_ifeq: btest = BoolTest::eq; goto handle_ifxx;
  case Bytecodes::_ifne: btest = BoolTest::ne; goto handle_ifxx;
  case Bytecodes::_iflt: btest = BoolTest::lt; goto handle_ifxx;
  case Bytecodes::_ifle: btest = BoolTest::le; goto handle_ifxx;
  case Bytecodes::_ifgt: btest = BoolTest::gt; goto handle_ifxx;
  case Bytecodes::_ifge: btest = BoolTest::ge; goto handle_ifxx;
  handle_ifxx:
    maybe_add_safepoint(iter().get_dest());
    a = _gvn.intcon(0);
    b = pop();
    c = _gvn.transform( new (C) CmpINode(b, a) );
    do_if(btest, c);
    break;
  case Bytecodes::_if_icmpeq: btest = BoolTest::eq; goto handle_if_icmp;
  case Bytecodes::_if_icmpne: btest = BoolTest::ne; goto handle_if_icmp;
  case Bytecodes::_if_icmplt: btest = BoolTest::lt; goto handle_if_icmp;
  case Bytecodes::_if_icmple: btest = BoolTest::le; goto handle_if_icmp;
  case Bytecodes::_if_icmpgt: btest = BoolTest::gt; goto handle_if_icmp;
  case Bytecodes::_if_icmpge: btest = BoolTest::ge; goto handle_if_icmp;
  handle_if_icmp:
    maybe_add_safepoint(iter().get_dest());
    a = pop();
    b = pop();
    c = _gvn.transform( new (C) CmpINode( b, a ) );
    do_if(btest, c);
    break;
  case Bytecodes::_tableswitch:
    do_tableswitch();
    break;
  case Bytecodes::_lookupswitch:
    do_lookupswitch();
    break;
  case Bytecodes::_invokestatic:
  case Bytecodes::_invokedynamic:
  case Bytecodes::_invokespecial:
  case Bytecodes::_invokevirtual:
  case Bytecodes::_invokeinterface:
    do_call();
    break;
  case Bytecodes::_checkcast:
    do_checkcast();
    break;
  case Bytecodes::_instanceof:
    do_instanceof();
    break;
  case Bytecodes::_anewarray:
    do_anewarray();
    break;
  case Bytecodes::_newarray:
    do_newarray((BasicType)iter().get_index());
    break;
  case Bytecodes::_multianewarray:
    do_multianewarray();
    break;
  case Bytecodes::_new:
    do_new();
    break;
  case Bytecodes::_jsr:
  case Bytecodes::_jsr_w:
    do_jsr();
    break;
  case Bytecodes::_ret:
    do_ret();
    break;
  case Bytecodes::_monitorenter:
    do_monitor_enter();
    break;
  case Bytecodes::_monitorexit:
    do_monitor_exit();
    break;
  case Bytecodes::_breakpoint:
    C->record_failure("breakpoint in method");
    return;
  default:
#ifndef PRODUCT
    map()->dump(99);
#endif
    tty->print("\nUnhandled bytecode %s\n", Bytecodes::name(bc()) );
    ShouldNotReachHere();
  }
#ifndef PRODUCT
  IdealGraphPrinter *printer = IdealGraphPrinter::printer();
  if(printer) {
    char buffer[256];
    sprintf(buffer, "Bytecode %d: %s", bci(), Bytecodes::name(bc()));
    bool old = printer->traverse_outs();
    printer->set_traverse_outs(true);
    printer->print_method(C, buffer, 4);
    printer->set_traverse_outs(old);
  }
#endif
}
C:\hotspot-69087d08d473\src\share\vm/opto/parse3.cpp
#include "precompiled.hpp"
#include "compiler/compileLog.hpp"
#include "interpreter/linkResolver.hpp"
#include "memory/universe.inline.hpp"
#include "oops/objArrayKlass.hpp"
#include "opto/addnode.hpp"
#include "opto/memnode.hpp"
#include "opto/parse.hpp"
#include "opto/rootnode.hpp"
#include "opto/runtime.hpp"
#include "opto/subnode.hpp"
#include "runtime/deoptimization.hpp"
#include "runtime/handles.inline.hpp"
bool Parse::static_field_ok_in_clinit(ciField *field, ciMethod *method) {
  assert( field->is_static(), "Only check if field is static");
  ciInstanceKlass *field_holder = field->holder();
  bool access_OK = false;
  if (method->holder()->is_subclass_of(field_holder)) {
    if (method->is_static()) {
      if (method->name() == ciSymbol::class_initializer_name()) {
        access_OK = true;
      }
    } else {
      if (method->name() == ciSymbol::object_initializer_name()) {
        access_OK = true;
      }
    }
  }
  return access_OK;
}
void Parse::do_field_access(bool is_get, bool is_field) {
  bool will_link;
  ciField* field = iter().get_field(will_link);
  assert(will_link, "getfield: typeflow responsibility");
  ciInstanceKlass* field_holder = field->holder();
  if (is_field == field->is_static()) {
    uncommon_trap(Deoptimization::Reason_unhandled,
                  Deoptimization::Action_none);
    return;
  }
  if (!is_field && !field_holder->is_initialized()) {
    if (!static_field_ok_in_clinit(field, method())) {
      uncommon_trap(Deoptimization::Reason_uninitialized,
                    Deoptimization::Action_reinterpret,
                    NULL, "!static_field_ok_in_clinit");
      return;
    }
  }
  if (!is_get && field->is_call_site_target()) {
    uncommon_trap(Deoptimization::Reason_unhandled,
                  Deoptimization::Action_reinterpret,
                  NULL, "put to call site target field");
    return;
  }
  assert(field->will_link(method()->holder(), bc()), "getfield: typeflow responsibility");
  Node* obj;
  if (is_field) {
    int obj_depth = is_get ? 0 : field->type()->size();
    obj = null_check(peek(obj_depth));
    if (stopped())  return;
#ifdef ASSERT
    const TypeInstPtr *tjp = TypeInstPtr::make(TypePtr::NotNull, iter().get_declared_field_holder());
    assert(_gvn.type(obj)->higher_equal(tjp), "cast_up is no longer needed");
#endif
    if (is_get) {
      (void) pop();  // pop receiver before getting
      do_get_xxx(obj, field, is_field);
    } else {
      do_put_xxx(obj, field, is_field);
      (void) pop();  // pop receiver after putting
    }
  } else {
    const TypeInstPtr* tip = TypeInstPtr::make(field_holder->java_mirror());
    obj = _gvn.makecon(tip);
    if (is_get) {
      do_get_xxx(obj, field, is_field);
    } else {
      do_put_xxx(obj, field, is_field);
    }
  }
}
void Parse::do_get_xxx(Node* obj, ciField* field, bool is_field) {
  if (field->is_constant()) {
    const Type* stable_type = NULL;
    if (FoldStableValues && field->is_stable()) {
      stable_type = Type::get_const_type(field->type());
      if (field->type()->is_array_klass()) {
        int stable_dimension = field->type()->as_array_klass()->dimension();
        stable_type = stable_type->is_aryptr()->cast_to_stable(true, stable_dimension);
      }
    }
    if (field->is_static()) {
      if (C->eliminate_boxing()) {
        ciSymbol* klass_name = field->holder()->name();
        if (field->name() == ciSymbol::cache_field_name() &&
            field->holder()->uses_default_loader() &&
            (klass_name == ciSymbol::java_lang_Character_CharacterCache() ||
             klass_name == ciSymbol::java_lang_Byte_ByteCache() ||
             klass_name == ciSymbol::java_lang_Short_ShortCache() ||
             klass_name == ciSymbol::java_lang_Integer_IntegerCache() ||
             klass_name == ciSymbol::java_lang_Long_LongCache())) {
          bool require_const = true;
          bool autobox_cache = true;
          if (push_constant(field->constant_value(), require_const, autobox_cache)) {
            return;
          }
        }
      }
      if (push_constant(field->constant_value(), false, false, stable_type))
        return;
    } else {
      if (obj->is_Con()) {
        const TypeOopPtr* oop_ptr = obj->bottom_type()->isa_oopptr();
        ciObject* constant_oop = oop_ptr->const_oop();
        ciConstant constant = field->constant_value_of(constant_oop);
        if (FoldStableValues && field->is_stable() && constant.is_null_or_zero()) {
        } else {
          if (push_constant(constant, true, false, stable_type))
            return;
        }
      }
    }
  }
  Node* leading_membar = NULL;
  ciType* field_klass = field->type();
  bool is_vol = field->is_volatile();
  int offset = field->offset_in_bytes();
  const TypePtr* adr_type = C->alias_type(field)->adr_type();
  Node *adr = basic_plus_adr(obj, obj, offset);
  BasicType bt = field->layout_type();
  const Type *type;
  bool must_assert_null = false;
  if( bt == T_OBJECT ) {
    if (!field->type()->is_loaded()) {
      type = TypeInstPtr::BOTTOM;
      must_assert_null = true;
    } else if (field->is_constant() && field->is_static()) {
      ciObject* con = field->constant_value().as_object();
      type = TypeOopPtr::make_from_constant(con)->isa_oopptr();
      assert(type != NULL, "field singleton type must be consistent");
    } else {
      type = TypeOopPtr::make_from_klass(field_klass->as_klass());
    }
  } else {
    type = Type::get_const_basic_type(bt);
  }
  if (support_IRIW_for_not_multiple_copy_atomic_cpu && field->is_volatile()) {
    leading_membar = insert_mem_bar(Op_MemBarVolatile);   // StoreLoad barrier
  }
  MemNode::MemOrd mo = is_vol ? MemNode::acquire : MemNode::unordered;
  Node* ld = make_load(NULL, adr, type, bt, adr_type, mo, LoadNode::DependsOnlyOnTest, is_vol);
  if (type2size[bt] == 1)
    push(ld);
  else
    push_pair(ld);
  if (must_assert_null) {
#ifndef PRODUCT
    if (PrintOpto && (Verbose || WizardMode)) {
      method()->print_name(); tty->print_cr(" asserting nullness of field at bci: %d", bci());
    }
#endif
    if (C->log() != NULL) {
      C->log()->elem("assert_null reason='field' klass='%d'",
                     C->log()->identify(field->type()));
    }
    set_bci(iter().next_bci());
    null_assert(peek());
    set_bci(iter().cur_bci()); // put it back
  }
  if (field->is_volatile()) {
    assert(leading_membar == NULL || support_IRIW_for_not_multiple_copy_atomic_cpu, "no leading membar expected");
    Node* mb = insert_mem_bar(Op_MemBarAcquire, ld);
    mb->as_MemBar()->set_trailing_load();
  }
}
void Parse::do_put_xxx(Node* obj, ciField* field, bool is_field) {
  Node* leading_membar = NULL;
  bool is_vol = field->is_volatile();
  if (is_vol) {
    leading_membar = insert_mem_bar(Op_MemBarRelease);
  }
  int offset = field->offset_in_bytes();
  const TypePtr* adr_type = C->alias_type(field)->adr_type();
  Node* adr = basic_plus_adr(obj, obj, offset);
  BasicType bt = field->layout_type();
  Node* val = type2size[bt] == 1 ? pop() : pop_pair();
  if (bt == T_DOUBLE)  val = dstore_rounding(val);
  const MemNode::MemOrd mo =
    is_vol ?
    MemNode::release :
    StoreNode::release_if_reference(bt);
  Node* store;
  if (bt == T_OBJECT) {
    const TypeOopPtr* field_type;
    if (!field->type()->is_loaded()) {
      field_type = TypeInstPtr::BOTTOM;
    } else {
      field_type = TypeOopPtr::make_from_klass(field->type()->as_klass());
    }
    store = store_oop_to_object(control(), obj, adr, adr_type, val, field_type, bt, mo);
  } else {
    store = store_to_memory(control(), adr, val, bt, adr_type, mo, is_vol);
  }
  if (is_vol) {
    if (!support_IRIW_for_not_multiple_copy_atomic_cpu) {
      Node* mb = insert_mem_bar(Op_MemBarVolatile, store); // Use fat membar
      MemBarNode::set_store_pair(leading_membar->as_MemBar(), mb->as_MemBar());
    }
    if (is_field) {
      set_wrote_volatile(true);
    }
  }
  if (is_field && (field->is_final() || field->is_stable())) {
    set_wrote_final(true);
    if (C->eliminate_boxing() &&
        adr_type->isa_oopptr() && adr_type->is_oopptr()->is_ptr_to_boxed_value() &&
        AllocateNode::Ideal_allocation(obj, &_gvn) != NULL) {
      set_alloc_with_final(obj);
    }
  }
}
bool Parse::push_constant(ciConstant constant, bool require_constant, bool is_autobox_cache, const Type* stable_type) {
  const Type* con_type = Type::make_from_constant(constant, require_constant, is_autobox_cache);
  switch (constant.basic_type()) {
  case T_ARRAY:
  case T_OBJECT:
    if (stable_type != NULL && con_type != NULL && con_type->isa_oopptr())
      con_type = con_type->join_speculative(stable_type);
    break;
  case T_ILLEGAL:
    assert(C->env()->failing(), "otherwise should not see this");
    push( zerocon(T_OBJECT) );
    return false;
  }
  if (con_type == NULL)
    return false;
  push_node(constant.basic_type(), makecon(con_type));
  return true;
}
void Parse::do_anewarray() {
  bool will_link;
  ciKlass* klass = iter().get_klass(will_link);
  assert(will_link, "anewarray: typeflow responsibility");
  ciObjArrayKlass* array_klass = ciObjArrayKlass::make(klass);
  if (!array_klass->is_loaded()) {
    uncommon_trap(Deoptimization::Reason_unloaded,
                  Deoptimization::Action_reinterpret,
                  array_klass);
    return;
  }
  kill_dead_locals();
  const TypeKlassPtr* array_klass_type = TypeKlassPtr::make(array_klass);
  Node* count_val = pop();
  Node* obj = new_array(makecon(array_klass_type), count_val, 1);
  push(obj);
}
void Parse::do_newarray(BasicType elem_type) {
  kill_dead_locals();
  Node*   count_val = pop();
  const TypeKlassPtr* array_klass = TypeKlassPtr::make(ciTypeArrayKlass::make(elem_type));
  Node*   obj = new_array(makecon(array_klass), count_val, 1);
  push(obj);
}
Node* Parse::expand_multianewarray(ciArrayKlass* array_klass, Node* *lengths, int ndimensions, int nargs) {
  Node* length = lengths[0];
  assert(length != NULL, "");
  Node* array = new_array(makecon(TypeKlassPtr::make(array_klass)), length, nargs);
  if (ndimensions > 1) {
    jint length_con = find_int_con(length, -1);
    guarantee(length_con >= 0, "non-constant multianewarray");
    ciArrayKlass* array_klass_1 = array_klass->as_obj_array_klass()->element_klass()->as_array_klass();
    const TypePtr* adr_type = TypeAryPtr::OOPS;
    const TypeOopPtr*    elemtype = _gvn.type(array)->is_aryptr()->elem()->make_oopptr();
    const intptr_t header   = arrayOopDesc::base_offset_in_bytes(T_OBJECT);
    for (jint i = 0; i < length_con; i++) {
      Node*    elem   = expand_multianewarray(array_klass_1, &lengths[1], ndimensions-1, nargs);
      intptr_t offset = header + ((intptr_t)i << LogBytesPerHeapOop);
      Node*    eaddr  = basic_plus_adr(array, offset);
      store_oop_to_array(control(), array, eaddr, adr_type, elem, elemtype, T_OBJECT, MemNode::unordered);
    }
  }
  return array;
}
void Parse::do_multianewarray() {
  int ndimensions = iter().get_dimensions();
  bool will_link;
  ciArrayKlass* array_klass = iter().get_klass(will_link)->as_array_klass();
  assert(will_link, "multianewarray: typeflow responsibility");
  kill_dead_locals();
  Node** length = NEW_RESOURCE_ARRAY(Node*, ndimensions + 1);
  length[ndimensions] = NULL;  // terminating null for make_runtime_call
  int j;
  for (j = ndimensions-1; j >= 0 ; j--) length[j] = pop();
  const jint expand_limit = MIN2((juint)MultiArrayExpandLimit, (juint)100);
  jint expand_count = 1;        // count of allocations in the expansion
  jint expand_fanout = 1;       // running total fanout
  for (j = 0; j < ndimensions-1; j++) {
    jint dim_con = find_int_con(length[j], -1);
    expand_fanout *= dim_con;
    expand_count  += expand_fanout; // count the level-J sub-arrays
    if (dim_con <= 0
        || dim_con > expand_limit
        || expand_count > expand_limit) {
      expand_count = 0;
      break;
    }
  }
  if (ndimensions == 1 || (1 <= expand_count && expand_count <= expand_limit)) {
    Node* obj = NULL;
    { PreserveReexecuteState preexecs(this);
      inc_sp(ndimensions);
      obj = expand_multianewarray(array_klass, &length[0], ndimensions, 0);
    } //original reexecute and sp are set back here
    push(obj);
    return;
  }
  address fun = NULL;
  switch (ndimensions) {
  case 1: ShouldNotReachHere(); break;
  case 2: fun = OptoRuntime::multianewarray2_Java(); break;
  case 3: fun = OptoRuntime::multianewarray3_Java(); break;
  case 4: fun = OptoRuntime::multianewarray4_Java(); break;
  case 5: fun = OptoRuntime::multianewarray5_Java(); break;
  };
  Node* c = NULL;
  if (fun != NULL) {
    c = make_runtime_call(RC_NO_LEAF | RC_NO_IO,
                          OptoRuntime::multianewarray_Type(ndimensions),
                          fun, NULL, TypeRawPtr::BOTTOM,
                          makecon(TypeKlassPtr::make(array_klass)),
                          length[0], length[1], length[2],
                          (ndimensions > 2) ? length[3] : NULL,
                          (ndimensions > 3) ? length[4] : NULL);
  } else {
    Node* dims = NULL;
    { PreserveReexecuteState preexecs(this);
      inc_sp(ndimensions);
      Node* dims_array_klass = makecon(TypeKlassPtr::make(ciArrayKlass::make(ciType::make(T_INT))));
      dims = new_array(dims_array_klass, intcon(ndimensions), 0);
      for (j = 0; j < ndimensions; j++) {
        Node *dims_elem = array_element_address(dims, intcon(j), T_INT);
        store_to_memory(control(), dims_elem, length[j], T_INT, TypeAryPtr::INTS, MemNode::unordered);
      }
    }
    c = make_runtime_call(RC_NO_LEAF | RC_NO_IO,
                          OptoRuntime::multianewarrayN_Type(),
                          OptoRuntime::multianewarrayN_Java(), NULL, TypeRawPtr::BOTTOM,
                          makecon(TypeKlassPtr::make(array_klass)),
                          dims);
  }
  make_slow_call_ex(c, env()->Throwable_klass(), false);
  Node* res = _gvn.transform(new (C) ProjNode(c, TypeFunc::Parms));
  const Type* type = TypeOopPtr::make_from_klass_raw(array_klass);
  type = type->is_ptr()->cast_to_ptr_type(TypePtr::NotNull);
  type = type->is_aryptr()->cast_to_exactness(true);
  const TypeInt* ltype = _gvn.find_int_type(length[0]);
  if (ltype != NULL)
    type = type->is_aryptr()->cast_to_size(ltype);
  Node* cast = _gvn.transform( new (C) CheckCastPPNode(control(), res, type) );
  push(cast);
}
C:\hotspot-69087d08d473\src\share\vm/opto/parseHelper.cpp
#include "precompiled.hpp"
#include "classfile/systemDictionary.hpp"
#include "compiler/compileLog.hpp"
#include "oops/objArrayKlass.hpp"
#include "opto/addnode.hpp"
#include "opto/memnode.hpp"
#include "opto/mulnode.hpp"
#include "opto/parse.hpp"
#include "opto/rootnode.hpp"
#include "opto/runtime.hpp"
#include "runtime/sharedRuntime.hpp"
void GraphKit::make_dtrace_method_entry_exit(ciMethod* method, bool is_entry) {
  const TypeFunc *call_type    = OptoRuntime::dtrace_method_entry_exit_Type();
  address         call_address = is_entry ? CAST_FROM_FN_PTR(address, SharedRuntime::dtrace_method_entry) :
                                            CAST_FROM_FN_PTR(address, SharedRuntime::dtrace_method_exit);
  const char     *call_name    = is_entry ? "dtrace_method_entry" : "dtrace_method_exit";
  Node* thread = _gvn.transform( new (C) ThreadLocalNode() );
  const TypePtr* method_type = TypeMetadataPtr::make(method);
  Node *method_node = _gvn.transform( ConNode::make(C, method_type) );
  kill_dead_locals();
  const TypePtr* raw_adr_type = TypeRawPtr::BOTTOM;
  make_runtime_call(RC_LEAF | RC_NARROW_MEM,
                    call_type, call_address,
                    call_name, raw_adr_type,
                    thread, method_node);
}
void Parse::do_checkcast() {
  bool will_link;
  ciKlass* klass = iter().get_klass(will_link);
  Node *obj = peek();
  const TypeOopPtr *tp = _gvn.type(obj)->isa_oopptr();
  if (!will_link || (tp && tp->klass() && !tp->klass()->is_loaded())) {
    if (C->log() != NULL) {
      if (!will_link) {
        C->log()->elem("assert_null reason='checkcast' klass='%d'",
                       C->log()->identify(klass));
      }
      if (tp && tp->klass() && !tp->klass()->is_loaded()) {
        C->log()->elem("assert_null reason='checkcast source' klass='%d'",
                       C->log()->identify(tp->klass()));
      }
    }
    null_assert(obj);
    assert( stopped() || _gvn.type(peek())->higher_equal(TypePtr::NULL_PTR), "what's left behind is null" );
    if (!stopped()) {
      profile_null_checkcast();
    }
    return;
  }
  Node *res = gen_checkcast(obj, makecon(TypeKlassPtr::make(klass)) );
  pop();
  push(res);
}
void Parse::do_instanceof() {
  if (stopped())  return;
  bool will_link;
  ciKlass* klass = iter().get_klass(will_link);
  if (!will_link) {
    if (C->log() != NULL) {
      C->log()->elem("assert_null reason='instanceof' klass='%d'",
                     C->log()->identify(klass));
    }
    null_assert(peek());
    assert( stopped() || _gvn.type(peek())->higher_equal(TypePtr::NULL_PTR), "what's left behind is null" );
    if (!stopped()) {
      pop();                   // pop the null
      push(_gvn.intcon(0));    // push false answer
    }
    return;
  }
  Node* res = gen_instanceof(peek(), makecon(TypeKlassPtr::make(klass)), true);
  pop();
  push(res);
}
void Parse::array_store_check() {
  Node *obj = peek(0);
  Node *idx = peek(1);
  Node *ary = peek(2);
  if (_gvn.type(obj) == TypePtr::NULL_PTR) {
    return;
  }
  int klass_offset = oopDesc::klass_offset_in_bytes();
  Node* p = basic_plus_adr( ary, ary, klass_offset );
  Node* array_klass = _gvn.transform(LoadKlassNode::make(_gvn, NULL, immutable_memory(), p, TypeInstPtr::KLASS));
  const TypeKlassPtr *tak = _gvn.type(array_klass)->is_klassptr();
  bool always_see_exact_class = false;
  if (MonomorphicArrayCheck
      && !too_many_traps(Deoptimization::Reason_array_check)
      && !tak->klass_is_exact()
      && tak != TypeKlassPtr::OBJECT) {
    always_see_exact_class = true;
    const TypeKlassPtr *extak = tak->cast_to_exactness(true)->is_klassptr();
    Node* con = makecon(extak);
    Node* cmp = _gvn.transform(new (C) CmpPNode( array_klass, con ));
    Node* bol = _gvn.transform(new (C) BoolNode( cmp, BoolTest::eq ));
    Node* ctrl= control();
    { BuildCutout unless(this, bol, PROB_MAX);
      uncommon_trap(Deoptimization::Reason_array_check,
                    Deoptimization::Action_maybe_recompile,
                    tak->klass());
    }
    if (stopped()) {          // MUST uncommon-trap?
      set_control(ctrl);      // Then Don't Do It, just fall into the normal checking
    } else {                  // Cast array klass to exactness:
      replace_in_map(array_klass,con);
      CompileLog* log = C->log();
      if (log != NULL) {
        log->elem("cast_up reason='monomorphic_array' from='%d' to='(exact)'",
                  log->identify(tak->klass()));
      }
      array_klass = con;      // Use cast value moving forward
    }
  }
  int element_klass_offset = in_bytes(ObjArrayKlass::element_klass_offset());
  Node *p2 = basic_plus_adr(array_klass, array_klass, element_klass_offset);
  Node* a_e_klass = _gvn.transform(LoadKlassNode::make(_gvn, always_see_exact_class ? control() : NULL,
                                                       immutable_memory(), p2, tak));
  gen_checkcast(obj, a_e_klass);
}
void Parse::emit_guard_for_new(ciInstanceKlass* klass) {
  Node* cur_thread = _gvn.transform( new (C) ThreadLocalNode() );
  Node* merge = new (C) RegionNode(3);
  _gvn.set_type(merge, Type::CONTROL);
  Node* kls = makecon(TypeKlassPtr::make(klass));
  Node* init_thread_offset = _gvn.MakeConX(in_bytes(InstanceKlass::init_thread_offset()));
  Node* adr_node = basic_plus_adr(kls, kls, init_thread_offset);
  Node* init_thread = make_load(NULL, adr_node, TypeRawPtr::BOTTOM, T_ADDRESS, MemNode::unordered);
  Node *tst   = Bool( CmpP( init_thread, cur_thread), BoolTest::eq);
  IfNode* iff = create_and_map_if(control(), tst, PROB_ALWAYS, COUNT_UNKNOWN);
  set_control(IfTrue(iff));
  merge->set_req(1, IfFalse(iff));
  Node* init_state_offset = _gvn.MakeConX(in_bytes(InstanceKlass::init_state_offset()));
  adr_node = basic_plus_adr(kls, kls, init_state_offset);
  Node* init_state = make_load(NULL, adr_node, TypeInt::UBYTE, T_BOOLEAN, MemNode::unordered);
  Node* being_init = _gvn.intcon(InstanceKlass::being_initialized);
  tst   = Bool( CmpI( init_state, being_init), BoolTest::eq);
  iff = create_and_map_if(control(), tst, PROB_ALWAYS, COUNT_UNKNOWN);
  set_control(IfTrue(iff));
  merge->set_req(2, IfFalse(iff));
  PreserveJVMState pjvms(this);
  record_for_igvn(merge);
  set_control(merge);
  uncommon_trap(Deoptimization::Reason_uninitialized,
                Deoptimization::Action_reinterpret,
                klass);
}
void Parse::do_new() {
  kill_dead_locals();
  bool will_link;
  ciInstanceKlass* klass = iter().get_klass(will_link)->as_instance_klass();
  assert(will_link, "_new: typeflow responsibility");
  if (!klass->is_initialized() && !klass->is_being_initialized() ||
      klass->is_abstract() || klass->is_interface() ||
      klass->name() == ciSymbol::java_lang_Class() ||
      iter().is_unresolved_klass()) {
    uncommon_trap(Deoptimization::Reason_uninitialized,
                  Deoptimization::Action_reinterpret,
                  klass);
    return;
  }
  if (klass->is_being_initialized()) {
    emit_guard_for_new(klass);
  }
  Node* kls = makecon(TypeKlassPtr::make(klass));
  Node* obj = new_instance(kls);
  push(obj);
  if (OptimizeStringConcat &&
      (klass == C->env()->StringBuilder_klass() ||
       klass == C->env()->StringBuffer_klass())) {
    C->set_has_stringbuilder(true);
  }
  if (C->eliminate_boxing() && klass->is_box_klass()) {
    C->set_has_boxed_value(true);
  }
}
#ifndef PRODUCT
void Parse::dump_map_adr_mem() const {
  tty->print_cr("--- Mapping from address types to memory Nodes ---");
  MergeMemNode *mem = map() == NULL ? NULL : (map()->memory()->is_MergeMem() ?
                                      map()->memory()->as_MergeMem() : NULL);
  for (uint i = 0; i < (uint)C->num_alias_types(); i++) {
    C->alias_type(i)->print_on(tty);
    tty->print("\t");
    if (mem && i < mem->req() && mem->in(i) && mem->in(i) != mem->empty_memory()) {
      mem->in(i)->dump();
    } else {
      tty->cr();
    }
  }
}
#endif
void Parse::test_counter_against_threshold(Node* cnt, int limit) {
  Node *threshold = makecon(TypeInt::make(limit));
  Node *chk   = _gvn.transform( new (C) CmpUNode( cnt, threshold) );
  BoolTest::mask btest = BoolTest::lt;
  Node *tst   = _gvn.transform( new (C) BoolNode( chk, btest) );
  { BuildCutout unless(this, tst, PROB_ALWAYS);
    uncommon_trap(Deoptimization::Reason_age,
                  Deoptimization::Action_maybe_recompile);
  }
}
void Parse::increment_and_test_invocation_counter(int limit) {
  if (!count_invocations()) return;
  ciMethod* m = method();
  MethodCounters* counters_adr = m->ensure_method_counters();
  if (counters_adr == NULL) {
    C->record_failure("method counters allocation failed");
    return;
  }
  Node* ctrl = control();
  const TypePtr* adr_type = TypeRawPtr::make((address) counters_adr);
  Node *counters_node = makecon(adr_type);
  Node* adr_iic_node = basic_plus_adr(counters_node, counters_node,
    MethodCounters::interpreter_invocation_counter_offset_in_bytes());
  Node* cnt = make_load(ctrl, adr_iic_node, TypeInt::INT, T_INT, adr_type, MemNode::unordered);
  test_counter_against_threshold(cnt, limit);
  Node* incr = _gvn.transform(new (C) AddINode(cnt, _gvn.intcon(1)));
  store_to_memory(ctrl, adr_iic_node, incr, T_INT, adr_type, MemNode::unordered);
}
Node* Parse::method_data_addressing(ciMethodData* md, ciProfileData* data, ByteSize counter_offset, Node* idx, uint stride) {
  ByteSize data_offset = MethodData::data_offset();
  int cell_offset = md->dp_to_di(data->dp());
  int offset = in_bytes(data_offset) + cell_offset + in_bytes(counter_offset);
  const TypePtr* adr_type = TypeMetadataPtr::make(md);
  Node* mdo = makecon(adr_type);
  Node* ptr = basic_plus_adr(mdo, mdo, offset);
  if (stride != 0) {
    Node* str = _gvn.MakeConX(stride);
    Node* scale = _gvn.transform( new (C) MulXNode( idx, str ) );
    ptr   = _gvn.transform( new (C) AddPNode( mdo, ptr, scale ) );
  }
  return ptr;
}
void Parse::increment_md_counter_at(ciMethodData* md, ciProfileData* data, ByteSize counter_offset, Node* idx, uint stride) {
  Node* adr_node = method_data_addressing(md, data, counter_offset, idx, stride);
  const TypePtr* adr_type = _gvn.type(adr_node)->is_ptr();
  Node* cnt  = make_load(NULL, adr_node, TypeInt::INT, T_INT, adr_type, MemNode::unordered);
  Node* incr = _gvn.transform(new (C) AddINode(cnt, _gvn.intcon(DataLayout::counter_increment)));
  store_to_memory(NULL, adr_node, incr, T_INT, adr_type, MemNode::unordered);
}
void Parse::test_for_osr_md_counter_at(ciMethodData* md, ciProfileData* data, ByteSize counter_offset, int limit) {
  Node* adr_node = method_data_addressing(md, data, counter_offset);
  const TypePtr* adr_type = _gvn.type(adr_node)->is_ptr();
  Node* cnt  = make_load(NULL, adr_node, TypeInt::INT, T_INT, adr_type, MemNode::unordered);
  test_counter_against_threshold(cnt, limit);
}
void Parse::set_md_flag_at(ciMethodData* md, ciProfileData* data, int flag_constant) {
  Node* adr_node = method_data_addressing(md, data, DataLayout::flags_offset());
  const TypePtr* adr_type = _gvn.type(adr_node)->is_ptr();
  Node* flags = make_load(NULL, adr_node, TypeInt::BYTE, T_BYTE, adr_type, MemNode::unordered);
  Node* incr = _gvn.transform(new (C) OrINode(flags, _gvn.intcon(flag_constant)));
  store_to_memory(NULL, adr_node, incr, T_BYTE, adr_type, MemNode::unordered);
}
void Parse::profile_taken_branch(int target_bci, bool force_update) {
  int cur_bci = bci();
  bool osr_site =
    (target_bci <= cur_bci) && count_invocations() && UseOnStackReplacement;
  set_bci(target_bci);
  if (method_data_update() || force_update) {
    ciMethodData* md = method()->method_data();
    assert(md != NULL, "expected valid ciMethodData");
    ciProfileData* data = md->bci_to_data(cur_bci);
    assert(data->is_JumpData(), "need JumpData for taken branch");
    increment_md_counter_at(md, data, JumpData::taken_offset());
  }
#ifndef TIERED
  if (method_data_update()) {
    ciMethodData* md = method()->method_data();
    if (osr_site) {
      ciProfileData* data = md->bci_to_data(cur_bci);
      int limit = (CompileThreshold
      test_for_osr_md_counter_at(md, data, JumpData::taken_offset(), limit);
    }
  } else {
    if (osr_site) {
      int limit = (CompileThreshold * OnStackReplacePercentage) / 100;
      increment_and_test_invocation_counter(limit);
    }
  }
#endif // TIERED
  set_bci(cur_bci);
}
void Parse::profile_not_taken_branch(bool force_update) {
  if (method_data_update() || force_update) {
    ciMethodData* md = method()->method_data();
    assert(md != NULL, "expected valid ciMethodData");
    ciProfileData* data = md->bci_to_data(bci());
    assert(data->is_BranchData(), "need BranchData for not taken branch");
    increment_md_counter_at(md, data, BranchData::not_taken_offset());
  }
}
void Parse::profile_call(Node* receiver) {
  if (!method_data_update()) return;
  switch (bc()) {
  case Bytecodes::_invokevirtual:
  case Bytecodes::_invokeinterface:
    profile_receiver_type(receiver);
    break;
  case Bytecodes::_invokestatic:
  case Bytecodes::_invokedynamic:
  case Bytecodes::_invokespecial:
    profile_generic_call();
    break;
  default: fatal("unexpected call bytecode");
  }
}
void Parse::profile_generic_call() {
  assert(method_data_update(), "must be generating profile code");
  ciMethodData* md = method()->method_data();
  assert(md != NULL, "expected valid ciMethodData");
  ciProfileData* data = md->bci_to_data(bci());
  assert(data->is_CounterData(), "need CounterData for not taken branch");
  increment_md_counter_at(md, data, CounterData::count_offset());
}
void Parse::profile_receiver_type(Node* receiver) {
  assert(method_data_update(), "must be generating profile code");
  ciMethodData* md = method()->method_data();
  assert(md != NULL, "expected valid ciMethodData");
  ciProfileData* data = md->bci_to_data(bci());
  assert(data->is_ReceiverTypeData(), "need ReceiverTypeData here");
  if (TypeProfileWidth < 1) {
    increment_md_counter_at(md, data, CounterData::count_offset());
    return;
  }
  ciReceiverTypeData* rdata = (ciReceiverTypeData*)data->as_ReceiverTypeData();
  Node* method_data = method_data_addressing(md, rdata, in_ByteSize(0));
  make_runtime_call(RC_LEAF, OptoRuntime::profile_receiver_type_Type(),
                    CAST_FROM_FN_PTR(address,
                                     OptoRuntime::profile_receiver_type_C),
                    "profile_receiver_type_C",
                    TypePtr::BOTTOM,
                    method_data, receiver);
}
void Parse::profile_ret(int target_bci) {
  if (!method_data_update()) return;
  if (TypeProfileWidth < 1) return;
  ciMethodData* md = method()->method_data();
  assert(md != NULL, "expected valid ciMethodData");
  ciProfileData* data = md->bci_to_data(bci());
  assert(data->is_RetData(), "need RetData for ret");
  ciRetData* ret_data = (ciRetData*)data->as_RetData();
  uint row;
  bool table_full = true;
  for (row = 0; row < ret_data->row_limit(); row++) {
    int key = ret_data->bci(row);
    table_full &= (key != RetData::no_bci);
    if (key == target_bci) break;
  }
  if (row >= ret_data->row_limit()) {
    if (!table_full) {
    }
    return;
  }
  increment_md_counter_at(md, data, RetData::bci_count_offset(row));
}
void Parse::profile_null_checkcast() {
  if (!method_data_update()) return;
  ciMethodData* md = method()->method_data();
  assert(md != NULL, "expected valid ciMethodData");
  ciProfileData* data = md->bci_to_data(bci());
  assert(data->is_BitData(), "need BitData for checkcast");
  set_md_flag_at(md, data, BitData::null_seen_byte_constant());
}
void Parse::profile_switch_case(int table_index) {
  if (!method_data_update()) return;
  ciMethodData* md = method()->method_data();
  assert(md != NULL, "expected valid ciMethodData");
  ciProfileData* data = md->bci_to_data(bci());
  assert(data->is_MultiBranchData(), "need MultiBranchData for switch case");
  if (table_index >= 0) {
    increment_md_counter_at(md, data, MultiBranchData::case_count_offset(table_index));
  } else {
    increment_md_counter_at(md, data, MultiBranchData::default_count_offset());
  }
}
C:\hotspot-69087d08d473\src\share\vm/opto/phase.cpp
#include "precompiled.hpp"
#include "code/nmethod.hpp"
#include "compiler/compileBroker.hpp"
#include "opto/compile.hpp"
#include "opto/matcher.hpp"
#include "opto/node.hpp"
#include "opto/phase.hpp"
#ifndef PRODUCT
int Phase::_total_bytes_compiled = 0;
elapsedTimer Phase::_t_totalCompilation;
elapsedTimer Phase::_t_methodCompilation;
elapsedTimer Phase::_t_stubCompilation;
#endif
elapsedTimer Phase::_t_parser;
elapsedTimer Phase::_t_optimizer;
elapsedTimer   Phase::_t_escapeAnalysis;
elapsedTimer     Phase::_t_connectionGraph;
elapsedTimer   Phase::_t_idealLoop;
elapsedTimer   Phase::_t_ccp;
elapsedTimer Phase::_t_matcher;
elapsedTimer Phase::_t_registerAllocation;
elapsedTimer Phase::_t_output;
#ifndef PRODUCT
elapsedTimer Phase::_t_graphReshaping;
elapsedTimer Phase::_t_scheduler;
elapsedTimer Phase::_t_blockOrdering;
elapsedTimer Phase::_t_macroEliminate;
elapsedTimer Phase::_t_macroExpand;
elapsedTimer Phase::_t_peephole;
elapsedTimer Phase::_t_postalloc_expand;
elapsedTimer Phase::_t_codeGeneration;
elapsedTimer Phase::_t_registerMethod;
elapsedTimer Phase::_t_temporaryTimer1;
elapsedTimer Phase::_t_temporaryTimer2;
elapsedTimer Phase::_t_idealLoopVerify;
elapsedTimer   Phase::_t_iterGVN;
elapsedTimer   Phase::_t_iterGVN2;
elapsedTimer   Phase::_t_incrInline;
elapsedTimer   Phase::_t_renumberLive;
elapsedTimer   Phase::_t_ctorChaitin;
elapsedTimer   Phase::_t_buildIFGphysical;
elapsedTimer   Phase::_t_computeLive;
elapsedTimer   Phase::_t_regAllocSplit;
elapsedTimer   Phase::_t_postAllocCopyRemoval;
elapsedTimer   Phase::_t_mergeMultidefs;
elapsedTimer   Phase::_t_fixupSpills;
elapsedTimer   Phase::_t_instrSched;
elapsedTimer   Phase::_t_buildOopMaps;
#endif
Phase::Phase( PhaseNumber pnum ) : _pnum(pnum), C( pnum == Compiler ? NULL : Compile::current()) {
  CompileBroker::maybe_block();
}
#ifndef PRODUCT
static const double minimum_reported_time             = 0.0001; // seconds
static const double expected_method_compile_coverage  = 0.97;   // %
static const double minimum_meaningful_method_compile = 2.00;   // seconds
void Phase::print_timers() {
  tty->print_cr ("Accumulated compiler times:");
  tty->print_cr ("---------------------------");
  tty->print_cr ("  Total compilation: %3.3f sec.", Phase::_t_totalCompilation.seconds());
  tty->print    ("    method compilation   : %3.3f sec", Phase::_t_methodCompilation.seconds());
  tty->print    ("/%d bytes",_total_bytes_compiled);
  tty->print_cr (" (%3.0f bytes per sec) ", Phase::_total_bytes_compiled / Phase::_t_methodCompilation.seconds());
  tty->print_cr ("    stub compilation     : %3.3f sec.", Phase::_t_stubCompilation.seconds());
  tty->print_cr ("  Phases:");
  tty->print_cr ("    parse          : %3.3f sec", Phase::_t_parser.seconds());
  tty->print_cr ("    optimizer      : %3.3f sec", Phase::_t_optimizer.seconds());
  if( Verbose || WizardMode ) {
    if (DoEscapeAnalysis) {
      tty->print_cr ("      escape analysis: %3.3f sec", Phase::_t_escapeAnalysis.seconds());
      tty->print_cr ("        connection graph: %3.3f sec", Phase::_t_connectionGraph.seconds());
      tty->print_cr ("      macroEliminate : %3.3f sec", Phase::_t_macroEliminate.seconds());
    }
    tty->print_cr ("      iterGVN        : %3.3f sec", Phase::_t_iterGVN.seconds());
    tty->print_cr ("      incrInline     : %3.3f sec", Phase::_t_incrInline.seconds());
    tty->print_cr ("      renumberLive   : %3.3f sec", Phase::_t_renumberLive.seconds());
    tty->print_cr ("      idealLoop      : %3.3f sec", Phase::_t_idealLoop.seconds());
    tty->print_cr ("      idealLoopVerify: %3.3f sec", Phase::_t_idealLoopVerify.seconds());
    tty->print_cr ("      ccp            : %3.3f sec", Phase::_t_ccp.seconds());
    tty->print_cr ("      iterGVN2       : %3.3f sec", Phase::_t_iterGVN2.seconds());
    tty->print_cr ("      macroExpand    : %3.3f sec", Phase::_t_macroExpand.seconds());
    tty->print_cr ("      graphReshape   : %3.3f sec", Phase::_t_graphReshaping.seconds());
    double optimizer_subtotal = Phase::_t_iterGVN.seconds() + Phase::_t_iterGVN2.seconds() + Phase::_t_renumberLive.seconds() +
      Phase::_t_escapeAnalysis.seconds() + Phase::_t_macroEliminate.seconds() +
      Phase::_t_idealLoop.seconds() + Phase::_t_ccp.seconds() +
      Phase::_t_macroExpand.seconds() + Phase::_t_graphReshaping.seconds();
    double percent_of_optimizer = ((optimizer_subtotal == 0.0) ? 0.0 : (optimizer_subtotal / Phase::_t_optimizer.seconds() * 100.0));
    tty->print_cr ("      subtotal       : %3.3f sec,  %3.2f %%", optimizer_subtotal, percent_of_optimizer);
  }
  tty->print_cr ("    matcher        : %3.3f sec", Phase::_t_matcher.seconds());
  tty->print_cr ("    scheduler      : %3.3f sec", Phase::_t_scheduler.seconds());
  tty->print_cr ("    regalloc       : %3.3f sec", Phase::_t_registerAllocation.seconds());
  if( Verbose || WizardMode ) {
    tty->print_cr ("      ctorChaitin    : %3.3f sec", Phase::_t_ctorChaitin.seconds());
    tty->print_cr ("      buildIFG       : %3.3f sec", Phase::_t_buildIFGphysical.seconds());
    tty->print_cr ("      computeLive    : %3.3f sec", Phase::_t_computeLive.seconds());
    tty->print_cr ("      regAllocSplit  : %3.3f sec", Phase::_t_regAllocSplit.seconds());
    tty->print_cr ("      postAllocCopyRemoval: %3.3f sec", Phase::_t_postAllocCopyRemoval.seconds());
    tty->print_cr ("      mergeMultidefs: %3.3f sec", Phase::_t_mergeMultidefs.seconds());
    tty->print_cr ("      fixupSpills    : %3.3f sec", Phase::_t_fixupSpills.seconds());
    double regalloc_subtotal = Phase::_t_ctorChaitin.seconds() +
      Phase::_t_buildIFGphysical.seconds() + Phase::_t_computeLive.seconds() +
      Phase::_t_regAllocSplit.seconds()    + Phase::_t_fixupSpills.seconds() +
      Phase::_t_postAllocCopyRemoval.seconds() + Phase::_t_mergeMultidefs.seconds();
    double percent_of_regalloc = ((regalloc_subtotal == 0.0) ? 0.0 : (regalloc_subtotal / Phase::_t_registerAllocation.seconds() * 100.0));
    tty->print_cr ("      subtotal       : %3.3f sec,  %3.2f %%", regalloc_subtotal, percent_of_regalloc);
  }
  tty->print_cr ("    blockOrdering  : %3.3f sec", Phase::_t_blockOrdering.seconds());
  tty->print_cr ("    peephole       : %3.3f sec", Phase::_t_peephole.seconds());
  if (Matcher::require_postalloc_expand) {
    tty->print_cr ("    postalloc_expand: %3.3f sec", Phase::_t_postalloc_expand.seconds());
  }
  tty->print_cr ("    codeGen        : %3.3f sec", Phase::_t_codeGeneration.seconds());
  tty->print_cr ("    install_code   : %3.3f sec", Phase::_t_registerMethod.seconds());
  tty->print_cr ("    -------------- : ----------");
  double phase_subtotal = Phase::_t_parser.seconds() +
    Phase::_t_optimizer.seconds() + Phase::_t_graphReshaping.seconds() +
    Phase::_t_matcher.seconds() + Phase::_t_scheduler.seconds() +
    Phase::_t_registerAllocation.seconds() + Phase::_t_blockOrdering.seconds() +
    Phase::_t_codeGeneration.seconds() + Phase::_t_registerMethod.seconds();
  double percent_of_method_compile = ((phase_subtotal == 0.0) ? 0.0 : phase_subtotal / Phase::_t_methodCompilation.seconds()) * 100.0;
  tty->print_cr ("    total          : %3.3f sec,  %3.2f %%", phase_subtotal, percent_of_method_compile);
  assert( percent_of_method_compile > expected_method_compile_coverage ||
          phase_subtotal < minimum_meaningful_method_compile,
          "Must account for method compilation");
  if( Phase::_t_temporaryTimer1.seconds() > minimum_reported_time ) {
    tty->cr();
    tty->print_cr ("    temporaryTimer1: %3.3f sec", Phase::_t_temporaryTimer1.seconds());
  }
  if( Phase::_t_temporaryTimer2.seconds() > minimum_reported_time ) {
    tty->cr();
    tty->print_cr ("    temporaryTimer2: %3.3f sec", Phase::_t_temporaryTimer2.seconds());
  }
  tty->print_cr ("    output         : %3.3f sec", Phase::_t_output.seconds());
  tty->print_cr ("      isched         : %3.3f sec", Phase::_t_instrSched.seconds());
  tty->print_cr ("      bldOopMaps     : %3.3f sec", Phase::_t_buildOopMaps.seconds());
}
#endif
C:\hotspot-69087d08d473\src\share\vm/opto/phase.hpp
#ifndef SHARE_VM_OPTO_PHASE_HPP
#define SHARE_VM_OPTO_PHASE_HPP
#include "libadt/port.hpp"
#include "runtime/timer.hpp"
class Compile;
class Phase : public StackObj {
public:
  enum PhaseNumber {
    Compiler,                         // Top-level compiler phase
    Parser,                           // Parse bytecodes
    Remove_Useless,                   // Remove useless nodes
    Remove_Useless_And_Renumber_Live, // First, remove useless nodes from the graph. Then, renumber live nodes.
    Optimistic,                       // Optimistic analysis phase
    GVN,                              // Pessimistic global value numbering phase
    Ins_Select,                       // Instruction selection phase
    CFG,                              // Build a CFG
    BlockLayout,                      // Linear ordering of blocks
    Register_Allocation,              // Register allocation, duh
    LIVE,                             // Dragon-book LIVE range problem
    StringOpts,                       // StringBuilder related optimizations
    Interference_Graph,               // Building the IFG
    Coalesce,                         // Coalescing copies
    Ideal_Loop,                       // Find idealized trip-counted loops
    Macro_Expand,                     // Expand macro nodes
    Peephole,                         // Apply peephole optimizations
    last_phase
  };
protected:
  enum PhaseNumber _pnum;       // Phase number (for stat gathering)
#ifndef PRODUCT
  static int _total_bytes_compiled;
  static elapsedTimer _t_totalCompilation;
  static elapsedTimer _t_methodCompilation;
  static elapsedTimer _t_stubCompilation;
#endif
  static elapsedTimer _t_parser;
  static elapsedTimer _t_optimizer;
public:
  static elapsedTimer   _t_escapeAnalysis;
  static elapsedTimer     _t_connectionGraph;
protected:
  static elapsedTimer   _t_idealLoop;
  static elapsedTimer   _t_ccp;
  static elapsedTimer _t_matcher;
  static elapsedTimer _t_registerAllocation;
  static elapsedTimer _t_output;
#ifndef PRODUCT
  static elapsedTimer _t_graphReshaping;
  static elapsedTimer _t_scheduler;
  static elapsedTimer _t_blockOrdering;
  static elapsedTimer _t_macroEliminate;
  static elapsedTimer _t_macroExpand;
  static elapsedTimer _t_peephole;
  static elapsedTimer _t_postalloc_expand;
  static elapsedTimer _t_codeGeneration;
  static elapsedTimer _t_registerMethod;
  static elapsedTimer _t_temporaryTimer1;
  static elapsedTimer _t_temporaryTimer2;
  static elapsedTimer _t_idealLoopVerify;
  static elapsedTimer   _t_iterGVN;
  static elapsedTimer   _t_iterGVN2;
  static elapsedTimer   _t_incrInline;
  static elapsedTimer   _t_renumberLive;
  static elapsedTimer   _t_ctorChaitin;
  static elapsedTimer   _t_buildIFGphysical;
  static elapsedTimer   _t_computeLive;
  static elapsedTimer   _t_regAllocSplit;
  static elapsedTimer   _t_postAllocCopyRemoval;
  static elapsedTimer   _t_mergeMultidefs;
  static elapsedTimer   _t_fixupSpills;
  static elapsedTimer   _t_instrSched;
  static elapsedTimer   _t_buildOopMaps;
#endif
public:
  Compile * C;
  Phase( PhaseNumber pnum );
#ifndef PRODUCT
  static void print_timers();
#endif
};
#endif // SHARE_VM_OPTO_PHASE_HPP
C:\hotspot-69087d08d473\src\share\vm/opto/phasetype.hpp
#ifndef SHARE_VM_OPTO_PHASETYPE_HPP
#define SHARE_VM_OPTO_PHASETYPE_HPP
enum CompilerPhaseType {
  PHASE_BEFORE_STRINGOPTS,
  PHASE_AFTER_STRINGOPTS,
  PHASE_BEFORE_REMOVEUSELESS,
  PHASE_AFTER_PARSING,
  PHASE_ITER_GVN1,
  PHASE_PHASEIDEAL_BEFORE_EA,
  PHASE_ITER_GVN_AFTER_EA,
  PHASE_ITER_GVN_AFTER_ELIMINATION,
  PHASE_PHASEIDEALLOOP1,
  PHASE_PHASEIDEALLOOP2,
  PHASE_PHASEIDEALLOOP3,
  PHASE_CPP1,
  PHASE_ITER_GVN2,
  PHASE_PHASEIDEALLOOP_ITERATIONS,
  PHASE_OPTIMIZE_FINISHED,
  PHASE_GLOBAL_CODE_MOTION,
  PHASE_FINAL_CODE,
  PHASE_AFTER_EA,
  PHASE_BEFORE_CLOOPS,
  PHASE_AFTER_CLOOPS,
  PHASE_BEFORE_BEAUTIFY_LOOPS,
  PHASE_AFTER_BEAUTIFY_LOOPS,
  PHASE_BEFORE_MATCHING,
  PHASE_INCREMENTAL_INLINE,
  PHASE_INCREMENTAL_BOXING_INLINE,
  PHASE_END,
  PHASE_FAILURE,
  PHASE_NUM_TYPES
};
class CompilerPhaseTypeHelper {
  public:
  static const char* to_string(CompilerPhaseType cpt) {
    switch (cpt) {
      case PHASE_BEFORE_STRINGOPTS:          return "Before StringOpts";
      case PHASE_AFTER_STRINGOPTS:           return "After StringOpts";
      case PHASE_BEFORE_REMOVEUSELESS:       return "Before RemoveUseless";
      case PHASE_AFTER_PARSING:              return "After Parsing";
      case PHASE_ITER_GVN1:                  return "Iter GVN 1";
      case PHASE_PHASEIDEAL_BEFORE_EA:       return "PhaseIdealLoop before EA";
      case PHASE_ITER_GVN_AFTER_EA:          return "Iter GVN after EA";
      case PHASE_ITER_GVN_AFTER_ELIMINATION: return "Iter GVN after eliminating allocations and locks";
      case PHASE_PHASEIDEALLOOP1:            return "PhaseIdealLoop 1";
      case PHASE_PHASEIDEALLOOP2:            return "PhaseIdealLoop 2";
      case PHASE_PHASEIDEALLOOP3:            return "PhaseIdealLoop 3";
      case PHASE_CPP1:                       return "PhaseCPP 1";
      case PHASE_ITER_GVN2:                  return "Iter GVN 2";
      case PHASE_PHASEIDEALLOOP_ITERATIONS:  return "PhaseIdealLoop iterations";
      case PHASE_OPTIMIZE_FINISHED:          return "Optimize finished";
      case PHASE_GLOBAL_CODE_MOTION:         return "Global code motion";
      case PHASE_FINAL_CODE:                 return "Final Code";
      case PHASE_AFTER_EA:                   return "After Escape Analysis";
      case PHASE_BEFORE_CLOOPS:              return "Before CountedLoop";
      case PHASE_AFTER_CLOOPS:               return "After CountedLoop";
      case PHASE_BEFORE_BEAUTIFY_LOOPS:      return "Before beautify loops";
      case PHASE_AFTER_BEAUTIFY_LOOPS:       return "After beautify loops";
      case PHASE_BEFORE_MATCHING:            return "Before Matching";
      case PHASE_INCREMENTAL_INLINE:         return "Incremental Inline";
      case PHASE_INCREMENTAL_BOXING_INLINE:  return "Incremental Boxing Inline";
      case PHASE_END:                        return "End";
      case PHASE_FAILURE:                    return "Failure";
      default:
        ShouldNotReachHere();
        return NULL;
    }
  }
};
#endif //SHARE_VM_OPTO_PHASETYPE_HPP
C:\hotspot-69087d08d473\src\share\vm/opto/phaseX.cpp
#include "precompiled.hpp"
#include "memory/allocation.inline.hpp"
#include "opto/block.hpp"
#include "opto/callnode.hpp"
#include "opto/cfgnode.hpp"
#include "opto/connode.hpp"
#include "opto/idealGraphPrinter.hpp"
#include "opto/loopnode.hpp"
#include "opto/machnode.hpp"
#include "opto/opcodes.hpp"
#include "opto/phaseX.hpp"
#include "opto/regalloc.hpp"
#include "opto/rootnode.hpp"
#define NODE_HASH_MINIMUM_SIZE    255
NodeHash::NodeHash(uint est_max_size) :
  _max( round_up(est_max_size < NODE_HASH_MINIMUM_SIZE ? NODE_HASH_MINIMUM_SIZE : est_max_size) ),
  _a(Thread::current()->resource_area()),
  _table( NEW_ARENA_ARRAY( _a , Node* , _max ) ), // (Node**)_a->Amalloc(_max * sizeof(Node*)) ),
  _inserts(0), _insert_limit( insert_limit() ),
  _look_probes(0), _lookup_hits(0), _lookup_misses(0),
  _total_insert_probes(0), _total_inserts(0),
  _insert_probes(0), _grows(0) {
  _sentinel = new (Compile::current()) ProjNode(NULL, TypeFunc::Control);
  memset(_table,0,sizeof(Node*)*_max);
}
NodeHash::NodeHash(Arena *arena, uint est_max_size) :
  _max( round_up(est_max_size < NODE_HASH_MINIMUM_SIZE ? NODE_HASH_MINIMUM_SIZE : est_max_size) ),
  _a(arena),
  _table( NEW_ARENA_ARRAY( _a , Node* , _max ) ),
  _inserts(0), _insert_limit( insert_limit() ),
  _look_probes(0), _lookup_hits(0), _lookup_misses(0),
  _delete_probes(0), _delete_hits(0), _delete_misses(0),
  _total_insert_probes(0), _total_inserts(0),
  _insert_probes(0), _grows(0) {
  _sentinel = new (Compile::current()) ProjNode(NULL, TypeFunc::Control);
  memset(_table,0,sizeof(Node*)*_max);
}
NodeHash::NodeHash(NodeHash *nh) {
  debug_only(_table = (Node**)badAddress);   // interact correctly w/ operator=
}
void NodeHash::replace_with(NodeHash *nh) {
  debug_only(_table = (Node**)badAddress);   // interact correctly w/ operator=
}
Node *NodeHash::hash_find( const Node *n ) {
  uint hash = n->hash();
  if (hash == Node::NO_HASH) {
    debug_only( _lookup_misses++ );
    return NULL;
  }
  uint key = hash & (_max-1);
  uint stride = key | 0x01;
  debug_only( _look_probes++ );
  Node *k = _table[key];        // Get hashed value
  if( !k ) {                    // ?Miss?
    debug_only( _lookup_misses++ );
    return NULL;                // Miss!
  }
  int op = n->Opcode();
  uint req = n->req();
  while( 1 ) {                  // While probing hash table
    if( k->req() == req &&      // Same count of inputs
        k->Opcode() == op ) {   // Same Opcode
      for( uint i=0; i<req; i++ )
        if( n->in(i)!=k->in(i)) // Different inputs?
          goto collision;       // "goto" is a speed hack...
      if( n->cmp(*k) ) {        // Check for any special bits
        debug_only( _lookup_hits++ );
        return k;               // Hit!
      }
    }
  collision:
    debug_only( _look_probes++ );
    key = (key + stride/*7*/) & (_max-1); // Stride through table with relative prime
    k = _table[key];            // Get hashed value
    if( !k ) {                  // ?Miss?
      debug_only( _lookup_misses++ );
      return NULL;              // Miss!
    }
  }
  ShouldNotReachHere();
  return NULL;
}
Node *NodeHash::hash_find_insert( Node *n ) {
  uint hash = n->hash();
  if (hash == Node::NO_HASH) {
    debug_only( _lookup_misses++ );
    return NULL;
  }
  uint key = hash & (_max-1);
  uint stride = key | 0x01;     // stride must be relatively prime to table siz
  uint first_sentinel = 0;      // replace a sentinel if seen.
  debug_only( _look_probes++ );
  Node *k = _table[key];        // Get hashed value
  if( !k ) {                    // ?Miss?
    debug_only( _lookup_misses++ );
    _table[key] = n;            // Insert into table!
    debug_only(n->enter_hash_lock()); // Lock down the node while in the table.
    check_grow();               // Grow table if insert hit limit
    return NULL;                // Miss!
  }
  else if( k == _sentinel ) {
    first_sentinel = key;      // Can insert here
  }
  int op = n->Opcode();
  uint req = n->req();
  while( 1 ) {                  // While probing hash table
    if( k->req() == req &&      // Same count of inputs
        k->Opcode() == op ) {   // Same Opcode
      for( uint i=0; i<req; i++ )
        if( n->in(i)!=k->in(i)) // Different inputs?
          goto collision;       // "goto" is a speed hack...
      if( n->cmp(*k) ) {        // Check for any special bits
        debug_only( _lookup_hits++ );
        return k;               // Hit!
      }
    }
  collision:
    debug_only( _look_probes++ );
    key = (key + stride) & (_max-1); // Stride through table w/ relative prime
    k = _table[key];            // Get hashed value
    if( !k ) {                  // ?Miss?
      debug_only( _lookup_misses++ );
      key = (first_sentinel == 0) ? key : first_sentinel; // ?saw sentinel?
      _table[key] = n;          // Insert into table!
      debug_only(n->enter_hash_lock()); // Lock down the node while in the table.
      check_grow();             // Grow table if insert hit limit
      return NULL;              // Miss!
    }
    else if( first_sentinel == 0 && k == _sentinel ) {
      first_sentinel = key;    // Can insert here
    }
  }
  ShouldNotReachHere();
  return NULL;
}
void NodeHash::hash_insert( Node *n ) {
  uint hash = n->hash();
  if (hash == Node::NO_HASH) {
    return;
  }
  check_grow();
  uint key = hash & (_max-1);
  uint stride = key | 0x01;
  while( 1 ) {                  // While probing hash table
    debug_only( _insert_probes++ );
    Node *k = _table[key];      // Get hashed value
    if( !k || (k == _sentinel) ) break;       // Found a slot
    assert( k != n, "already inserted" );
    key = (key + stride) & (_max-1); // Stride through table w/ relative prime
  }
  _table[key] = n;              // Insert into table!
  debug_only(n->enter_hash_lock()); // Lock down the node while in the table.
}
bool NodeHash::hash_delete( const Node *n ) {
  Node *k;
  uint hash = n->hash();
  if (hash == Node::NO_HASH) {
    debug_only( _delete_misses++ );
    return false;
  }
  uint key = hash & (_max-1);
  uint stride = key | 0x01;
  debug_only( uint counter = 0; );
  for( ; /* (k != NULL) && (k != _sentinel) */; ) {
    debug_only( counter++ );
    debug_only( _delete_probes++ );
    k = _table[key];            // Get hashed value
    if( !k ) {                  // Miss?
      debug_only( _delete_misses++ );
#ifdef ASSERT
      if( VerifyOpto ) {
        for( uint i=0; i < _max; i++ )
          assert( _table[i] != n, "changed edges with rehashing" );
      }
#endif
      return false;             // Miss! Not in chain
    }
    else if( n == k ) {
      debug_only( _delete_hits++ );
      _table[key] = _sentinel;  // Hit! Label as deleted entry
      debug_only(((Node*)n)->exit_hash_lock()); // Unlock the node upon removal from table.
      return true;
    }
    else {
      key = (key + stride/*7*/) & (_max-1);
      assert( counter <= _insert_limit, "Cycle in hash-table");
    }
  }
  ShouldNotReachHere();
  return false;
}
uint NodeHash::round_up( uint x ) {
  x += (x>>2);                  // Add 25% slop
  if( x <16 ) return 16;        // Small stuff
  uint i=16;
  while( i < x ) i <<= 1;       // Double to fit
  return i;                     // Return hash table size
}
void  NodeHash::grow() {
  uint   old_max   = _max;
  Node **old_table = _table;
  _grows++;
  _total_inserts       += _inserts;
  _total_insert_probes += _insert_probes;
  _inserts         = 0;
  _insert_probes   = 0;
  _max     = _max << 1;
  _table   = NEW_ARENA_ARRAY( _a , Node* , _max ); // (Node**)_a->Amalloc( _max * sizeof(Node*) );
  memset(_table,0,sizeof(Node*)*_max);
  _insert_limit = insert_limit();
  for( uint i = 0; i < old_max; i++ ) {
    Node *m = *old_table++;
    if( !m || m == _sentinel ) continue;
    debug_only(m->exit_hash_lock()); // Unlock the node upon removal from old table.
    hash_insert(m);
  }
}
void  NodeHash::clear() {
#ifdef ASSERT
  for (uint i = 0; i < _max; i++) {
    Node* n = _table[i];
    if (!n || n == _sentinel)  continue;
    n->exit_hash_lock();
  }
#endif
  memset( _table, 0, _max * sizeof(Node*) );
}
void NodeHash::remove_useless_nodes(VectorSet &useful) {
  uint max = size();
  Node *sentinel_node = sentinel();
  for( uint i = 0; i < max; ++i ) {
    Node *n = at(i);
    if(n != NULL && n != sentinel_node && !useful.test(n->_idx)) {
      debug_only(n->exit_hash_lock()); // Unlock the node when removed
      _table[i] = sentinel_node;       // Replace with placeholder
    }
  }
}
void NodeHash::check_no_speculative_types() {
#ifdef ASSERT
  uint max = size();
  Node *sentinel_node = sentinel();
  for (uint i = 0; i < max; ++i) {
    Node *n = at(i);
    if(n != NULL && n != sentinel_node && n->is_Type()) {
      TypeNode* tn = n->as_Type();
      const Type* t = tn->type();
      const Type* t_no_spec = t->remove_speculative();
      assert(t == t_no_spec, "dead node in hash table or missed node during speculative cleanup");
    }
  }
#endif
}
#ifndef PRODUCT
void NodeHash::dump() {
  _total_inserts       += _inserts;
  _total_insert_probes += _insert_probes;
  if (PrintCompilation && PrintOptoStatistics && Verbose && (_inserts > 0)) {
    if (WizardMode) {
      for (uint i=0; i<_max; i++) {
        if (_table[i])
          tty->print("%d/%d/%d ",i,_table[i]->hash()&(_max-1),_table[i]->_idx);
      }
    }
    tty->print("\nGVN Hash stats:  %d grows to %d max_size\n", _grows, _max);
    tty->print("  %d/%d (%8.1f%% full)\n", _inserts, _max, (double)_inserts/_max*100.0);
    tty->print("  %dp/(%dh+%dm) (%8.2f probes/lookup)\n", _look_probes, _lookup_hits, _lookup_misses, (double)_look_probes/(_lookup_hits+_lookup_misses));
    tty->print("  %dp/%di (%8.2f probes/insert)\n", _total_insert_probes, _total_inserts, (double)_total_insert_probes/_total_inserts);
    assert((_lookup_misses+_lookup_hits)*4+100 >= _look_probes, "bad hash function");
    assert( _inserts+(_inserts>>3) < _max, "table too full" );
    assert( _inserts*3+100 >= _insert_probes, "bad hash function" );
  }
}
Node *NodeHash::find_index(uint idx) { // For debugging
  for( uint i = 0; i < _max; i++ ) {
    Node *m = _table[i];
    if( !m || m == _sentinel ) continue;
    if( m->_idx == (uint)idx ) return m;
  }
  return NULL;
}
#endif
#ifdef ASSERT
NodeHash::~NodeHash() {
  if (_table != (Node**)badAddress)  clear();
}
void NodeHash::operator=(const NodeHash& nh) {
  if (&nh == this)  return;
  if (_table != (Node**)badAddress)  clear();
  memcpy(this, &nh, sizeof(*this));
  ((NodeHash*)&nh)->_table = (Node**)badAddress;
}
#endif
PhaseRemoveUseless::PhaseRemoveUseless(PhaseGVN *gvn, Unique_Node_List *worklist, PhaseNumber phase_num) : Phase(phase_num),
  _useful(Thread::current()->resource_area()) {
  if( !UseLoopSafepoints || !OptoRemoveUseless ) return;
  C->identify_useful_nodes(_useful);
  C->update_dead_node_list(_useful);
  gvn->remove_useless_nodes(_useful.member_set());
  worklist->remove_useless_nodes(_useful.member_set());
  C->remove_useless_nodes(_useful);
}
PhaseRenumberLive::PhaseRenumberLive(PhaseGVN* gvn,
                                     Unique_Node_List* worklist, Unique_Node_List* new_worklist,
                                     PhaseNumber phase_num) :
  PhaseRemoveUseless(gvn, worklist, Remove_Useless_And_Renumber_Live) {
  assert(RenumberLiveNodes, "RenumberLiveNodes must be set to true for node renumbering to take place");
  assert(C->live_nodes() == _useful.size(), "the number of live nodes must match the number of useful nodes");
  assert(gvn->nodes_size() == 0, "GVN must not contain any nodes at this point");
  uint old_unique_count = C->unique();
  uint live_node_count = C->live_nodes();
  uint worklist_size = worklist->size();
  Type_Array new_type_array(C->comp_arena());
  uint current_idx = 0; // The current new node ID. Incremented after every assignment.
  for (uint i = 0; i < _useful.size(); i++) {
    Node* n = _useful.at(i);
    assert(!n->is_Phi() || n->as_Phi()->inst_mem_id() == -1, "should not be linked to data Phi");
    const Type* type = gvn->type_or_null(n);
    new_type_array.map(current_idx, type);
    bool in_worklist = false;
    if (worklist->member(n)) {
      in_worklist = true;
    }
    n->set_idx(current_idx); // Update node ID.
    if (in_worklist) {
      new_worklist->push(n);
    }
    current_idx++;
  }
  assert(worklist_size == new_worklist->size(), "the new worklist must have the same size as the original worklist");
  assert(live_node_count == current_idx, "all live nodes must be processed");
  gvn->replace_types(new_type_array);
  C->set_unique(live_node_count);
  C->reset_dead_node_list();
}
PhaseTransform::PhaseTransform( PhaseNumber pnum ) : Phase(pnum),
  _arena(Thread::current()->resource_area()),
  _nodes(_arena),
  _types(_arena)
{
  init_con_caches();
#ifndef PRODUCT
  clear_progress();
  clear_transforms();
  set_allow_progress(true);
#endif
  _types.map(C->unique(), NULL);
}
PhaseTransform::PhaseTransform( Arena *arena, PhaseNumber pnum ) : Phase(pnum),
  _arena(arena),
  _nodes(arena),
  _types(arena)
{
  init_con_caches();
#ifndef PRODUCT
  clear_progress();
  clear_transforms();
  set_allow_progress(true);
#endif
  _types.map(C->unique(), NULL);
}
PhaseTransform::PhaseTransform( PhaseTransform *pt, PhaseNumber pnum ) : Phase(pnum),
  _arena(pt->_arena),
  _nodes(pt->_nodes),
  _types(pt->_types)
{
  init_con_caches();
#ifndef PRODUCT
  clear_progress();
  clear_transforms();
  set_allow_progress(true);
#endif
}
void PhaseTransform::init_con_caches() {
  memset(_icons,0,sizeof(_icons));
  memset(_lcons,0,sizeof(_lcons));
  memset(_zcons,0,sizeof(_zcons));
}
const TypeInt* PhaseTransform::find_int_type(Node* n) {
  if (n == NULL)  return NULL;
  const Type* t = type_or_null(n);
  if (t == NULL)  return NULL;
  return t->isa_int();
}
const TypeLong* PhaseTransform::find_long_type(Node* n) {
  if (n == NULL)  return NULL;
  const Type* t = type_or_null(n);
  if (t == NULL)  return NULL;
  return t->isa_long();
}
#ifndef PRODUCT
void PhaseTransform::dump_old2new_map() const {
  _nodes.dump();
}
void PhaseTransform::dump_new( uint nidx ) const {
  for( uint i=0; i<_nodes.Size(); i++ )
    if( _nodes[i] && _nodes[i]->_idx == nidx ) {
      _nodes[i]->dump();
      tty->cr();
      tty->print_cr("Old index= %d",i);
      return;
    }
  tty->print_cr("Node %d not found in the new indices", nidx);
}
void PhaseTransform::dump_types( ) const {
  _types.dump();
}
void PhaseTransform::dump_nodes_and_types(const Node *root, uint depth, bool only_ctrl) {
  VectorSet visited(Thread::current()->resource_area());
  dump_nodes_and_types_recur( root, depth, only_ctrl, visited );
}
void PhaseTransform::dump_nodes_and_types_recur( const Node *n, uint depth, bool only_ctrl, VectorSet &visited) {
  if( !n ) return;
  if( depth == 0 ) return;
  if( visited.test_set(n->_idx) ) return;
  for( uint i=0; i<n->len(); i++ ) {
    if( only_ctrl && !(n->is_Region()) && i != TypeFunc::Control ) continue;
    dump_nodes_and_types_recur( n->in(i), depth-1, only_ctrl, visited );
  }
  n->dump();
  if (type_or_null(n) != NULL) {
    tty->print("      "); type(n)->dump(); tty->cr();
  }
}
#endif
PhaseValues::PhaseValues( Arena *arena, uint est_max_size ) : PhaseTransform(arena, GVN), _table(arena, est_max_size) {
  NOT_PRODUCT( clear_new_values(); )
}
PhaseValues::PhaseValues( PhaseValues *ptv ) : PhaseTransform( ptv, GVN ),
  _table(&ptv->_table) {
  NOT_PRODUCT( clear_new_values(); )
}
PhaseValues::PhaseValues( PhaseValues *ptv, const char *dummy ) : PhaseTransform( ptv, GVN ),
  _table(ptv->arena(),ptv->_table.size()) {
  NOT_PRODUCT( clear_new_values(); )
}
#ifndef PRODUCT
PhaseValues::~PhaseValues() {
  _table.dump();
  if( PrintCompilation && Verbose && WizardMode ) {
    tty->print("\n%sValues: %d nodes ---> %d/%d (%d)",
      is_IterGVN() ? "Iter" : "    ", C->unique(), made_progress(), made_transforms(), made_new_values());
    if( made_transforms() != 0 ) {
      tty->print_cr("  ratio %f", made_progress()/(float)made_transforms() );
    } else {
      tty->cr();
    }
  }
}
#endif
ConNode* PhaseTransform::makecon(const Type *t) {
  assert(t->singleton(), "must be a constant");
  assert(!t->empty() || t == Type::TOP, "must not be vacuous range");
  switch (t->base()) {  // fast paths
  case Type::Half:
  case Type::Top:  return (ConNode*) C->top();
  case Type::Int:  return intcon( t->is_int()->get_con() );
  case Type::Long: return longcon( t->is_long()->get_con() );
  }
  if (t->is_zero_type())
    return zerocon(t->basic_type());
  return uncached_makecon(t);
}
ConNode* PhaseValues::uncached_makecon(const Type *t) {
  assert(t->singleton(), "must be a constant");
  ConNode* x = ConNode::make(C, t);
  ConNode* k = (ConNode*)hash_find_insert(x); // Value numbering
  if (k == NULL) {
    set_type(x, t);             // Missed, provide type mapping
    GrowableArray<Node_Notes*>* nna = C->node_note_array();
    if (nna != NULL) {
      Node_Notes* loc = C->locate_node_notes(nna, x->_idx, true);
      loc->clear(); // do not put debug info on constants
    }
  } else {
    x->destruct();              // Hit, destroy duplicate constant
    x = k;                      // use existing constant
  }
  return x;
}
ConINode* PhaseTransform::intcon(int i) {
  if (i >= _icon_min && i <= _icon_max) {
    ConINode* icon = _icons[i-_icon_min];
    if (icon != NULL && icon->in(TypeFunc::Control) != NULL)
      return icon;
  }
  ConINode* icon = (ConINode*) uncached_makecon(TypeInt::make(i));
  assert(icon->is_Con(), "");
  if (i >= _icon_min && i <= _icon_max)
    _icons[i-_icon_min] = icon;   // Cache small integers
  return icon;
}
ConLNode* PhaseTransform::longcon(jlong l) {
  if (l >= _lcon_min && l <= _lcon_max) {
    ConLNode* lcon = _lcons[l-_lcon_min];
    if (lcon != NULL && lcon->in(TypeFunc::Control) != NULL)
      return lcon;
  }
  ConLNode* lcon = (ConLNode*) uncached_makecon(TypeLong::make(l));
  assert(lcon->is_Con(), "");
  if (l >= _lcon_min && l <= _lcon_max)
    _lcons[l-_lcon_min] = lcon;      // Cache small integers
  return lcon;
}
ConNode* PhaseTransform::zerocon(BasicType bt) {
  assert((uint)bt <= _zcon_max, "domain check");
  ConNode* zcon = _zcons[bt];
  if (zcon != NULL && zcon->in(TypeFunc::Control) != NULL)
    return zcon;
  zcon = (ConNode*) uncached_makecon(Type::get_zero_type(bt));
  _zcons[bt] = zcon;
  return zcon;
}
Node *PhaseGVN::transform( Node *n ) {
  return transform_no_reclaim(n);
}
Node *PhaseGVN::transform_no_reclaim( Node *n ) {
  NOT_PRODUCT( set_transforms(); )
  Node *k = n;
  NOT_PRODUCT( uint loop_count = 0; )
  while( 1 ) {
    Node *i = k->Ideal(this, /*can_reshape=*/false);
    if( !i ) break;
    assert( i->_idx >= k->_idx, "Idealize should return new nodes, use Identity to return old nodes" );
    k = i;
    assert(loop_count++ < K, "infinite loop in PhaseGVN::transform");
  }
  NOT_PRODUCT( if( loop_count != 0 ) { set_progress(); } )
  ensure_type_or_null(k);
  const Type *t = k->Value(this); // Get runtime Value set
  assert(t != NULL, "value sanity");
  if (type_or_null(k) != t) {
#ifndef PRODUCT
    if (type_or_null(k) == NULL) {
      inc_new_values();
      set_progress();
    }
#endif
    set_type(k, t);
    k->raise_bottom_type(t);
  }
  if( t->singleton() && !k->is_Con() ) {
    NOT_PRODUCT( set_progress(); )
    return makecon(t);          // Turn into a constant
  }
  Node *i = k->Identity(this);  // Look for a nearby replacement
  if( i != k ) {                // Found? Return replacement!
    NOT_PRODUCT( set_progress(); )
    return i;
  }
  i = hash_find_insert(k);      // Insert if new
  if( i && (i != k) ) {
    NOT_PRODUCT( set_progress(); )
    return i;
  }
  return k;
}
#ifdef ASSERT
void PhaseGVN::dead_loop_check( Node *n ) {
  if (n != NULL && !n->is_dead_loop_safe() && !n->is_CFG()) {
    bool no_dead_loop = true;
    uint cnt = n->req();
    for (uint i = 1; i < cnt && no_dead_loop; i++) {
      Node *in = n->in(i);
      if (in == n) {
        no_dead_loop = false;
      } else if (in != NULL && !in->is_dead_loop_safe()) {
        uint icnt = in->req();
        for (uint j = 1; j < icnt && no_dead_loop; j++) {
          if (in->in(j) == n || in->in(j) == in)
            no_dead_loop = false;
        }
      }
    }
    if (!no_dead_loop) n->dump(3);
    assert(no_dead_loop, "dead loop detected");
  }
}
#endif
PhaseIterGVN::PhaseIterGVN( PhaseIterGVN *igvn, const char *dummy ) : PhaseGVN(igvn,dummy), _worklist( ),
                                                                      _stack(C->live_nodes() >> 1),
                                                                      _delay_transform(false) {
}
PhaseIterGVN::PhaseIterGVN( PhaseIterGVN *igvn ) : PhaseGVN(igvn),
                                                   _worklist( igvn->_worklist ),
                                                   _stack( igvn->_stack ),
                                                   _delay_transform(igvn->_delay_transform)
{
}
PhaseIterGVN::PhaseIterGVN( PhaseGVN *gvn ) : PhaseGVN(gvn),
                                              _worklist(*C->for_igvn()),
                                              _stack(C->comp_arena(), 32),
                                              _delay_transform(false)
{
  uint max;
  max = _table.size();
  for( uint i = 0; i < max; ++i ) {
    Node *n = _table.at(i);
    if(n != NULL && n != _table.sentinel() && n->outcnt() == 0) {
      if( n->is_top() ) continue;
      assert( false, "Parse::remove_useless_nodes missed this node");
      hash_delete(n);
    }
  }
  max = _worklist.size();
  for( uint j = 0; j < max; j++ ) {
    Node *n = _worklist.at(j);
    uint uop = n->Opcode();
    if( uop == Op_Phi || uop == Op_Region ||
        n->is_Type() ||
        n->is_Mem() )
      add_users_to_worklist(n);
  }
}
#ifndef PRODUCT
void PhaseIterGVN::verify_step(Node* n) {
  _verify_window[_verify_counter % _verify_window_size] = n;
  ++_verify_counter;
  ResourceMark rm;
  ResourceArea *area = Thread::current()->resource_area();
  VectorSet old_space(area), new_space(area);
  if (C->unique() < 1000 ||
      0 == _verify_counter % (C->unique() < 10000 ? 10 : 100)) {
    ++_verify_full_passes;
    Node::verify_recur(C->root(), -1, old_space, new_space);
  }
  const int verify_depth = 4;
  for ( int i = 0; i < _verify_window_size; i++ ) {
    Node* n = _verify_window[i];
    if ( n == NULL )  continue;
    if( n->in(0) == NodeSentinel ) {  // xform_idom
      _verify_window[i] = n->in(1);
      --i; continue;
    }
    Node::verify_recur(n, verify_depth, old_space, new_space);
  }
}
#endif
void PhaseIterGVN::init_worklist( Node *n ) {
  if( _worklist.member(n) ) return;
  _worklist.push(n);
  uint cnt = n->req();
  for( uint i =0 ; i < cnt; i++ ) {
    Node *m = n->in(i);
    if( m ) init_worklist(m);
  }
}
void PhaseIterGVN::optimize() {
  debug_only(uint num_processed  = 0;);
#ifndef PRODUCT
  {
    _verify_counter = 0;
    _verify_full_passes = 0;
    for ( int i = 0; i < _verify_window_size; i++ ) {
      _verify_window[i] = NULL;
    }
  }
#endif
#ifdef ASSERT
  Node* prev = NULL;
  uint rep_cnt = 0;
#endif
  uint loop_count = 0;
  while( _worklist.size() ) {
    if (C->check_node_count(NodeLimitFudgeFactor * 2,
                            "out of nodes optimizing method")) {
      return;
    }
    Node *n  = _worklist.pop();
    if (++loop_count >= K * C->live_nodes()) {
      debug_only(n->dump(4);)
      assert(false, "infinite loop in PhaseIterGVN::optimize");
      C->record_method_not_compilable("infinite loop in PhaseIterGVN::optimize");
      return;
    }
#ifdef ASSERT
    if (n == prev) {
      if (++rep_cnt > 3) {
        n->dump(4);
        assert(false, "loop in Ideal transformation");
      }
    } else {
      rep_cnt = 0;
    }
    prev = n;
#endif
    if (TraceIterativeGVN && Verbose) {
      tty->print("  Pop ");
      NOT_PRODUCT( n->dump(); )
      debug_only(if( (num_processed++ % 100) == 0 ) _worklist.print_set();)
    }
    if (n->outcnt() != 0) {
#ifndef PRODUCT
      uint wlsize = _worklist.size();
      const Type* oldtype = type_or_null(n);
#endif //PRODUCT
      Node *nn = transform_old(n);
#ifndef PRODUCT
      if (TraceIterativeGVN) {
        const Type* newtype = type_or_null(n);
        if (nn != n) {
          tty->print("< ");
          if (oldtype != newtype && oldtype != NULL) {
            oldtype->dump();
          }
          do { tty->print("\t"); } while (tty->position() < 16);
          tty->print("<");
          n->dump();
        }
        if (oldtype != newtype || nn != n) {
          if (oldtype == NULL) {
            tty->print("* ");
          } else if (nn != n) {
            tty->print("> ");
          } else {
            tty->print("= ");
          }
          if (newtype == NULL) {
            tty->print("null");
          } else {
            newtype->dump();
          }
          do { tty->print("\t"); } while (tty->position() < 16);
          nn->dump();
        }
        if (Verbose && wlsize < _worklist.size()) {
          tty->print("  Push {");
          while (wlsize != _worklist.size()) {
            Node* pushed = _worklist.at(wlsize++);
            tty->print(" %d", pushed->_idx);
          }
          tty->print_cr(" }");
        }
      }
      if( VerifyIterativeGVN && nn != n ) {
        verify_step((Node*) NULL);  // ignore n, it might be subsumed
      }
#endif
    } else if (!n->is_top()) {
      remove_dead_node(n);
    }
  }
#ifndef PRODUCT
  C->verify_graph_edges();
  if( VerifyOpto && allow_progress() ) {
    C->root()->verify();
    { // Check if any progress was missed using IterGVN
      ResourceMark rm;
      PhaseIterGVN igvn2(this,"Verify"); // Fresh and clean!
      igvn2.init_worklist(C->root());
      igvn2.set_allow_progress(false);
      igvn2.optimize();
      igvn2.set_allow_progress(true);
    }
  }
  if ( VerifyIterativeGVN && PrintOpto ) {
    if ( _verify_counter == _verify_full_passes )
      tty->print_cr("VerifyIterativeGVN: %d transforms and verify passes",
                    (int) _verify_full_passes);
    else
      tty->print_cr("VerifyIterativeGVN: %d transforms, %d full verify passes",
                  (int) _verify_counter, (int) _verify_full_passes);
  }
#endif
}
Node* PhaseIterGVN::register_new_node_with_optimizer(Node* n, Node* orig) {
  set_type_bottom(n);
  _worklist.push(n);
  if (orig != NULL)  C->copy_node_notes_to(n, orig);
  return n;
}
Node *PhaseIterGVN::transform( Node *n ) {
  if (_delay_transform) {
    register_new_node_with_optimizer(n);
    return n;
  }
  ensure_type_or_null(n);
  if (type_or_null(n) == NULL) {
    set_type_bottom(n);
  }
  return transform_old(n);
}
Node *PhaseIterGVN::transform_old( Node *n ) {
#ifndef PRODUCT
  debug_only(uint loop_count = 0;);
  set_transforms();
#endif
  _table.hash_delete(n);
  if( VerifyIterativeGVN ) {
   assert( !_table.find_index(n->_idx), "found duplicate entry in table");
  }
  Node *k = n;
  DEBUG_ONLY(dead_loop_check(k);)
  DEBUG_ONLY(bool is_new = (k->outcnt() == 0);)
  Node *i = k->Ideal(this, /*can_reshape=*/true);
  assert(i != k || is_new || i->outcnt() > 0, "don't return dead nodes");
#ifndef PRODUCT
  if( VerifyIterativeGVN )
    verify_step(k);
  if( i && VerifyOpto ) {
    if( !allow_progress() ) {
      if (i->is_Add() && i->outcnt() == 1) {
      } else if( i->is_If() && (i->in(0) == NULL) ) {
        return i;
      } else
        set_progress();
    } else
      set_progress();
  }
#endif
  while( i ) {
#ifndef PRODUCT
    debug_only( if( loop_count >= K ) i->dump(4); )
    assert(loop_count < K, "infinite loop in PhaseIterGVN::transform");
    debug_only( loop_count++; )
#endif
    assert((i->_idx >= k->_idx) || i->is_top(), "Idealize should return new nodes, use Identity to return old nodes");
    add_users_to_worklist( k );
    if( k != i ) {
      subsume_node( k, i );
      k = i;
    }
    DEBUG_ONLY(dead_loop_check(k);)
    DEBUG_ONLY(is_new = (k->outcnt() == 0);)
    i = k->Ideal(this, /*can_reshape=*/true);
    assert(i != k || is_new || i->outcnt() > 0, "don't return dead nodes");
#ifndef PRODUCT
    if( VerifyIterativeGVN )
      verify_step(k);
    if( i && VerifyOpto ) set_progress();
#endif
  }
  ensure_type_or_null(k);
  const Type *t = k->Value(this);
  assert(t != NULL, "value sanity");
  if (t != type_or_null(k)) {
    NOT_PRODUCT( set_progress(); )
    NOT_PRODUCT( inc_new_values();)
    set_type(k, t);
    k->raise_bottom_type(t);
    add_users_to_worklist( k );
  }
  if( t->singleton() && !k->is_Con() ) {
    NOT_PRODUCT( set_progress(); )
    Node *con = makecon(t);     // Make a constant
    add_users_to_worklist( k );
    subsume_node( k, con );     // Everybody using k now uses con
    return con;
  }
  i = k->Identity(this);        // Look for a nearby replacement
  if( i != k ) {                // Found? Return replacement!
    NOT_PRODUCT( set_progress(); )
    add_users_to_worklist( k );
    subsume_node( k, i );       // Everybody using k now uses i
    return i;
  }
  i = hash_find_insert(k);      // Check for pre-existing node
  if( i && (i != k) ) {
    NOT_PRODUCT( set_progress(); )
    add_users_to_worklist( k );
    subsume_node( k, i );       // Everybody using k now uses i
    return i;
  }
  return k;
}
const Type* PhaseIterGVN::saturate(const Type* new_type, const Type* old_type,
                                   const Type* limit_type) const {
  return new_type->narrow(old_type);
}
void PhaseIterGVN::remove_globally_dead_node( Node *dead ) {
  enum DeleteProgress {
    PROCESS_INPUTS,
    PROCESS_OUTPUTS
  };
  assert(_stack.is_empty(), "not empty");
  _stack.push(dead, PROCESS_INPUTS);
  while (_stack.is_nonempty()) {
    dead = _stack.node();
    if (dead->Opcode() == Op_SafePoint) {
      dead->as_SafePoint()->disconnect_from_root(this);
    }
    uint progress_state = _stack.index();
    assert(dead != C->root(), "killing root, eh?");
    assert(!dead->is_top(), "add check for top when pushing");
    NOT_PRODUCT( set_progress(); )
    if (progress_state == PROCESS_INPUTS) {
      _stack.set_index(PROCESS_OUTPUTS);
      if (!dead->is_Con()) { // Don't kill cons but uses
        bool recurse = false;
        _table.hash_delete( dead );
        for (uint i = 0; i < dead->req(); i++) {
          Node *in = dead->in(i);
          if (in != NULL && in != C->top()) {  // Points to something?
            int nrep = dead->replace_edge(in, NULL);  // Kill edges
            assert((nrep > 0), "sanity");
            if (in->outcnt() == 0) { // Made input go dead?
              _stack.push(in, PROCESS_INPUTS); // Recursively remove
              recurse = true;
            } else if (in->outcnt() == 1 &&
                       in->has_special_unique_user()) {
              _worklist.push(in->unique_out());
            } else if (in->outcnt() <= 2 && dead->is_Phi()) {
              if (in->Opcode() == Op_Region) {
                _worklist.push(in);
              } else if (in->is_Store()) {
                DUIterator_Fast imax, i = in->fast_outs(imax);
                _worklist.push(in->fast_out(i));
                i++;
                if (in->outcnt() == 2) {
                  _worklist.push(in->fast_out(i));
                  i++;
                }
                assert(!(i < imax), "sanity");
              }
            }
            if (ReduceFieldZeroing && dead->is_Load() && i == MemNode::Memory &&
                in->is_Proj() && in->in(0) != NULL && in->in(0)->is_Initialize()) {
              for (DUIterator_Fast jmax, j = in->fast_outs(jmax); j < jmax; j++) {
                Node *n = in->fast_out(j);
                if (n->is_Store()) {
                  _worklist.push(n);
                }
              }
            }
          } // if (in != NULL && in != C->top())
        } // for (uint i = 0; i < dead->req(); i++)
        if (recurse) {
          continue;
        }
      } // if (!dead->is_Con())
    } // if (progress_state == PROCESS_INPUTS)
    if (dead->outcnt() > 0) {
      _stack.push(dead->raw_out(0), PROCESS_INPUTS);
    } else {
      _stack.pop();
      _worklist.remove(dead);
      if (!dead->is_Con()) {
        C->record_dead_node(dead->_idx);
      }
      if (dead->is_macro()) {
        C->remove_macro_node(dead);
      }
      if (dead->is_expensive()) {
        C->remove_expensive_node(dead);
      }
      CastIINode* cast = dead->isa_CastII();
      if (cast != NULL && cast->has_range_check()) {
        C->remove_range_check_cast(cast);
      }
    }
  } // while (_stack.is_nonempty())
}
void PhaseIterGVN::subsume_node( Node *old, Node *nn ) {
  if (old->Opcode() == Op_SafePoint) {
    old->as_SafePoint()->disconnect_from_root(this);
  }
  assert( old != hash_find(old), "should already been removed" );
  assert( old != C->top(), "cannot subsume top node");
  C->copy_node_notes_to(nn, old);
  for (DUIterator_Last imin, i = old->last_outs(imin); i >= imin; ) {
    Node* use = old->last_out(i);  // for each use...
    bool is_in_table = _table.hash_delete( use );
    uint num_edges = 0;
    for (uint jmax = use->len(), j = 0; j < jmax; j++) {
      if (use->in(j) == old) {
        use->set_req(j, nn);
        ++num_edges;
      }
    }
    if( is_in_table ) {
      hash_find_insert(use);
    }
    i -= num_edges;    // we deleted 1 or more copies of this edge
  }
  if (old->is_Phi() && old->as_Phi()->type()->has_memory() && old->in(0) != NULL) {
    Node* region = old->in(0);
    for (DUIterator_Fast imax, i = region->fast_outs(imax); i < imax; i++) {
      PhiNode* phi = region->fast_out(i)->isa_Phi();
      if (phi != NULL && phi->inst_mem_id() == (int)old->_idx) {
        phi->set_inst_mem_id((int)nn->_idx);
      }
    }
  }
  Node *temp = new (C) Node(1);
  temp->init_req(0,nn);     // Add a use to nn to prevent him from dying
  remove_dead_node( old );
  temp->del_req(0);         // Yank bogus edge
#ifndef PRODUCT
  if( VerifyIterativeGVN ) {
    for ( int i = 0; i < _verify_window_size; i++ ) {
      if ( _verify_window[i] == old )
        _verify_window[i] = nn;
    }
  }
#endif
  _worklist.remove(temp);   // this can be necessary
  temp->destruct();         // reuse the _idx of this little guy
}
void PhaseIterGVN::add_users_to_worklist0( Node *n ) {
  for (DUIterator_Fast imax, i = n->fast_outs(imax); i < imax; i++) {
    _worklist.push(n->fast_out(i));  // Push on worklist
  }
}
static PhiNode* countedloop_phi_from_cmp(CmpINode* cmp, Node* n) {
  for (DUIterator_Fast imax, i = cmp->fast_outs(imax); i < imax; i++) {
    Node* bol = cmp->fast_out(i);
    for (DUIterator_Fast i2max, i2 = bol->fast_outs(i2max); i2 < i2max; i2++) {
      Node* iff = bol->fast_out(i2);
      if (iff->is_CountedLoopEnd()) {
        CountedLoopEndNode* cle = iff->as_CountedLoopEnd();
        if (cle->limit() == n) {
          PhiNode* phi = cle->phi();
          if (phi != NULL) {
            return phi;
          }
        }
      }
    }
  }
  return NULL;
}
void PhaseIterGVN::add_users_to_worklist( Node *n ) {
  add_users_to_worklist0(n);
  for (DUIterator_Fast imax, i = n->fast_outs(imax); i < imax; i++) {
    Node* use = n->fast_out(i); // Get use
    if( use->is_Multi() ||      // Multi-definer?  Push projs on worklist
        use->is_Store() )       // Enable store/load same address
      add_users_to_worklist0(use);
    if (use->is_CallDynamicJava() && n == use->in(TypeFunc::Parms)) {
      Node* p = use->as_CallDynamicJava()->proj_out(TypeFunc::Control);
      if (p != NULL) {
        add_users_to_worklist0(p);
      }
    }
    uint use_op = use->Opcode();
    if(use->is_Cmp()) {       // Enable CMP/BOOL optimization
      add_users_to_worklist(use); // Put Bool on worklist
      if (use->outcnt() > 0) {
        Node* bol = use->raw_out(0);
        if (bol->outcnt() > 0) {
          Node* iff = bol->raw_out(0);
          if (iff->outcnt() == 2) {
            Node* ifproj0 = iff->raw_out(0);
            Node* ifproj1 = iff->raw_out(1);
            if (ifproj0->outcnt() > 0 && ifproj1->outcnt() > 0) {
              Node* region0 = ifproj0->raw_out(0);
              Node* region1 = ifproj1->raw_out(0);
              if( region0 == region1 )
                add_users_to_worklist0(region0);
            }
          }
        }
      }
      if (use_op == Op_CmpI) {
        Node* phi = countedloop_phi_from_cmp((CmpINode*)use, n);
        if (phi != NULL) {
          _worklist.push(phi);
        }
        Node* in1 = use->in(1);
        for (uint i = 0; i < in1->outcnt(); i++) {
          if (in1->raw_out(i)->Opcode() == Op_CastII) {
            Node* castii = in1->raw_out(i);
            if (castii->in(0) != NULL && castii->in(0)->in(0) != NULL && castii->in(0)->in(0)->is_If()) {
              Node* ifnode = castii->in(0)->in(0);
              if (ifnode->in(1) != NULL && ifnode->in(1)->is_Bool() && ifnode->in(1)->in(1) == use) {
                _worklist.push(castii);
              }
            }
          }
        }
      }
    }
    if( use->is_ConstraintCast() || use->is_CheckCastPP() ) {
      for (DUIterator_Fast i2max, i2 = use->fast_outs(i2max); i2 < i2max; i2++) {
        Node* u = use->fast_out(i2);
        if (u->is_Phi())
          _worklist.push(u);
      }
    }
    if( use_op == Op_LShiftI ) {
      for (DUIterator_Fast i2max, i2 = use->fast_outs(i2max); i2 < i2max; i2++) {
        Node* u = use->fast_out(i2);
        if (u->Opcode() == Op_RShiftI)
          _worklist.push(u);
      }
    }
    if (use_op == Op_AddI || use_op == Op_SubI) {
      for (DUIterator_Fast i2max, i2 = use->fast_outs(i2max); i2 < i2max; i2++) {
        Node* u = use->fast_out(i2);
        if (u->is_Cmp() && (u->Opcode() == Op_CmpU)) {
          _worklist.push(u);
        }
      }
    }
    if( use_op == Op_AddP ) {
      for (DUIterator_Fast i2max, i2 = use->fast_outs(i2max); i2 < i2max; i2++) {
        Node* u = use->fast_out(i2);
        if (u->is_Mem())
          _worklist.push(u);
      }
    }
    if (use_op == Op_Allocate || use_op == Op_AllocateArray) {
      InitializeNode* init = use->as_Allocate()->initialization();
      if (init != NULL) {
        Node* imem = init->proj_out(TypeFunc::Memory);
        if (imem != NULL)  add_users_to_worklist0(imem);
      }
    }
    if (use_op == Op_Initialize) {
      Node* imem = use->as_Initialize()->proj_out(TypeFunc::Memory);
      if (imem != NULL)  add_users_to_worklist0(imem);
    }
  }
}
void PhaseIterGVN::remove_speculative_types()  {
  assert(UseTypeSpeculation, "speculation is off");
  for (uint i = 0; i < _types.Size(); i++)  {
    const Type* t = _types.fast_lookup(i);
    if (t != NULL) {
      _types.map(i, t->remove_speculative());
    }
  }
  _table.check_no_speculative_types();
}
#ifndef PRODUCT
uint PhaseCCP::_total_invokes   = 0;
uint PhaseCCP::_total_constants = 0;
#endif
PhaseCCP::PhaseCCP( PhaseIterGVN *igvn ) : PhaseIterGVN(igvn) {
  NOT_PRODUCT( clear_constants(); )
  assert( _worklist.size() == 0, "" );
  _nodes.clear();               // Clear out from IterGVN
  analyze();
}
#ifndef PRODUCT
PhaseCCP::~PhaseCCP() {
  inc_invokes();
  _total_constants += count_constants();
}
#endif
#ifdef ASSERT
static bool ccp_type_widens(const Type* t, const Type* t0) {
  assert(t->meet(t0) == t, "Not monotonic");
  switch (t->base() == t0->base() ? t->base() : Type::Top) {
  case Type::Int:
    assert(t0->isa_int()->_widen <= t->isa_int()->_widen, "widen increases");
    break;
  case Type::Long:
    assert(t0->isa_long()->_widen <= t->isa_long()->_widen, "widen increases");
    break;
  }
  return true;
}
#endif //ASSERT
void PhaseCCP::analyze() {
  for (int i = C->unique() - 1; i >= 0; i--)  {
    _types.map(i,Type::TOP);
  }
  Unique_Node_List worklist;
  worklist.push(C->root());
  while( worklist.size() ) {
    Node *n = worklist.pop();
    const Type *t = n->Value(this);
    if (t != type(n)) {
      assert(ccp_type_widens(t, type(n)), "ccp type must widen");
#ifndef PRODUCT
      if( TracePhaseCCP ) {
        t->dump();
        do { tty->print("\t"); } while (tty->position() < 16);
        n->dump();
      }
#endif
      set_type(n, t);
      for (DUIterator_Fast imax, i = n->fast_outs(imax); i < imax; i++) {
        Node* m = n->fast_out(i);   // Get user
        if (m->is_Region()) {  // New path to Region?  Must recheck Phis too
          for (DUIterator_Fast i2max, i2 = m->fast_outs(i2max); i2 < i2max; i2++) {
            Node* p = m->fast_out(i2); // Propagate changes to uses
            if (p->bottom_type() != type(p)) { // If not already bottomed out
              worklist.push(p); // Propagate change to user
            }
          }
        }
        if (m->is_Call()) {
          for (DUIterator_Fast i2max, i2 = m->fast_outs(i2max); i2 < i2max; i2++) {
            Node* p = m->fast_out(i2);  // Propagate changes to uses
            if (p->is_Proj() && p->as_Proj()->_con == TypeFunc::Control) {
              Node* catch_node = p->find_out_with(Op_Catch);
              if (catch_node != NULL) {
                worklist.push(catch_node);
              }
            }
          }
        }
        if (m->bottom_type() != type(m)) { // If not already bottomed out
          worklist.push(m);     // Propagate change to user
        }
        uint m_op = m->Opcode();
        if (m_op == Op_AddI || m_op == Op_SubI) {
          for (DUIterator_Fast i2max, i2 = m->fast_outs(i2max); i2 < i2max; i2++) {
            Node* p = m->fast_out(i2); // Propagate changes to uses
            if (p->Opcode() == Op_CmpU) {
              if(p->bottom_type() != type(p)) { // If not already bottomed out
                worklist.push(p); // Propagate change to user
              }
            }
          }
        }
        if (m_op == Op_CmpI) {
          PhiNode* phi = countedloop_phi_from_cmp((CmpINode*)m, n);
          if (phi != NULL) {
            worklist.push(phi);
          }
        }
      }
    }
  }
}
void PhaseCCP::do_transform() {
  C->set_root( transform(C->root())->as_Root() );
  assert( C->top(),  "missing TOP node" );
  assert( C->root(), "missing root" );
}
Node *PhaseCCP::transform( Node *n ) {
  Node *new_node = _nodes[n->_idx]; // Check for transformed node
  if( new_node != NULL )
    return new_node;                // Been there, done that, return old answer
  new_node = transform_once(n);     // Check for constant
  _nodes.map( n->_idx, new_node );  // Flag as having been cloned
  GrowableArray <Node *> trstack(C->live_nodes() >> 1);
  trstack.push(new_node);           // Process children of cloned node
  while ( trstack.is_nonempty() ) {
    Node *clone = trstack.pop();
    uint cnt = clone->req();
    for( uint i = 0; i < cnt; i++ ) {          // For all inputs do
      Node *input = clone->in(i);
      if( input != NULL ) {                    // Ignore NULLs
        Node *new_input = _nodes[input->_idx]; // Check for cloned input node
        if( new_input == NULL ) {
          new_input = transform_once(input);   // Check for constant
          _nodes.map( input->_idx, new_input );// Flag as having been cloned
          trstack.push(new_input);
        }
        assert( new_input == clone->in(i), "insanity check");
      }
    }
  }
  return new_node;
}
Node *PhaseCCP::transform_once( Node *n ) {
  const Type *t = type(n);
  if( t->singleton() ) {
    Node *nn = n;               // Default is to return the original constant
    if( t == Type::TOP ) {
      if( C->cached_top_node() == NULL || C->cached_top_node()->in(0) == NULL ) {
        C->set_cached_top_node( ConNode::make(C, Type::TOP) );
        set_type(C->top(), Type::TOP);
      }
      nn = C->top();
    }
    if( !n->is_Con() ) {
      if( t != Type::TOP ) {
        nn = makecon(t);        // ConNode::make(t);
        NOT_PRODUCT( inc_constants(); )
      } else if( n->is_Region() ) { // Unreachable region
        n->set_req(0, NULL);        // Cut selfreference
        for (DUIterator i = n->outs(); n->has_out(i); i++) {
          Node* m = n->out(i);
          if( m->is_Phi() ) {
            assert(type(m) == Type::TOP, "Unreachable region should not have live phis.");
            replace_node(m, nn);
            --i; // deleted this phi; rescan starting with next position
          }
        }
      }
      replace_node(n,nn);       // Update DefUse edges for new constant
    }
    return nn;
  }
  if (t != n->bottom_type()) {
    hash_delete(n);             // changing bottom type may force a rehash
    n->raise_bottom_type(t);
    _worklist.push(n);          // n re-enters the hash table via the worklist
  }
  Node *nn = n->Ideal_DU_postCCP(this);
  switch( n->Opcode() ) {
  case Op_FastLock:      // Revisit FastLocks for lock coarsening
  case Op_If:
  case Op_CountedLoopEnd:
  case Op_Region:
  case Op_Loop:
  case Op_CountedLoop:
  case Op_Conv2B:
  case Op_Opaque1:
  case Op_Opaque2:
    _worklist.push(n);
    break;
  default:
    break;
  }
  if( nn ) {
    _worklist.push(n);
    add_users_to_worklist(n);
    return nn;
  }
  return  n;
}
const Type* PhaseCCP::saturate(const Type* new_type, const Type* old_type,
                               const Type* limit_type) const {
  const Type* wide_type = new_type->widen(old_type, limit_type);
  if (wide_type != new_type) {          // did we widen?
    new_type = wide_type->filter(limit_type);
  }
  return new_type;
}
#ifndef PRODUCT
void PhaseCCP::print_statistics() {
  tty->print_cr("CCP: %d  constants found: %d", _total_invokes, _total_constants);
}
#endif
#ifndef PRODUCT
uint PhasePeephole::_total_peepholes = 0;
#endif
PhasePeephole::PhasePeephole( PhaseRegAlloc *regalloc, PhaseCFG &cfg )
  : PhaseTransform(Peephole), _regalloc(regalloc), _cfg(cfg) {
  NOT_PRODUCT( clear_peepholes(); )
}
#ifndef PRODUCT
PhasePeephole::~PhasePeephole() {
  _total_peepholes += count_peepholes();
}
#endif
Node *PhasePeephole::transform( Node *n ) {
  ShouldNotCallThis();
  return NULL;
}
void PhasePeephole::do_transform() {
  bool method_name_not_printed = true;
  for (uint block_number = 1; block_number < _cfg.number_of_blocks(); ++block_number) {
    Block* block = _cfg.get_block(block_number);
    bool block_not_printed = true;
    uint end_index = block->number_of_nodes();
    for( uint instruction_index = 1; instruction_index < end_index; ++instruction_index ) {
      Node     *n = block->get_node(instruction_index);
      if( n->is_Mach() ) {
        MachNode *m = n->as_Mach();
        int deleted_count = 0;
        MachNode *m2 = m->peephole( block, instruction_index, _regalloc, deleted_count, C );
        if( m2 != NULL ) {
#ifndef PRODUCT
          if( PrintOptoPeephole ) {
            if( C->method() && method_name_not_printed ) {
              C->method()->print_short_name(); tty->cr();
              method_name_not_printed = false;
            }
            if( Verbose && block_not_printed) {
              tty->print_cr("in block");
              block->dump();
              block_not_printed = false;
            }
            for( int i = (deleted_count - 1); i >= 0; --i ) {
              block->get_node(instruction_index-i)->as_Mach()->format(_regalloc); tty->cr();
            }
            tty->print_cr("replaced with");
            m2->format(_regalloc);
            tty->print("\n\n");
          }
#endif
          uint safe_instruction_index = (instruction_index - deleted_count);
          for( ; (instruction_index > safe_instruction_index); --instruction_index ) {
            block->remove_node( instruction_index );
          }
          block->insert_node(m2, safe_instruction_index + 1);
          end_index = block->number_of_nodes() - 1; // Recompute new block size
          NOT_PRODUCT( inc_peepholes(); )
        }
      }
    }
  }
}
#ifndef PRODUCT
void PhasePeephole::print_statistics() {
  tty->print_cr("Peephole: peephole rules applied: %d",  _total_peepholes);
}
#endif
void Node::set_req_X( uint i, Node *n, PhaseIterGVN *igvn ) {
  assert( is_not_dead(n), "can not use dead node");
  assert( igvn->hash_find(this) != this, "Need to remove from hash before changing edges" );
  Node *old = in(i);
  set_req(i, n);
  if( old ) {
    switch (old->outcnt()) {
    case 0:
      if (!old->is_top())
        igvn->_worklist.push( old );
      break;
    case 1:
      if( old->is_Store() || old->has_special_unique_user() )
        igvn->add_users_to_worklist( old );
      break;
    case 2:
      if( old->is_Store() )
        igvn->add_users_to_worklist( old );
      if( old->Opcode() == Op_Region )
        igvn->_worklist.push(old);
      break;
    case 3:
      if( old->Opcode() == Op_Region ) {
        igvn->_worklist.push(old);
        igvn->add_users_to_worklist( old );
      }
      break;
    default:
      break;
    }
  }
}
void Node::replace_by(Node *new_node) {
  assert(!is_top(), "top node has no DU info");
  for (DUIterator_Last imin, i = last_outs(imin); i >= imin; ) {
    Node* use = last_out(i);
    uint uses_found = 0;
    for (uint j = 0; j < use->len(); j++) {
      if (use->in(j) == this) {
        if (j < use->req())
              use->set_req(j, new_node);
        else  use->set_prec(j, new_node);
        uses_found++;
      }
    }
    i -= uses_found;    // we deleted 1 or more copies of this edge
  }
}
void Type_Array::grow( uint i ) {
  if( !_max ) {
    _max = 1;
    _types = (const Type**)_a->Amalloc( _max * sizeof(Type*) );
    _types[0] = NULL;
  }
  uint old = _max;
  while( i >= _max ) _max <<= 1;        // Double to fit
  _types = (const Type**)_a->Arealloc( _types, old*sizeof(Type*),_max*sizeof(Type*));
  memset( &_types[old], 0, (_max-old)*sizeof(Type*) );
}
#ifndef PRODUCT
void Type_Array::dump() const {
  uint max = Size();
  for( uint i = 0; i < max; i++ ) {
    if( _types[i] != NULL ) {
      tty->print("  %d\t== ", i); _types[i]->dump(); tty->cr();
    }
  }
}
#endif
C:\hotspot-69087d08d473\src\share\vm/opto/phaseX.hpp
#ifndef SHARE_VM_OPTO_PHASEX_HPP
#define SHARE_VM_OPTO_PHASEX_HPP
#include "libadt/dict.hpp"
#include "libadt/vectset.hpp"
#include "memory/resourceArea.hpp"
#include "opto/memnode.hpp"
#include "opto/node.hpp"
#include "opto/phase.hpp"
#include "opto/type.hpp"
class Compile;
class ConINode;
class ConLNode;
class Node;
class Type;
class PhaseTransform;
class   PhaseGVN;
class     PhaseIterGVN;
class       PhaseCCP;
class   PhasePeephole;
class   PhaseRegAlloc;
class NodeHash : public StackObj {
protected:
  Arena *_a;                    // Arena to allocate in
  uint   _max;                  // Size of table (power of 2)
  uint   _inserts;              // For grow and debug, count of hash_inserts
  uint   _insert_limit;         // 'grow' when _inserts reaches _insert_limit
  Node **_table;                // Hash table of Node pointers
  Node  *_sentinel;             // Replaces deleted entries in hash table
public:
  NodeHash(uint est_max_size);
  NodeHash(Arena *arena, uint est_max_size);
  NodeHash(NodeHash *use_this_state);
#ifdef ASSERT
  ~NodeHash();                  // Unlock all nodes upon destruction of table.
  void operator=(const NodeHash&); // Unlock all nodes upon replacement of table.
#endif
  Node  *hash_find(const Node*);// Find an equivalent version in hash table
  Node  *hash_find_insert(Node*);// If not in table insert else return found node
  void   hash_insert(Node*);    // Insert into hash table
  bool   hash_delete(const Node*);// Replace with _sentinel in hash table
  void   check_grow() {
    _inserts++;
    if( _inserts == _insert_limit ) { grow(); }
    assert( _inserts <= _insert_limit, "hash table overflow");
    assert( _inserts < _max, "hash table overflow" );
  }
  static uint round_up(uint);   // Round up to nearest power of 2
  void   grow();                // Grow _table to next power of 2 and rehash
  uint   insert_limit() const { return _max - (_max>>2); }
  void   clear();               // Set all entries to NULL, keep storage.
  uint   size()         const { return _max; }
  Node  *at(uint table_index) {
    assert(table_index < _max, "Must be within table");
    return _table[table_index];
  }
  void   remove_useless_nodes(VectorSet &useful); // replace with sentinel
  void   replace_with(NodeHash* nh);
  void   check_no_speculative_types(); // Check no speculative part for type nodes in table
  Node  *sentinel() { return _sentinel; }
#ifndef PRODUCT
  Node  *find_index(uint idx);  // For debugging
  void   dump();                // For debugging, dump statistics
#endif
  uint   _grows;                // For debugging, count of table grow()s
  uint   _look_probes;          // For debugging, count of hash probes
  uint   _lookup_hits;          // For debugging, count of hash_finds
  uint   _lookup_misses;        // For debugging, count of hash_finds
  uint   _insert_probes;        // For debugging, count of hash probes
  uint   _delete_probes;        // For debugging, count of hash probes for deletes
  uint   _delete_hits;          // For debugging, count of hash probes for deletes
  uint   _delete_misses;        // For debugging, count of hash probes for deletes
  uint   _total_inserts;        // For debugging, total inserts into hash table
  uint   _total_insert_probes;  // For debugging, total probes while inserting
};
class Type_Array : public StackObj {
  Arena *_a;                    // Arena to allocate in
  uint   _max;
  const Type **_types;
  void grow( uint i );          // Grow array node to fit
  const Type *operator[] ( uint i ) const // Lookup, or NULL for not mapped
  { return (i<_max) ? _types[i] : (Type*)NULL; }
  friend class PhaseTransform;
public:
  Type_Array(Arena *a) : _a(a), _max(0), _types(0) {}
  Type_Array(Type_Array *ta) : _a(ta->_a), _max(ta->_max), _types(ta->_types) { }
  const Type *fast_lookup(uint i) const{assert(i<_max,"oob");return _types[i];}
  void map( uint i, const Type *n ) { if( i>=_max ) grow(i); _types[i] = n; }
  uint Size() const { return _max; }
#ifndef PRODUCT
  void dump() const;
#endif
};
class PhaseRemoveUseless : public Phase {
protected:
  Unique_Node_List _useful;   // Nodes reachable from root
public:
  PhaseRemoveUseless(PhaseGVN *gvn, Unique_Node_List *worklist, PhaseNumber phase_num = Remove_Useless);
  Unique_Node_List *get_useful() { return &_useful; }
};
class PhaseRenumberLive : public PhaseRemoveUseless {
public:
  PhaseRenumberLive(PhaseGVN* gvn,
                    Unique_Node_List* worklist, Unique_Node_List* new_worklist,
                    PhaseNumber phase_num = Remove_Useless_And_Renumber_Live);
};
class PhaseTransform : public Phase {
protected:
  Arena*     _arena;
  Node_List  _nodes;           // Map old node indices to new nodes.
  Type_Array _types;           // Map old node indices to Types.
  enum { _icon_min = -1 * HeapWordSize,
         _icon_max = 16 * HeapWordSize,
         _lcon_min = _icon_min,
         _lcon_max = _icon_max,
         _zcon_max = (uint)T_CONFLICT
  };
  ConINode* _icons[_icon_max - _icon_min + 1];   // cached jint constant nodes
  ConLNode* _lcons[_lcon_max - _lcon_min + 1];   // cached jlong constant nodes
  ConNode*  _zcons[_zcon_max + 1];               // cached is_zero_type nodes
  void init_con_caches();
public:
  PhaseTransform( PhaseNumber pnum );
  PhaseTransform( Arena *arena, PhaseNumber pnum );
  PhaseTransform( PhaseTransform *phase, PhaseNumber pnum );
  Arena*      arena()   { return _arena; }
  Type_Array& types()   { return _types; }
  void replace_types(Type_Array new_types) {
    _types = new_types;
  }
  uint nodes_size() {
    return _nodes.size();
  }
public:
  const Type* type(const Node* n) const {
    assert(n != NULL, "must not be null");
    const Type* t = _types.fast_lookup(n->_idx);
    assert(t != NULL, "must set before get");
    return t;
  }
  const Type* type_or_null(const Node* n) const {
    return _types.fast_lookup(n->_idx);
  }
  void    set_type(const Node* n, const Type *t) {
    assert(t != NULL, "type must not be null");
    _types.map(n->_idx, t);
  }
  void    set_type_bottom(const Node* n) {
    assert(_types[n->_idx] == NULL, "must set the initial type just once");
    _types.map(n->_idx, n->bottom_type());
  }
  void ensure_type_or_null(const Node* n) {
    if (n->_idx >= _types.Size())
      _types.map(n->_idx, NULL);   // Grow the types array as needed.
  }
  const TypeInt*  find_int_type( Node* n);
  const TypeLong* find_long_type(Node* n);
  jint  find_int_con( Node* n, jint  value_if_unknown) {
    const TypeInt* t = find_int_type(n);
    return (t != NULL && t->is_con()) ? t->get_con() : value_if_unknown;
  }
  jlong find_long_con(Node* n, jlong value_if_unknown) {
    const TypeLong* t = find_long_type(n);
    return (t != NULL && t->is_con()) ? t->get_con() : value_if_unknown;
  }
  ConNode* makecon(const Type* t);
  virtual ConNode* uncached_makecon(const Type* t)  // override in PhaseValues
  { ShouldNotCallThis(); return NULL; }
  ConINode* intcon(jint i);
  ConLNode* longcon(jlong l);
  ConNode* zerocon(BasicType bt);
  virtual Node *transform( Node *n ) = 0;
  bool eqv(const Node* n1, const Node* n2) const { return n1 == n2; }
  virtual const Type* saturate(const Type* new_type, const Type* old_type,
                               const Type* limit_type) const
  { ShouldNotCallThis(); return NULL; }
  virtual PhaseIterGVN *is_IterGVN() { return 0; }
#ifndef PRODUCT
  void dump_old2new_map() const;
  void dump_new( uint new_lidx ) const;
  void dump_types() const;
  void dump_nodes_and_types(const Node *root, uint depth, bool only_ctrl = true);
  void dump_nodes_and_types_recur( const Node *n, uint depth, bool only_ctrl, VectorSet &visited);
  uint   _count_progress;       // For profiling, count transforms that make progress
  void   set_progress()        { ++_count_progress; assert( allow_progress(),"No progress allowed during verification"); }
  void   clear_progress()      { _count_progress = 0; }
  uint   made_progress() const { return _count_progress; }
  uint   _count_transforms;     // For profiling, count transforms performed
  void   set_transforms()      { ++_count_transforms; }
  void   clear_transforms()    { _count_transforms = 0; }
  uint   made_transforms() const{ return _count_transforms; }
  bool   _allow_progress;      // progress not allowed during verification pass
  void   set_allow_progress(bool allow) { _allow_progress = allow; }
  bool   allow_progress()               { return _allow_progress; }
#endif
};
class PhaseValues : public PhaseTransform {
protected:
  NodeHash  _table;             // Hash table for value-numbering
public:
  PhaseValues( Arena *arena, uint est_max_size );
  PhaseValues( PhaseValues *pt );
  PhaseValues( PhaseValues *ptv, const char *dummy );
  NOT_PRODUCT( ~PhaseValues(); )
  virtual PhaseIterGVN *is_IterGVN() { return 0; }
  bool   hash_delete(Node *n)     { return _table.hash_delete(n); }
  void   hash_insert(Node *n)     { _table.hash_insert(n); }
  Node  *hash_find_insert(Node *n){ return _table.hash_find_insert(n); }
  Node  *hash_find(const Node *n) { return _table.hash_find(n); }
  void   remove_useless_nodes(VectorSet &useful) {
    _table.remove_useless_nodes(useful);
    init_con_caches();
  }
  virtual ConNode* uncached_makecon(const Type* t);  // override from PhaseTransform
  virtual const Type* saturate(const Type* new_type, const Type* old_type,
                               const Type* limit_type) const
  { return new_type; }
#ifndef PRODUCT
  uint   _count_new_values;     // For profiling, count new values produced
  void    inc_new_values()        { ++_count_new_values; }
  void    clear_new_values()      { _count_new_values = 0; }
  uint    made_new_values() const { return _count_new_values; }
#endif
};
class PhaseGVN : public PhaseValues {
public:
  PhaseGVN( Arena *arena, uint est_max_size ) : PhaseValues( arena, est_max_size ) {}
  PhaseGVN( PhaseGVN *gvn ) : PhaseValues( gvn ) {}
  PhaseGVN( PhaseGVN *gvn, const char *dummy ) : PhaseValues( gvn, dummy ) {}
  Node  *transform( Node *n );
  Node  *transform_no_reclaim( Node *n );
  void replace_with(PhaseGVN* gvn) {
    _table.replace_with(&gvn->_table);
    _types = gvn->_types;
  }
  DEBUG_ONLY(void dead_loop_check(Node *n);)
};
class PhaseIterGVN : public PhaseGVN {
private:
  bool _delay_transform;  // When true simply register the node when calling transform
  virtual Node *transform_old( Node *a_node );
  void subsume_node( Node *old, Node *nn );
  Node_Stack _stack;      // Stack used to avoid recursion
protected:
  virtual Node *transform( Node *a_node );
  void init_worklist( Node *a_root );
  virtual const Type* saturate(const Type* new_type, const Type* old_type,
                               const Type* limit_type) const;
public:
  PhaseIterGVN( PhaseIterGVN *igvn ); // Used by CCP constructor
  PhaseIterGVN( PhaseGVN *gvn ); // Used after Parser
  PhaseIterGVN( PhaseIterGVN *igvn, const char *dummy ); // Used after +VerifyOpto
  virtual PhaseIterGVN *is_IterGVN() { return this; }
  Unique_Node_List _worklist;       // Iterative worklist
  void optimize();
  Node* register_new_node_with_optimizer(Node* n, Node* orig = NULL);
  void remove_globally_dead_node( Node *dead );
  void remove_dead_node( Node *dead ) {
    assert(dead->outcnt() == 0 && !dead->is_top(), "node must be dead");
    remove_globally_dead_node(dead);
  }
  void add_users_to_worklist0( Node *n );
  void add_users_to_worklist ( Node *n );
  void replace_node( Node *old, Node *nn ) {
    add_users_to_worklist(old);
    hash_delete(old); // Yank from hash before hacking edges
    subsume_node(old, nn);
  }
  void rehash_node_delayed(Node* n) {
    hash_delete(n);
    _worklist.push(n);
  }
  void replace_input_of(Node* n, int i, Node* in) {
    rehash_node_delayed(n);
    n->set_req(i, in);
  }
  void delete_input_of(Node* n, int i) {
    rehash_node_delayed(n);
    n->del_req(i);
  }
  bool delay_transform() const { return _delay_transform; }
  void set_delay_transform(bool delay) {
    _delay_transform = delay;
  }
  Node* clone_loop_predicates(Node* old_entry, Node* new_entry, bool clone_limit_check);
  ProjNode* create_new_if_for_predicate(ProjNode* cont_proj, Node* new_entry,
                                        Deoptimization::DeoptReason reason);
  void remove_speculative_types();
  void check_no_speculative_types() {
    _table.check_no_speculative_types();
  }
#ifndef PRODUCT
protected:
  julong _verify_counter;
  julong _verify_full_passes;
  enum { _verify_window_size = 30 };
  Node* _verify_window[_verify_window_size];
  void verify_step(Node* n);
#endif
};
class PhaseCCP : public PhaseIterGVN {
  virtual Node *transform_once( Node *n );
public:
  PhaseCCP( PhaseIterGVN *igvn ); // Compute conditional constants
  NOT_PRODUCT( ~PhaseCCP(); )
  void analyze();
  virtual Node *transform( Node *n );
  void          do_transform();
  virtual const Type* saturate(const Type* new_type, const Type* old_type,
                               const Type* limit_type) const;
#ifndef PRODUCT
  static uint _total_invokes;    // For profiling, count invocations
  void    inc_invokes()          { ++PhaseCCP::_total_invokes; }
  static uint _total_constants;  // For profiling, count constants found
  uint   _count_constants;
  void    clear_constants()      { _count_constants = 0; }
  void    inc_constants()        { ++_count_constants; }
  uint    count_constants() const { return _count_constants; }
  static void print_statistics();
#endif
};
class PhasePeephole : public PhaseTransform {
  PhaseRegAlloc *_regalloc;
  PhaseCFG     &_cfg;
  virtual Node *transform( Node *n );
public:
  PhasePeephole( PhaseRegAlloc *regalloc, PhaseCFG &cfg );
  NOT_PRODUCT( ~PhasePeephole(); )
  void          do_transform();
#ifndef PRODUCT
  static uint _total_peepholes;  // For profiling, count peephole rules applied
  uint   _count_peepholes;
  void    clear_peepholes()      { _count_peepholes = 0; }
  void    inc_peepholes()        { ++_count_peepholes; }
  uint    count_peepholes() const { return _count_peepholes; }
  static void print_statistics();
#endif
};
#endif // SHARE_VM_OPTO_PHASEX_HPP
C:\hotspot-69087d08d473\src\share\vm/opto/postaloc.cpp
#include "precompiled.hpp"
#include "memory/allocation.inline.hpp"
#include "opto/chaitin.hpp"
#include "opto/machnode.hpp"
static bool register_contains_value(Node* val, OptoReg::Name reg, int n_regs,
                                    Node_List& value) {
  for (int i = 0; i < n_regs; i++) {
    OptoReg::Name nreg = OptoReg::add(reg,-i);
    if (value[nreg] != val)
      return false;
  }
  return true;
}
bool PhaseChaitin::may_be_copy_of_callee( Node *def ) const {
  if (_matcher.number_of_saved_registers() == 0) return false;
  const int limit = 60;
  int i;
  for( i=0; i < limit; i++ ) {
    if( def->is_Proj() && def->in(0)->is_Start() &&
        _matcher.is_save_on_entry(lrgs(_lrg_map.live_range_id(def)).reg()))
      return true;              // Direct use of callee-save proj
    if( def->is_Copy() )        // Copies carry value through
      def = def->in(def->is_Copy());
    else if( def->is_Phi() )    // Phis can merge it from any direction
      def = def->in(1);
    else
      break;
    guarantee(def != NULL, "must not resurrect dead copy");
  }
  return i == limit;
}
int PhaseChaitin::yank( Node *old, Block *current_block, Node_List *value, Node_List *regnd ) {
  int blk_adjust=0;
  Block *oldb = _cfg.get_block_for_node(old);
  oldb->find_remove(old);
  if (oldb == current_block) {
    blk_adjust++;
  }
  _cfg.unmap_node_from_block(old);
  OptoReg::Name old_reg = lrgs(_lrg_map.live_range_id(old)).reg();
  if( regnd && (*regnd)[old_reg]==old ) { // Instruction is currently available?
    value->map(old_reg,NULL);  // Yank from value/regnd maps
    regnd->map(old_reg,NULL);  // This register's value is now unknown
  }
  return blk_adjust;
}
#ifdef ASSERT
static bool expected_yanked_node(Node *old, Node *orig_old) {
  if (old->is_MachSpillCopy()) {
    return true;
  } else if (old->is_Con()) {
    return true;
  } else if (old->is_MachProj()) { // Dead kills projection of Con node
    return (old == orig_old);
  } else if (old->is_Copy()) {     // Dead copy of a callee-save value
    return (old == orig_old);
  } else if (old->is_MachTemp()) {
    return orig_old->is_Con();
  } else if (old->is_Phi()) { // Junk phi's
    return true;
  } else if (old->is_MachConstantBase()) {
    return (orig_old->is_Con() && orig_old->is_MachConstant());
  }
  return false;
}
#endif
int PhaseChaitin::yank_if_dead_recurse(Node *old, Node *orig_old, Block *current_block,
                                       Node_List *value, Node_List *regnd) {
  int blk_adjust=0;
  if (old->outcnt() == 0 && old != C->top()) {
#ifdef ASSERT
    if (!expected_yanked_node(old, orig_old)) {
      tty->print_cr("==============================================");
      tty->print_cr("orig_old:");
      orig_old->dump();
      tty->print_cr("old:");
      old->dump();
      assert(false, "unexpected yanked node");
    }
    if (old->is_Con())
      orig_old = old; // Reset to satisfy expected nodes checks.
#endif
    blk_adjust += yank(old, current_block, value, regnd);
    for (uint i = 1; i < old->req(); i++) {
      Node* n = old->in(i);
      if (n != NULL) {
        old->set_req(i, NULL);
        blk_adjust += yank_if_dead_recurse(n, orig_old, current_block, value, regnd);
      }
    }
    old->disconnect_inputs(NULL, C);
  }
  return blk_adjust;
}
int PhaseChaitin::use_prior_register( Node *n, uint idx, Node *def, Block *current_block, Node_List &value, Node_List &regnd ) {
  if( def == n->in(idx) ) return 0;
  if( def->outcnt() == 0 ) return 0;
  const LRG &def_lrg = lrgs(_lrg_map.live_range_id(def));
  OptoReg::Name def_reg = def_lrg.reg();
  const RegMask &use_mask = n->in_RegMask(idx);
  bool can_use = ( RegMask::can_represent(def_reg) ? (use_mask.Member(def_reg) != 0)
                                                   : (use_mask.is_AllStack() != 0));
  if (!RegMask::is_vector(def->ideal_reg())) {
    can_use = can_use && !use_mask.is_misaligned_pair() && !def_lrg.mask().is_misaligned_pair();
  }
  if (!can_use)
    return 0;
  Node *old = n->in(idx);
  if( may_be_copy_of_callee(def) ) {
    if( old->outcnt() > 1 ) return 0; // We're the not last user
    int idx = old->is_Copy();
    assert( idx, "chain of copies being removed" );
    Node *old2 = old->in(idx);  // Chain of copies
    if( old2->outcnt() > 1 ) return 0; // old is not the last user
    int idx2 = old2->is_Copy();
    if( !idx2 ) return 0;       // Not a chain of 2 copies
    if( def != old2->in(idx2) ) return 0; // Chain of exactly 2 copies
  }
  n->set_req(idx,def);
  _post_alloc++;
  return yank_if_dead(old,current_block,&value,&regnd);
}
Node *PhaseChaitin::skip_copies( Node *c ) {
  int idx = c->is_Copy();
  uint is_oop = lrgs(_lrg_map.live_range_id(c))._is_oop;
  while (idx != 0) {
    guarantee(c->in(idx) != NULL, "must not resurrect dead copy");
    if (lrgs(_lrg_map.live_range_id(c->in(idx)))._is_oop != is_oop) {
      break;  // casting copy, not the same value
    }
    c = c->in(idx);
    idx = c->is_Copy();
  }
  return c;
}
int PhaseChaitin::elide_copy( Node *n, int k, Block *current_block, Node_List &value, Node_List &regnd, bool can_change_regs ) {
  int blk_adjust = 0;
  uint nk_idx = _lrg_map.live_range_id(n->in(k));
  OptoReg::Name nk_reg = lrgs(nk_idx).reg();
  Node *x = n->in(k);
  int idx;
  while( (idx=x->is_Copy()) != 0 ) {
    Node *copy = x->in(idx);
    guarantee(copy != NULL, "must not resurrect dead copy");
    if(lrgs(_lrg_map.live_range_id(copy)).reg() != nk_reg) {
      break;
    }
    blk_adjust += use_prior_register(n,k,copy,current_block,value,regnd);
    if (n->in(k) != copy) {
      break; // Failed for some cutout?
    }
    x = copy;                   // Progress, try again
  }
  if( !can_change_regs )
    return blk_adjust;          // Only check stupid copies!
  if( &value == NULL ) return blk_adjust;
  Node *val = skip_copies(n->in(k));
  if (val == x) return blk_adjust; // No progress?
  int n_regs = RegMask::num_registers(val->ideal_reg());
  uint val_idx = _lrg_map.live_range_id(val);
  OptoReg::Name val_reg = lrgs(val_idx).reg();
  if (register_contains_value(val, val_reg, n_regs, value)) {
    blk_adjust += use_prior_register(n,k,regnd[val_reg],current_block,value,regnd);
    if( n->in(k) == regnd[val_reg] ) // Success!  Quit trying
      return blk_adjust;
  }
  const Type *t = val->is_Con() ? val->bottom_type() : NULL;
  for( uint reg = 0; reg < (uint)_max_reg; reg++ ) {
    if (reg == (uint)nk_reg) {
      bool ignore_self = true;
      x = n->in(k);
      DUIterator_Fast imax, i = x->fast_outs(imax);
      Node* first = x->fast_out(i); i++;
      while (i < imax && ignore_self) {
        Node* use = x->fast_out(i); i++;
        if (use != first) ignore_self = false;
      }
      if (ignore_self) continue;
    }
    Node *vv = value[reg];
    if (n_regs > 1) { // Doubles and vectors check for aligned-adjacent set
      uint last = (n_regs-1); // Looking for the last part of a set
      if ((reg&last) != last) continue; // Wrong part of a set
      if (!register_contains_value(vv, reg, n_regs, value)) continue; // Different value
    }
    if( vv == val ||            // Got a direct hit?
        (t && vv && vv->bottom_type() == t && vv->is_Mach() &&
         vv->as_Mach()->rule() == val->as_Mach()->rule()) ) { // Or same constant?
      assert( !n->is_Phi(), "cannot change registers at a Phi so easily" );
      if( OptoReg::is_stack(nk_reg) || // CISC-loading from stack OR
          OptoReg::is_reg(reg) || // turning into a register use OR
          regnd[reg]->outcnt()==1 ) { // last use of a spill-load turns into a CISC use
        blk_adjust += use_prior_register(n,k,regnd[reg],current_block,value,regnd);
        if( n->in(k) == regnd[reg] ) // Success!  Quit trying
          return blk_adjust;
      } // End of if not degrading to a stack
    } // End of if found value in another register
  } // End of scan all machine registers
  return blk_adjust;
}
bool PhaseChaitin::eliminate_copy_of_constant(Node* val, Node* n,
                                              Block *current_block,
                                              Node_List& value, Node_List& regnd,
                                              OptoReg::Name nreg, OptoReg::Name nreg2) {
  if (value[nreg] != val && val->is_Con() &&
      value[nreg] != NULL && value[nreg]->is_Con() &&
      (nreg2 == OptoReg::Bad || value[nreg] == value[nreg2]) &&
      value[nreg]->bottom_type() == val->bottom_type() &&
      value[nreg]->as_Mach()->rule() == val->as_Mach()->rule()) {
    for (DUIterator_Fast imax, i = n->fast_outs(imax); i < imax; i++) {
      Node* use = n->fast_out(i);
      if (use->is_Proj() && use->outcnt() == 0) {
        use->set_req(0, C->top());
        yank_if_dead(use, current_block, &value, &regnd);
        --i; --imax;
      }
    }
    _post_alloc++;
    return true;
  }
  return false;
}
void PhaseChaitin::merge_multidefs() {
  NOT_PRODUCT( Compile::TracePhase t3("mergeMultidefs", &_t_mergeMultidefs, TimeCompiler); )
  ResourceMark rm;
  RegToDefUseMap reg2defuse(_max_reg, _max_reg, RegDefUse());
  for (uint i = 0; i < _cfg.number_of_blocks(); i++) {
    Block* block = _cfg.get_block(i);
    for (uint j = 1; j < block->number_of_nodes(); j++) {
      Node* n = block->get_node(j);
      if (n->is_Phi()) continue;
      for (uint k = 1; k < n->req(); k++) {
        j += possibly_merge_multidef(n, k, block, reg2defuse);
      }
      uint lrg = _lrg_map.live_range_id(n);
      if (lrg > 0 && lrgs(lrg).is_multidef()) {
        OptoReg::Name reg = lrgs(lrg).reg();
        reg2defuse.at(reg).clear();
      }
    }
    for (int j = 0; j < reg2defuse.length(); j++) {
      reg2defuse.at(j).clear();
    }
  }
}
int PhaseChaitin::possibly_merge_multidef(Node *n, uint k, Block *block, RegToDefUseMap& reg2defuse) {
  int blk_adjust = 0;
  uint lrg = _lrg_map.live_range_id(n->in(k));
  if (lrg > 0 && lrgs(lrg).is_multidef()) {
    OptoReg::Name reg = lrgs(lrg).reg();
    Node* def = reg2defuse.at(reg).def();
    if (def != NULL && lrg == _lrg_map.live_range_id(def) && def != n->in(k)) {
      MachMergeNode* merge;
      if (def->is_MachMerge()) { // is it already a merge?
        merge = def->as_MachMerge();
      } else {
        merge = new (C) MachMergeNode(def);
        uint use_index = block->find_node(reg2defuse.at(reg).first_use());
        block->insert_node(merge, use_index++);
        _cfg.map_node_to_block(merge, block);
        _lrg_map.extend(merge->_idx, lrg);
        blk_adjust++;
        for (; use_index < block->number_of_nodes(); use_index++) {
          Node* use = block->get_node(use_index);
          if (use == n) {
            break;
          }
          use->replace_edge(def, merge);
        }
      }
      if (merge->find_edge(n->in(k)) == -1) {
        merge->add_req(n->in(k));
      }
      n->set_req(k, merge);
    }
    reg2defuse.at(reg).update(n->in(k), n);
  }
  return blk_adjust;
}
void PhaseChaitin::post_allocate_copy_removal() {
  NOT_PRODUCT( Compile::TracePhase t3("postAllocCopyRemoval", &_t_postAllocCopyRemoval, TimeCompiler); )
  ResourceMark rm;
  Node_List **blk2value = NEW_RESOURCE_ARRAY( Node_List *, _cfg.number_of_blocks() + 1);
  memset(blk2value, 0, sizeof(Node_List*) * (_cfg.number_of_blocks() + 1));
  Node_List **blk2regnd = NEW_RESOURCE_ARRAY( Node_List *, _cfg.number_of_blocks() + 1);
  memset(blk2regnd, 0, sizeof(Node_List*) * (_cfg.number_of_blocks() + 1));
  GrowableArray<Node_List*> free_list = GrowableArray<Node_List*>(16);
  for (uint i = 0; i < _cfg.number_of_blocks(); i++) {
    uint j;
    Block* block = _cfg.get_block(i);
    uint phi_dex;
    for (phi_dex = 1; phi_dex < block->number_of_nodes(); phi_dex++) {
      Node* phi = block->get_node(phi_dex);
      if (!phi->is_Phi()) {
        break;
      }
    }
    bool missing_some_inputs = false;
    Block *freed = NULL;
    for (j = 1; j < block->num_preds(); j++) {
      Block* pb = _cfg.get_block_for_node(block->pred(j));
      for (uint k = 1; k < phi_dex; k++) {
        elide_copy(block->get_node(k), j, block, *blk2value[pb->_pre_order], *blk2regnd[pb->_pre_order], false);
      }
      if (blk2value[pb->_pre_order]) { // Have a mapping on this edge?
        uint k;
        for (k = 0; k < pb->_num_succs; k++) {
          Block* pbsucc = pb->_succs[k];
          if (!blk2value[pbsucc->_pre_order] && pbsucc != block) {
            break;              // Found a future user
          }
        }
        if (k >= pb->_num_succs) { // No more uses, free!
          freed = pb;           // Record last block freed
          free_list.push(blk2value[pb->_pre_order]);
          free_list.push(blk2regnd[pb->_pre_order]);
        }
      } else {                  // This block has unvisited (loopback) inputs
        missing_some_inputs = true;
      }
    }
    Node_List &regnd = *(free_list.is_empty() ? new Node_List() : free_list.pop());
    Node_List &value = *(free_list.is_empty() ? new Node_List() : free_list.pop());
    assert( !freed || blk2value[freed->_pre_order] == &value, "" );
    value.map(_max_reg,NULL);
    regnd.map(_max_reg,NULL);
    blk2value[block->_pre_order] = &value;
    blk2regnd[block->_pre_order] = &regnd;
    if (missing_some_inputs) {
      for (uint k = 0; k < (uint)_max_reg; k++) {
        value.map(k,NULL);
        regnd.map(k,NULL);
      }
    } else {
      if( !freed ) {            // Didn't get a freebie prior block
        freed = _cfg.get_block_for_node(block->pred(1));
        Node_List &f_value = *blk2value[freed->_pre_order];
        Node_List &f_regnd = *blk2regnd[freed->_pre_order];
        for( uint k = 0; k < (uint)_max_reg; k++ ) {
          value.map(k,f_value[k]);
          regnd.map(k,f_regnd[k]);
        }
      }
      for (j = 1; j < block->num_preds(); j++) {
        Block* pb = _cfg.get_block_for_node(block->pred(j));
        if (pb == freed) {
          continue; // Did self already via freelist
        }
        Node_List &p_regnd = *blk2regnd[pb->_pre_order];
        for( uint k = 0; k < (uint)_max_reg; k++ ) {
          if( regnd[k] != p_regnd[k] ) { // Conflict on reaching defs?
            value.map(k,NULL); // Then no value handy
            regnd.map(k,NULL);
          }
        }
      }
    }
    for (j = 1; j < phi_dex; j++) {
      uint k;
      Node *phi = block->get_node(j);
      uint pidx = _lrg_map.live_range_id(phi);
      OptoReg::Name preg = lrgs(_lrg_map.live_range_id(phi)).reg();
      Node *u = NULL;
      for (k = 1; k < phi->req(); k++) {
        Node *x = phi->in(k);
        if( phi != x && u != x ) // Found a different input
          u = u ? NodeSentinel : x; // Capture unique input, or NodeSentinel for 2nd input
      }
      if (u != NodeSentinel) {    // Junk Phi.  Remove
        phi->replace_by(u);
        j -= yank_if_dead(phi, block, &value, &regnd);
        phi_dex--;
        continue;
      }
      if( pidx ) {
        value.map(preg,phi);
        regnd.map(preg,phi);
        int n_regs = RegMask::num_registers(phi->ideal_reg());
        for (int l = 1; l < n_regs; l++) {
          OptoReg::Name preg_lo = OptoReg::add(preg,-l);
          value.map(preg_lo,phi);
          regnd.map(preg_lo,phi);
        }
      }
    }
    for (j = phi_dex; j < block->number_of_nodes(); j++) {
      Node* n = block->get_node(j);
      if(n->outcnt() == 0 &&   // Dead?
         n != C->top() &&      // (ignore TOP, it has no du info)
         !n->is_Proj() ) {     // fat-proj kills
        j -= yank_if_dead(n, block, &value, &regnd);
        continue;
      }
      uint k;
      for (k = 1; k < n->req(); k++) {
        Node *def = n->in(k);   // n->in(k) is a USE; def is the DEF for this USE
        guarantee(def != NULL, "no disconnected nodes at this point");
        uint useidx = _lrg_map.live_range_id(def); // useidx is the live range index for this USE
        if( useidx ) {
          OptoReg::Name ureg = lrgs(useidx).reg();
          if( !value[ureg] ) {
            int idx;            // Skip occasional useless copy
            while( (idx=def->is_Copy()) != 0 &&
                   def->in(idx) != NULL &&  // NULL should not happen
                   ureg == lrgs(_lrg_map.live_range_id(def->in(idx))).reg())
              def = def->in(idx);
            Node *valdef = skip_copies(def); // tighten up val through non-useless copies
            value.map(ureg,valdef); // record improved reaching-def info
            regnd.map(ureg,   def);
            uint def_ideal_reg = def->ideal_reg();
            int n_regs = RegMask::num_registers(def_ideal_reg);
            for (int l = 1; l < n_regs; l++) {
              OptoReg::Name ureg_lo = OptoReg::add(ureg,-l);
              if (!value[ureg_lo] &&
                  (!RegMask::can_represent(ureg_lo) ||
                   lrgs(useidx).mask().Member(ureg_lo))) { // Nearly always adjacent
                value.map(ureg_lo,valdef); // record improved reaching-def info
                regnd.map(ureg_lo,   def);
              }
            }
          }
        }
      }
      const uint two_adr = n->is_Mach() ? n->as_Mach()->two_adr() : 0;
      for (k = 1; k < n->req(); k++) {
        j -= elide_copy(n, k, block, value, regnd, two_adr != k);
      }
      uint lidx = _lrg_map.live_range_id(n);
      if (!lidx) {
        continue;
      }
      OptoReg::Name nreg = lrgs(lidx).reg();
      Node *val = skip_copies(n);
      if (regnd[nreg] != NULL && regnd[nreg]->outcnt() == 0) {
        regnd.map(nreg, NULL);
        value.map(nreg, NULL);
      }
      uint n_ideal_reg = n->ideal_reg();
      int n_regs = RegMask::num_registers(n_ideal_reg);
      if (n_regs == 1) {
        if( value[nreg] != val ) {
          if (eliminate_copy_of_constant(val, n, block, value, regnd, nreg, OptoReg::Bad)) {
            j -= replace_and_yank_if_dead(n, nreg, block, value, regnd);
          } else {
            regnd.map(nreg,n);
            value.map(nreg,val);
          }
        } else if( !may_be_copy_of_callee(n) ) {
          assert(n->is_Copy(), "");
          j -= replace_and_yank_if_dead(n, nreg, block, value, regnd);
        }
      } else if (RegMask::is_vector(n_ideal_reg)) {
        if (!register_contains_value(val, nreg, n_regs, value)) {
          regnd.map(nreg,n);
          value.map(nreg,val);
          for (int l = 1; l < n_regs; l++) {
            OptoReg::Name nreg_lo = OptoReg::add(nreg,-l);
            regnd.map(nreg_lo, n );
            value.map(nreg_lo,val);
          }
        } else if (n->is_Copy()) {
          j -= replace_and_yank_if_dead(n, nreg, block, value, regnd);
        }
      } else {
        OptoReg::Name nreg_lo = OptoReg::add(nreg,-1);
        if( RegMask::can_represent(nreg_lo) &&     // Either a spill slot, or
            !lrgs(lidx).mask().Member(nreg_lo) ) { // Nearly always adjacent
          RegMask tmp = lrgs(lidx).mask();
          tmp.Remove(nreg);
          nreg_lo = tmp.find_first_elem();
        }
        if (value[nreg] != val || value[nreg_lo] != val) {
          if (eliminate_copy_of_constant(val, n, block, value, regnd, nreg, nreg_lo)) {
            j -= replace_and_yank_if_dead(n, nreg, block, value, regnd);
          } else {
            regnd.map(nreg   , n );
            regnd.map(nreg_lo, n );
            value.map(nreg   ,val);
            value.map(nreg_lo,val);
          }
        } else if (!may_be_copy_of_callee(n)) {
          assert(n->is_Copy(), "");
          j -= replace_and_yank_if_dead(n, nreg, block, value, regnd);
        }
      }
      if( n_ideal_reg == MachProjNode::fat_proj ) {
        RegMask rm = n->out_RegMask();
        nreg = rm.find_first_elem();
        while( OptoReg::is_valid(nreg)) {
          rm.Remove(nreg);
          value.map(nreg,n);
          regnd.map(nreg,n);
          nreg = rm.find_first_elem();
        }
      }
    } // End of for all instructions in the block
  } // End for all blocks
}
C:\hotspot-69087d08d473\src\share\vm/opto/regalloc.cpp
#include "precompiled.hpp"
#include "opto/regalloc.hpp"
static const int NodeRegsOverflowSize = 200;
void (*PhaseRegAlloc::_alloc_statistics[MAX_REG_ALLOCATORS])();
int PhaseRegAlloc::_num_allocators = 0;
#ifndef PRODUCT
int PhaseRegAlloc::_total_framesize = 0;
int PhaseRegAlloc::_max_framesize = 0;
#endif
PhaseRegAlloc::PhaseRegAlloc( uint unique, PhaseCFG &cfg,
                              Matcher &matcher,
                              void (*pr_stats)() ):
               Phase(Register_Allocation), _cfg(cfg), _matcher(matcher),
               _node_oops(Thread::current()->resource_area()),
               _node_regs(0),
               _node_regs_max_index(0),
               _framesize(0xdeadbeef)
{
    int i;
    for (i=0; i < _num_allocators; i++) {
        if (_alloc_statistics[i] == pr_stats)
            return;
    }
    assert((_num_allocators + 1) < MAX_REG_ALLOCATORS, "too many register allocators");
    _alloc_statistics[_num_allocators++] = pr_stats;
}
int PhaseRegAlloc::reg2offset_unchecked( OptoReg::Name reg ) const {
  int slot = (reg < _matcher._new_SP)
    ? reg - OptoReg::stack0() + _framesize
    : reg - _matcher._new_SP;
  return slot*VMRegImpl::stack_slot_size;
}
int PhaseRegAlloc::reg2offset( OptoReg::Name reg ) const {
  assert( reg <  _matcher._old_SP ||
          (reg >= OptoReg::add(_matcher._old_SP,C->out_preserve_stack_slots()) &&
           reg <  _matcher._in_arg_limit) ||
          reg >=  OptoReg::add(_matcher._new_SP, C->out_preserve_stack_slots()) ||
          reg == _matcher.return_addr(),
          "register allocated in a preserve area" );
  return reg2offset_unchecked( reg );
}
OptoReg::Name PhaseRegAlloc::offset2reg(int stk_offset) const {
  int slot = stk_offset / jintSize;
  int reg = (slot < (int) _framesize)
    ? slot + _matcher._new_SP
    : OptoReg::stack2reg(slot) - _framesize;
  assert(stk_offset == reg2offset((OptoReg::Name) reg),
         "offset2reg does not invert properly");
  return (OptoReg::Name) reg;
}
void PhaseRegAlloc::set_oop( const Node *n, bool is_an_oop ) {
  if( is_an_oop ) {
    _node_oops.set(n->_idx);
  }
}
bool PhaseRegAlloc::is_oop( const Node *n ) const {
  return _node_oops.test(n->_idx) != 0;
}
void PhaseRegAlloc::alloc_node_regs(int size) {
  _node_regs_max_index = size + (size >> 1) + NodeRegsOverflowSize;
  _node_regs = NEW_RESOURCE_ARRAY( OptoRegPair, _node_regs_max_index );
  for( uint i = size; i < _node_regs_max_index; ++i )
    _node_regs[i].set_bad();
}
#ifndef PRODUCT
void
PhaseRegAlloc::print_statistics() {
  tty->print_cr("Total frameslots = %d, Max frameslots = %d", _total_framesize, _max_framesize);
  int i;
  for (i=0; i < _num_allocators; i++) {
    _alloc_statistics[i]();
  }
}
#endif
C:\hotspot-69087d08d473\src\share\vm/opto/regalloc.hpp
#ifndef SHARE_VM_OPTO_REGALLOC_HPP
#define SHARE_VM_OPTO_REGALLOC_HPP
#include "code/vmreg.hpp"
#include "opto/block.hpp"
#include "opto/matcher.hpp"
#include "opto/phase.hpp"
class Node;
class Matcher;
class PhaseCFG;
#define  MAX_REG_ALLOCATORS   10
class PhaseRegAlloc : public Phase {
  friend class VMStructs;
  static void (*_alloc_statistics[MAX_REG_ALLOCATORS])();
  static int _num_allocators;
protected:
  OptoRegPair  *_node_regs;
  uint         _node_regs_max_index;
  VectorSet    _node_oops;         // Mapping from node indices to oopiness
  void alloc_node_regs(int size);  // allocate _node_regs table with at least "size" elements
  PhaseRegAlloc( uint unique, PhaseCFG &cfg, Matcher &matcher,
                 void (*pr_stats)());
public:
  PhaseCFG &_cfg;               // Control flow graph
  uint _framesize;              // Size of frame in stack-slots. not counting preserve area
  OptoReg::Name _max_reg;       // Past largest register seen
  Matcher &_matcher;            // Convert Ideal to MachNodes
  uint node_regs_max_index() const { return _node_regs_max_index; }
  OptoReg::Name get_reg_first( const Node *n ) const {
    debug_only( if( n->_idx >= _node_regs_max_index ) n->dump(); );
    assert( n->_idx < _node_regs_max_index, "Exceeded _node_regs array");
    return _node_regs[n->_idx].first();
  }
  OptoReg::Name get_reg_second( const Node *n ) const {
    debug_only( if( n->_idx >= _node_regs_max_index ) n->dump(); );
    assert( n->_idx < _node_regs_max_index, "Exceeded _node_regs array");
    return _node_regs[n->_idx].second();
  }
  virtual void Register_Allocate() = 0;
  virtual void add_reference( const Node *node, const Node *old_node) = 0;
  void set_bad( uint idx ) {
    assert( idx < _node_regs_max_index, "Exceeded _node_regs array");
    _node_regs[idx].set_bad();
  }
  void set1( uint idx, OptoReg::Name reg ) {
    assert( idx < _node_regs_max_index, "Exceeded _node_regs array");
    _node_regs[idx].set1(reg);
  }
  void set2( uint idx, OptoReg::Name reg ) {
    assert( idx < _node_regs_max_index, "Exceeded _node_regs array");
    _node_regs[idx].set2(reg);
  }
  void set_pair( uint idx, OptoReg::Name hi, OptoReg::Name lo ) {
    assert( idx < _node_regs_max_index, "Exceeded _node_regs array");
    _node_regs[idx].set_pair(hi, lo);
  }
  void set_ptr( uint idx, OptoReg::Name reg ) {
    assert( idx < _node_regs_max_index, "Exceeded _node_regs array");
    _node_regs[idx].set_ptr(reg);
  }
  void set_oop( const Node *n, bool );
  bool is_oop( const Node *n ) const;
  int reg2offset          ( OptoReg::Name reg ) const;
  int reg2offset_unchecked( OptoReg::Name reg ) const;
  OptoReg::Name offset2reg( int stk_offset ) const;
  int get_encode(const Node *n) const {
    assert( n->_idx < _node_regs_max_index, "Exceeded _node_regs array");
    OptoReg::Name first = _node_regs[n->_idx].first();
    OptoReg::Name second = _node_regs[n->_idx].second();
    assert( !OptoReg::is_valid(second) || second == first+1, "" );
    assert(OptoReg::is_reg(first), "out of range");
    return Matcher::_regEncode[first];
  }
#ifndef PRODUCT
  static int _total_framesize;
  static int _max_framesize;
  virtual void dump_frame() const = 0;
  virtual char *dump_register( const Node *n, char *buf  ) const = 0;
  static void print_statistics();
#endif
};
#endif // SHARE_VM_OPTO_REGALLOC_HPP
C:\hotspot-69087d08d473\src\share\vm/opto/regmask.cpp
#include "precompiled.hpp"
#include "opto/compile.hpp"
#include "opto/regmask.hpp"
#if defined AD_MD_HPP
# include AD_MD_HPP
#elif defined TARGET_ARCH_MODEL_x86_32
# include "adfiles/ad_x86_32.hpp"
#elif defined TARGET_ARCH_MODEL_x86_64
# include "adfiles/ad_x86_64.hpp"
#elif defined TARGET_ARCH_MODEL_aarch64
# include "adfiles/ad_aarch64.hpp"
#elif defined TARGET_ARCH_MODEL_sparc
# include "adfiles/ad_sparc.hpp"
#elif defined TARGET_ARCH_MODEL_zero
# include "adfiles/ad_zero.hpp"
#elif defined TARGET_ARCH_MODEL_ppc_64
# include "adfiles/ad_ppc_64.hpp"
#endif
#define RM_SIZE _RM_SIZE /* a constant private to the class RegMask */
int find_lowest_bit( uint32 mask ) {
  int n = 0;
  if( (mask & 0xffff) == 0 ) {
    mask >>= 16;
    n += 16;
  }
  if( (mask & 0xff) == 0 ) {
    mask >>= 8;
    n += 8;
  }
  if( (mask & 0xf) == 0 ) {
    mask >>= 4;
    n += 4;
  }
  if( (mask & 0x3) == 0 ) {
    mask >>= 2;
    n += 2;
  }
  if( (mask & 0x1) == 0 ) {
    mask >>= 1;
     n += 1;
  }
  if( mask == 0 ) {
    n = 32;
  }
  return n;
}
int find_hihghest_bit( uint32 mask ) {
  int n = 0;
  if( mask > 0xffff ) {
    mask >>= 16;
    n += 16;
  }
  if( mask > 0xff ) {
    mask >>= 8;
    n += 8;
  }
  if( mask > 0xf ) {
    mask >>= 4;
    n += 4;
  }
  if( mask > 0x3 ) {
    mask >>= 2;
    n += 2;
  }
  if( mask > 0x1 ) {
    mask >>= 1;
    n += 1;
  }
  if( mask == 0 ) {
    n = 32;
  }
  return n;
}
#ifndef PRODUCT
void OptoReg::dump(int r, outputStream *st) {
  switch (r) {
  case Special: st->print("r---"); break;
  case Bad:     st->print("rBAD"); break;
  default:
    if (r < _last_Mach_Reg) st->print("%s", Matcher::regName[r]);
    else st->print("rS%d",r);
    break;
  }
}
#endif
const RegMask RegMask::Empty(
# define BODY(I) 0,
  FORALL_BODY
# undef BODY
  0
);
bool RegMask::is_vector(uint ireg) {
  return (ireg == Op_VecS || ireg == Op_VecD || ireg == Op_VecX || ireg == Op_VecY);
}
int RegMask::num_registers(uint ireg) {
    switch(ireg) {
      case Op_VecY:
        return 8;
      case Op_VecX:
        return 4;
      case Op_VecD:
      case Op_RegD:
      case Op_RegL:
#ifdef _LP64
      case Op_RegP:
#endif
        return 2;
    }
    return 1;
}
OptoReg::Name RegMask::find_first_pair() const {
  verify_pairs();
  for( int i = 0; i < RM_SIZE; i++ ) {
    if( _A[i] ) {               // Found some bits
      int bit = _A[i] & -_A[i]; // Extract low bit
      return OptoReg::Name((i<<_LogWordBits)+find_lowest_bit(bit)+1);
    }
  }
  return OptoReg::Bad;
}
void RegMask::clear_to_pairs() {
  for( int i = 0; i < RM_SIZE; i++ ) {
    int bits = _A[i];
    bits &= ((bits & 0x55555555)<<1); // 1 hi-bit set for each pair
    bits |= (bits>>1);          // Smear 1 hi-bit into a pair
    _A[i] = bits;
  }
  verify_pairs();
}
void RegMask::smear_to_pairs() {
  for( int i = 0; i < RM_SIZE; i++ ) {
    int bits = _A[i];
    bits |= ((bits & 0x55555555)<<1); // Smear lo bit hi per pair
    bits |= ((bits & 0xAAAAAAAA)>>1); // Smear hi bit lo per pair
    _A[i] = bits;
  }
  verify_pairs();
}
bool RegMask::is_aligned_pairs() const {
  for( int i = 0; i < RM_SIZE; i++ ) {
    int bits = _A[i];
    while( bits ) {             // Check bits for pairing
      int bit = bits & -bits;   // Extract low bit
      if( (bit & 0x55555555) == 0 ) return false;
      bits -= bit;              // Remove bit from mask
      if( (bits & (bit<<1)) == 0 ) return false;
      bits -= (bit<<1);         // Remove other halve of pair
    }
  }
  return true;
}
int RegMask::is_bound1() const {
  if( is_AllStack() ) return false;
  int bit = -1;                 // Set to hold the one bit allowed
  for( int i = 0; i < RM_SIZE; i++ ) {
    if( _A[i] ) {               // Found some bits
      if( bit != -1 ) return false; // Already had bits, so fail
      bit = _A[i] & -_A[i];     // Extract 1 bit from mask
      if( bit != _A[i] ) return false; // Found many bits, so fail
    }
  }
  return true;
}
int RegMask::is_bound_pair() const {
  if( is_AllStack() ) return false;
  int bit = -1;                 // Set to hold the one bit allowed
  for( int i = 0; i < RM_SIZE; i++ ) {
    if( _A[i] ) {               // Found some bits
      if( bit != -1 ) return false; // Already had bits, so fail
      bit = _A[i] & -(_A[i]);   // Extract 1 bit from mask
      if( (bit << 1) != 0 ) {   // Bit pair stays in same word?
        if( (bit | (bit<<1)) != _A[i] )
          return false;         // Require adjacent bit pair and no more bits
      } else {                  // Else its a split-pair case
        if( bit != _A[i] ) return false; // Found many bits, so fail
        i++;                    // Skip iteration forward
        if( i >= RM_SIZE || _A[i] != 1 )
          return false; // Require 1 lo bit in next word
      }
    }
  }
  return true;
}
static int low_bits[3] = { 0x55555555, 0x11111111, 0x01010101 };
OptoReg::Name RegMask::find_first_set(const int size) const {
  verify_sets(size);
  for (int i = 0; i < RM_SIZE; i++) {
    if (_A[i]) {                // Found some bits
      int bit = _A[i] & -_A[i]; // Extract low bit
      return OptoReg::Name((i<<_LogWordBits)+find_lowest_bit(bit)+(size-1));
    }
  }
  return OptoReg::Bad;
}
void RegMask::clear_to_sets(const int size) {
  if (size == 1) return;
  assert(2 <= size && size <= 8, "update low bits table");
  assert(is_power_of_2(size), "sanity");
  int low_bits_mask = low_bits[size>>2];
  for (int i = 0; i < RM_SIZE; i++) {
    int bits = _A[i];
    int sets = (bits & low_bits_mask);
    for (int j = 1; j < size; j++) {
      sets = (bits & (sets<<1)); // filter bits which produce whole sets
    }
    sets |= (sets>>1);           // Smear 1 hi-bit into a set
    if (size > 2) {
      sets |= (sets>>2);         // Smear 2 hi-bits into a set
      if (size > 4) {
        sets |= (sets>>4);       // Smear 4 hi-bits into a set
      }
    }
    _A[i] = sets;
  }
  verify_sets(size);
}
void RegMask::smear_to_sets(const int size) {
  if (size == 1) return;
  assert(2 <= size && size <= 8, "update low bits table");
  assert(is_power_of_2(size), "sanity");
  int low_bits_mask = low_bits[size>>2];
  for (int i = 0; i < RM_SIZE; i++) {
    int bits = _A[i];
    int sets = 0;
    for (int j = 0; j < size; j++) {
      sets |= (bits & low_bits_mask);  // collect partial bits
      bits  = bits>>1;
    }
    sets |= (sets<<1);           // Smear 1 lo-bit  into a set
    if (size > 2) {
      sets |= (sets<<2);         // Smear 2 lo-bits into a set
      if (size > 4) {
        sets |= (sets<<4);       // Smear 4 lo-bits into a set
      }
    }
    _A[i] = sets;
  }
  verify_sets(size);
}
bool RegMask::is_aligned_sets(const int size) const {
  if (size == 1) return true;
  assert(2 <= size && size <= 8, "update low bits table");
  assert(is_power_of_2(size), "sanity");
  int low_bits_mask = low_bits[size>>2];
  for (int i = 0; i < RM_SIZE; i++) {
    int bits = _A[i];
    while (bits) {              // Check bits for pairing
      int bit = bits & -bits;   // Extract low bit
      if ((bit & low_bits_mask) == 0) return false;
      int hi_bit = bit << (size-1); // high bit
      int set = hi_bit + ((hi_bit-1) & ~(bit-1));
      if ((bits & set) != set) return false;
      bits -= set;  // Remove this set
    }
  }
  return true;
}
int RegMask::is_bound_set(const int size) const {
  if( is_AllStack() ) return false;
  assert(1 <= size && size <= 8, "update low bits table");
  int bit = -1;                 // Set to hold the one bit allowed
  for (int i = 0; i < RM_SIZE; i++) {
    if (_A[i] ) {               // Found some bits
      if (bit != -1)
       return false;            // Already had bits, so fail
      bit = _A[i] & -_A[i];     // Extract low bit from mask
      int hi_bit = bit << (size-1); // high bit
      if (hi_bit != 0) {        // Bit set stays in same word?
        int set = hi_bit + ((hi_bit-1) & ~(bit-1));
        if (set != _A[i])
          return false;         // Require adjacent bit set and no more bits
      } else {                  // Else its a split-set case
        if (((-1) & ~(bit-1)) != _A[i])
          return false;         // Found many bits, so fail
        i++;                    // Skip iteration forward and check high part
        int set = bit>>24;
        set = set & -set; // Remove sign extension.
        set = (((set << size) - 1) >> 8);
        if (i >= RM_SIZE || _A[i] != set)
          return false; // Require expected low bits in next word
      }
    }
  }
  return true;
}
bool RegMask::is_UP() const {
  if( is_AllStack() )
    return false;
  if( overlap(Matcher::STACK_ONLY_mask) )
    return false;
  return true;
}
uint RegMask::Size() const {
  extern uint8 bitsInByte[256];
  uint sum = 0;
  for( int i = 0; i < RM_SIZE; i++ )
    sum +=
      bitsInByte[(_A[i]>>24) & 0xff] +
      bitsInByte[(_A[i]>>16) & 0xff] +
      bitsInByte[(_A[i]>> 8) & 0xff] +
      bitsInByte[ _A[i]      & 0xff];
  return sum;
}
#ifndef PRODUCT
void RegMask::dump(outputStream *st) const {
  st->print("[");
  RegMask rm = *this;           // Structure copy into local temp
  OptoReg::Name start = rm.find_first_elem(); // Get a register
  if (OptoReg::is_valid(start)) { // Check for empty mask
    rm.Remove(start);           // Yank from mask
    OptoReg::dump(start, st);   // Print register
    OptoReg::Name last = start;
    while (1) {                 //
      OptoReg::Name reg = rm.find_first_elem(); // Get a register
      if (!OptoReg::is_valid(reg))
        break;                  // Empty mask, end loop
      rm.Remove(reg);           // Yank from mask
      if (last+1 == reg) {      // See if they are adjacent
        last = reg;
      } else {                  // Ending some kind of run
        if (start == last) {    // 1-register run; no special printing
        } else if (start+1 == last) {
          st->print(",");       // 2-register run; print as "rX,rY"
          OptoReg::dump(last, st);
        } else {                // Multi-register run; print as "rX-rZ"
          st->print("-");
          OptoReg::dump(last, st);
        }
        st->print(",");         // Seperate start of new run
        start = last = reg;     // Start a new register run
        OptoReg::dump(start, st); // Print register
      } // End of if ending a register run or not
    } // End of while regmask not empty
    if (start == last) {        // 1-register run; no special printing
    } else if (start+1 == last) {
      st->print(",");           // 2-register run; print as "rX,rY"
      OptoReg::dump(last, st);
    } else {                    // Multi-register run; print as "rX-rZ"
      st->print("-");
      OptoReg::dump(last, st);
    }
    if (rm.is_AllStack()) st->print("...");
  }
  st->print("]");
}
#endif
C:\hotspot-69087d08d473\src\share\vm/opto/regmask.hpp
#ifndef SHARE_VM_OPTO_REGMASK_HPP
#define SHARE_VM_OPTO_REGMASK_HPP
#include "code/vmreg.hpp"
#include "libadt/port.hpp"
#include "opto/optoreg.hpp"
#if defined ADGLOBALS_MD_HPP
# include ADGLOBALS_MD_HPP
#elif defined TARGET_ARCH_MODEL_x86_32
# include "adfiles/adGlobals_x86_32.hpp"
#elif defined TARGET_ARCH_MODEL_x86_64
# include "adfiles/adGlobals_x86_64.hpp"
#elif defined TARGET_ARCH_MODEL_aarch64
# include "adfiles/adGlobals_aarch64.hpp"
#elif defined TARGET_ARCH_MODEL_sparc
# include "adfiles/adGlobals_sparc.hpp"
#elif defined TARGET_ARCH_MODEL_zero
# include "adfiles/adGlobals_zero.hpp"
#elif defined TARGET_ARCH_MODEL_ppc_64
# include "adfiles/adGlobals_ppc_64.hpp"
#endif
int find_lowest_bit( uint32 mask );
int find_hihghest_bit( uint32 mask );
class RegMask VALUE_OBJ_CLASS_SPEC {
  union {
    double _dummy_force_double_alignment[RM_SIZE>>1];
    int _A[RM_SIZE];
  };
  enum {
    _WordBits    = BitsPerInt,
    _LogWordBits = LogBitsPerInt,
    _RM_SIZE     = RM_SIZE   // local constant, imported, then hidden by #undef
  };
public:
  enum { CHUNK_SIZE = RM_SIZE*_WordBits };
  enum { SlotsPerLong = 2,
         SlotsPerVecS = 1,
         SlotsPerVecD = 2,
         SlotsPerVecX = 4,
         SlotsPerVecY = 8 };
  RegMask(
#   define BODY(I) int a##I,
    FORALL_BODY
#   undef BODY
    int dummy = 0 ) {
#   define BODY(I) _A[I] = a##I;
    FORALL_BODY
#   undef BODY
  }
  RegMask( RegMask *rm ) {
#   define BODY(I) _A[I] = rm->_A[I];
    FORALL_BODY
#   undef BODY
  }
  RegMask( ) { Clear(); }
  RegMask( OptoReg::Name reg ) { Clear(); Insert(reg); }
  int Member( OptoReg::Name reg ) const {
    assert( reg < CHUNK_SIZE, "" );
    return _A[reg>>_LogWordBits] & (1<<(reg&(_WordBits-1)));
  }
  int is_AllStack() const { return _A[RM_SIZE-1] >> (_WordBits-1); }
  void set_AllStack() { Insert(OptoReg::Name(CHUNK_SIZE-1)); }
  int is_NotEmpty( ) const {
    int tmp = 0;
#   define BODY(I) tmp |= _A[I];
    FORALL_BODY
#   undef BODY
    return tmp;
  }
  OptoReg::Name find_first_elem() const {
    int base, bits;
#   define BODY(I) if( (bits = _A[I]) != 0 ) base = I<<_LogWordBits; else
    FORALL_BODY
#   undef BODY
      { base = OptoReg::Bad; bits = 1<<0; }
    return OptoReg::Name(base + find_lowest_bit(bits));
  }
  OptoReg::Name find_last_elem() const {
    int base, bits;
#   define BODY(I) if( (bits = _A[RM_SIZE-1-I]) != 0 ) base = (RM_SIZE-1-I)<<_LogWordBits; else
    FORALL_BODY
#   undef BODY
      { base = OptoReg::Bad; bits = 1<<0; }
    return OptoReg::Name(base + find_hihghest_bit(bits));
  }
  OptoReg::Name find_first_pair() const;
  void clear_to_pairs();
  void smear_to_pairs();
  void verify_pairs() const { assert( is_aligned_pairs(), "mask is not aligned, adjacent pairs" ); }
  bool is_aligned_pairs() const;
  bool is_misaligned_pair() const { return Size()==2 && !is_aligned_pairs(); }
  int is_bound1() const;
  int is_bound_pair() const;
  int is_bound(uint ireg) const {
    if (is_vector(ireg)) {
      if (is_bound_set(num_registers(ireg)))
        return true;
    } else if (is_bound1() || is_bound_pair()) {
      return true;
    }
    return false;
  }
  OptoReg::Name find_first_set(const int size) const;
  void clear_to_sets(const int size);
  void smear_to_sets(const int size);
  void verify_sets(int size) const { assert(is_aligned_sets(size), "mask is not aligned, adjacent sets"); }
  bool is_aligned_sets(const int size) const;
  bool is_misaligned_set(int size) const { return (int)Size()==size && !is_aligned_sets(size);}
  int is_bound_set(const int size) const;
  static bool is_vector(uint ireg);
  static int num_registers(uint ireg);
  int overlap( const RegMask &rm ) const {
    return
#   define BODY(I) (_A[I] & rm._A[I]) |
    FORALL_BODY
#   undef BODY
    0 ;
  }
  bool is_UP() const;
  void Clear( ) {
#   define BODY(I) _A[I] = 0;
    FORALL_BODY
#   undef BODY
  }
  void Set_All( ) {
#   define BODY(I) _A[I] = -1;
    FORALL_BODY
#   undef BODY
  }
  void Insert( OptoReg::Name reg ) {
    assert( reg < CHUNK_SIZE, "" );
    _A[reg>>_LogWordBits] |= (1<<(reg&(_WordBits-1)));
  }
  void Remove( OptoReg::Name reg ) {
    assert( reg < CHUNK_SIZE, "" );
    _A[reg>>_LogWordBits] &= ~(1<<(reg&(_WordBits-1)));
  }
  void OR( const RegMask &rm ) {
#   define BODY(I) this->_A[I] |= rm._A[I];
    FORALL_BODY
#   undef BODY
  }
  void AND( const RegMask &rm ) {
#   define BODY(I) this->_A[I] &= rm._A[I];
    FORALL_BODY
#   undef BODY
  }
  void SUBTRACT( const RegMask &rm ) {
#   define BODY(I) _A[I] &= ~rm._A[I];
    FORALL_BODY
#   undef BODY
  }
  uint Size() const;
#ifndef PRODUCT
  void print() const { dump(); }
  void dump(outputStream *st = tty) const; // Print a mask
#endif
  static const RegMask Empty;   // Common empty mask
  static bool can_represent(OptoReg::Name reg) {
    return (int)reg < (int)(CHUNK_SIZE-1);
  }
  static bool can_represent_arg(OptoReg::Name reg) {
    return (int)reg < (int)(CHUNK_SIZE-SlotsPerVecY);
  }
};
#undef RM_SIZE
#endif // SHARE_VM_OPTO_REGMASK_HPP
C:\hotspot-69087d08d473\src\share\vm/opto/reg_split.cpp
#include "precompiled.hpp"
#include "libadt/vectset.hpp"
#include "memory/allocation.inline.hpp"
#include "opto/addnode.hpp"
#include "opto/c2compiler.hpp"
#include "opto/callnode.hpp"
#include "opto/cfgnode.hpp"
#include "opto/chaitin.hpp"
#include "opto/loopnode.hpp"
#include "opto/machnode.hpp"
static const char out_of_nodes[] = "out of nodes during split";
Node *PhaseChaitin::get_spillcopy_wide( Node *def, Node *use, uint uidx ) {
  uint ireg = def->ideal_reg();
  if( ireg == 0 || ireg == Op_RegFlags ) {
    assert(false, "attempted to spill a non-spillable item");
    C->record_method_not_compilable("attempted to spill a non-spillable item");
    return NULL;
  }
  if (C->check_node_count(NodeLimitFudgeFactor, out_of_nodes)) {
    return NULL;
  }
  const RegMask *i_mask = &def->out_RegMask();
  const RegMask *w_mask = C->matcher()->idealreg2spillmask[ireg];
  const RegMask *o_mask = use ? &use->in_RegMask(uidx) : w_mask;
  const RegMask *w_i_mask = w_mask->overlap( *i_mask ) ? w_mask : i_mask;
  const RegMask *w_o_mask;
  int num_regs = RegMask::num_registers(ireg);
  bool is_vect = RegMask::is_vector(ireg);
  if( w_mask->overlap( *o_mask ) && // Overlap AND
      ((num_regs == 1) // Single use or aligned
        ||  is_vect    // or vector
        || !is_vect && o_mask->is_aligned_pairs()) ) {
    assert(!is_vect || o_mask->is_aligned_sets(num_regs), "vectors are aligned");
    w_o_mask = w_mask;
  } else {                      // wide ideal mask does not overlap with o_mask
    w_o_mask = o_mask;          // Must target desired registers
    if( !C->matcher()->idealreg2regmask[ireg]->overlap( *o_mask) && o_mask->is_UP() )
      w_i_mask = &C->FIRST_STACK_mask();
  }
  return new (C) MachSpillCopyNode( def, *w_i_mask, *w_o_mask );
}
void PhaseChaitin::insert_proj( Block *b, uint i, Node *spill, uint maxlrg ) {
  while( i < b->number_of_nodes() &&
         (b->get_node(i)->is_Proj() ||
          b->get_node(i)->is_Phi() ) )
    i++;
  if( b->get_node(i)->is_Catch() ) {
    while( 1 ) {
      const CatchProjNode *cp = b->get_node(++i)->as_CatchProj();
      if( cp->_con == CatchProjNode::fall_through_index )
        break;
    }
    int sidx = i - b->end_idx()-1;
    b = b->_succs[sidx];        // Switch to successor block
    i = 1;                      // Right at start of block
  }
  b->insert_node(spill, i);    // Insert node in block
  _cfg.map_node_to_block(spill,  b); // Update node->block mapping to reflect
  if( i <= b->_ihrp_index ) b->_ihrp_index++;
  if( i <= b->_fhrp_index ) b->_fhrp_index++;
  new_lrg(spill,maxlrg);
}
uint PhaseChaitin::split_DEF( Node *def, Block *b, int loc, uint maxlrg, Node **Reachblock, Node **debug_defs, GrowableArray<uint> splits, int slidx ) {
#ifdef ASSERT
  splits.at_put(slidx, splits.at(slidx)+1);
#endif
  Node *be = b->end();
  if( be->is_MachNullCheck() && be->in(1) == def && def == b->get_node(loc)) {
    b = b->_succs[b->get_node(b->end_idx()+1)->Opcode() == Op_IfTrue];
    loc = 0;                    // Just past the Region
  }
  assert( loc >= 0, "must insert past block head" );
  Node *spill = get_spillcopy_wide(def,NULL,0);
  if (!spill) {
    return 0;
  }
  insert_proj( b, loc+1, spill, maxlrg++);
  Reachblock[slidx] = spill;
  debug_defs[slidx] = spill;
  return maxlrg;
}
uint PhaseChaitin::split_USE( Node *def, Block *b, Node *use, uint useidx, uint maxlrg, bool def_down, bool cisc_sp, GrowableArray<uint> splits, int slidx ) {
#ifdef ASSERT
  splits.at_put(slidx, splits.at(slidx)+1);
#endif
  JVMState* jvms = use->jvms();
  uint debug_start = jvms ? jvms->debug_start() : 999999;
  uint debug_end   = jvms ? jvms->debug_end()   : 999999;
  if (useidx >= debug_start && useidx < debug_end) {
    if( def->is_Mach() ) {
      if( def_down ) {
        use->set_req(useidx, def);
      } else {
        Block *b = _cfg.get_block_for_node(use);
        int bindex = b->find_node(use);
        Node *spill = get_spillcopy_wide(def,use,useidx);
        if (!spill) {
          return 0;
        }
        insert_proj( b, bindex, spill, maxlrg++ );
        use->set_req(useidx,spill);
      }
      return maxlrg;
    }  // End special splitting for debug info live range
  }  // If debug info
  if( UseCISCSpill && cisc_sp ) {
    int inp = use->cisc_operand();
    if( inp != AdlcVMDeps::Not_cisc_spillable )
      inp = use->as_Mach()->operand_index(inp);
    if( inp == (int)useidx ) {
      use->set_req(useidx, def);
#ifndef PRODUCT
      if( TraceCISCSpill ) {
        tty->print("  set_split: ");
        use->dump();
      }
#endif
      return maxlrg;
    }
  }
  int bindex;
  if( use->is_Phi() ) {
    b = _cfg.get_block_for_node(b->pred(useidx));
    bindex = b->end_idx();
  } else {
    bindex = b->find_node(use);
  }
  Node *spill = get_spillcopy_wide( def, use, useidx );
  if( !spill ) return 0;        // Bailed out
  insert_proj( b, bindex, spill, maxlrg++ );
  use->set_req(useidx,spill);
  return maxlrg;
}
Node* clone_node(Node* def, Block *b, Compile* C) {
  if (def->needs_anti_dependence_check()) {
#ifdef ASSERT
    if (Verbose) {
      tty->print_cr("RA attempts to clone node with anti_dependence:");
      def->dump(-1); tty->cr();
      tty->print_cr("into block:");
      b->dump();
    }
#endif
    if (C->subsume_loads() == true && !C->failing()) {
      C->record_failure(C2Compiler::retry_no_subsuming_loads());
    } else {
      C->record_method_not_compilable("RA Split failed: attempt to clone node with anti_dependence");
    }
    return 0;
  }
  return def->clone();
}
Node *PhaseChaitin::split_Rematerialize( Node *def, Block *b, uint insidx, uint &maxlrg, GrowableArray<uint> splits, int slidx, uint *lrg2reach, Node **Reachblock, bool walkThru ) {
  if( def->req() > 1 ) {
    for( uint i = 1; i < def->req(); i++ ) {
      Node *in = def->in(i);
      uint lidx = _lrg_map.live_range_id(in);
      if (lidx < _lrg_map.max_lrg_id() && lrgs(lidx).is_singledef()) {
        continue;
      }
      Block *b_def = _cfg.get_block_for_node(def);
      int idx_def = b_def->find_node(def);
      Node *in_spill = get_spillcopy_wide( in, def, i );
      if( !in_spill ) return 0; // Bailed out
      insert_proj(b_def,idx_def,in_spill,maxlrg++);
      if( b_def == b )
        insidx++;
      def->set_req(i,in_spill);
    }
  }
  Node *spill = clone_node(def, b, C);
  if (spill == NULL || C->check_node_count(NodeLimitFudgeFactor, out_of_nodes)) {
    return 0;
  }
  if( spill->req() > 1 ) {
    for( uint i = 1; i < spill->req(); i++ ) {
      Node *in = spill->in(i);
      uint lidx = _lrg_map.find_id(in);
      if (walkThru) {
        while (in->is_SpillCopy() && lidx >= _lrg_map.max_lrg_id()) {
          in = in->in(1);
          lidx = _lrg_map.find_id(in);
        }
        if (lidx < _lrg_map.max_lrg_id() && lrgs(lidx).is_multidef()) {
          in = spill->in(i);
          lidx = _lrg_map.find_id(in);
        }
      }
      if (lidx < _lrg_map.max_lrg_id() && lrgs(lidx).reg() >= LRG::SPILL_REG) {
        Node *rdef = Reachblock[lrg2reach[lidx]];
        if (rdef) {
          spill->set_req(i, rdef);
        }
      }
    }
  }
  assert( spill->out_RegMask().is_UP(), "rematerialize to a reg" );
  set_was_spilled(spill);
  if( _spilled_once.test(def->_idx) )
    set_was_spilled(spill);
  insert_proj( b, insidx, spill, maxlrg++ );
#ifdef ASSERT
  splits.at_put(slidx, splits.at(slidx)+1);
#endif
  uint i = insidx+1;
  int found_projs = clone_projs( b, i, def, spill, maxlrg);
  if (found_projs > 0) {
    if (i <= b->_ihrp_index) {
      b->_ihrp_index += found_projs;
    }
    if (i <= b->_fhrp_index) {
      b->_fhrp_index += found_projs;
    }
  }
  return spill;
}
bool PhaseChaitin::is_high_pressure( Block *b, LRG *lrg, uint insidx ) {
  if( lrg->_was_spilled1 ) return true;
  bool is_float_or_vector = lrg->_is_float || lrg->_is_vector;
  uint hrp_idx = is_float_or_vector ? b->_fhrp_index : b->_ihrp_index;
  if( insidx < hrp_idx ) return false;
  int block_pres = is_float_or_vector ? b->_freg_pressure : b->_reg_pressure;
  int bound_pres = is_float_or_vector ? FLOATPRESSURE : INTPRESSURE;
  int lrg_pres = (lrg->get_invalid_mask_size() > lrg->num_regs())
    ? (lrg->get_invalid_mask_size() >> (lrg->num_regs()-1)) : bound_pres;
  return block_pres >= lrg_pres;
}
bool PhaseChaitin::prompt_use( Block *b, uint lidx ) {
  if (lrgs(lidx)._was_spilled2) {
    return false;
  }
  for( uint i = 1; i <= b->end_idx(); i++ ) {
    Node *n = b->get_node(i);
    if (n->is_Phi()) {
      continue;
    }
    for (uint j = 1; j < n->req(); j++) {
      if (_lrg_map.find_id(n->in(j)) == lidx) {
        return true;          // Found 1st use!
      }
    }
    if (n->out_RegMask().is_NotEmpty()) {
      return false;
    }
  }
  return false;
}
uint PhaseChaitin::Split(uint maxlrg, ResourceArea* split_arena) {
  NOT_PRODUCT( Compile::TracePhase t3("regAllocSplit", &_t_regAllocSplit, TimeCompiler); )
  ResourceMark rm(split_arena);
  uint                 bidx, pidx, slidx, insidx, inpidx, twoidx;
  uint                 non_phi = 1, spill_cnt = 0;
  Node                *n1, *n2, *n3;
  Node_List           *defs,*phis;
  bool                *UPblock;
  bool                 u1, u2, u3;
  Block               *b, *pred;
  PhiNode             *phi;
  GrowableArray<uint>  lidxs(split_arena, maxlrg, 0, 0);
  GrowableArray<uint>  splits(split_arena, maxlrg, 0, 0);
#define NEW_SPLIT_ARRAY(type, size)\
  (type*) split_arena->allocate_bytes((size) * sizeof(type))
  uint *lrg2reach = NEW_SPLIT_ARRAY(uint, maxlrg);
  defs = new Node_List();
  phis = new Node_List();
  for (bidx = 1; bidx < maxlrg; bidx++) {
    if (lrgs(bidx).alive() && lrgs(bidx).reg() >= LRG::SPILL_REG) {
      assert(!lrgs(bidx).mask().is_AllStack(),"AllStack should color");
      lrg2reach[bidx] = spill_cnt;
      spill_cnt++;
      lidxs.append(bidx);
#ifdef ASSERT
      splits.append(0);
#endif
#ifndef PRODUCT
      if( PrintOpto && WizardMode && lrgs(bidx)._was_spilled1 )
        tty->print_cr("Warning, 2nd spill of L%d",bidx);
#endif
    }
  }
  Node ***Reaches     = NEW_SPLIT_ARRAY( Node**, _cfg.number_of_blocks() + 1);
  bool  **UP          = NEW_SPLIT_ARRAY( bool*, _cfg.number_of_blocks() + 1);
  Node  **debug_defs  = NEW_SPLIT_ARRAY( Node*, spill_cnt );
  VectorSet **UP_entry= NEW_SPLIT_ARRAY( VectorSet*, spill_cnt );
  for (bidx = 0; bidx < _cfg.number_of_blocks() + 1; bidx++) {
    Reaches[bidx]     = NEW_SPLIT_ARRAY( Node*, spill_cnt );
    UP[bidx]          = NEW_SPLIT_ARRAY( bool, spill_cnt );
    Node **Reachblock = Reaches[bidx];
    bool *UPblock     = UP[bidx];
    for( slidx = 0; slidx < spill_cnt; slidx++ ) {
      UPblock[slidx] = true;     // Assume they start in registers
      Reachblock[slidx] = NULL;  // Assume that no def is present
    }
  }
#undef NEW_SPLIT_ARRAY
  for( slidx = 0; slidx < spill_cnt; slidx++ )
    UP_entry[slidx] = new VectorSet(split_arena);
  for( bidx = 0; bidx < _cfg.number_of_blocks(); bidx++ ) {
    if (C->check_node_count(spill_cnt, out_of_nodes)) {
      return 0;
    }
    b  = _cfg.get_block(bidx);
    Node** Reachblock = Reaches[b->_pre_order];
    UPblock    = UP[b->_pre_order];
    non_phi = 1;
    for( slidx = 0; slidx < spill_cnt; slidx++ ) {
      uint lidx = lidxs.at(slidx);
      if( lrgs(lidx).is_singledef() &&
          lrgs(lidx)._def->rematerialize() ) {
        Reachblock[slidx] = lrgs(lidx)._def;
        UPblock[slidx] = true;
        Block *pred1 = _cfg.get_block_for_node(b->pred(1));
        continue;
      }
      bool needs_phi = false;
      bool needs_split = false;
      bool has_phi = false;
      n1 = b->pred(1);
      pred = _cfg.get_block_for_node(n1);
      pidx = pred->_pre_order;
      Node **Ltmp = Reaches[pidx];
      bool  *Utmp = UP[pidx];
      n1 = Ltmp[slidx];
      u1 = Utmp[slidx];
      n3 = n1;
      u3 = u1;
      for( inpidx = 2; inpidx < b->num_preds(); inpidx++ ) {
        n2 = b->pred(inpidx);
        pred = _cfg.get_block_for_node(n2);
        pidx = pred->_pre_order;
        Ltmp = Reaches[pidx];
        Utmp = UP[pidx];
        n2 = Ltmp[slidx];
        u2 = Utmp[slidx];
        if( n1 != n2 ) {
          needs_phi = true;
        }
        if( n1 && n2 && (u1 != u2) ) {
          needs_split = true;
        }
        n1 = n2;
        u1 = u2;
        if( (n3 == NULL) && (n2 != NULL) ){
          n3 = n2;
          u3 = u2;
        }
      }  // End for all potential Phi inputs
      for( insidx = 1; insidx <= b->end_idx(); insidx++ ) {
        n1 = b->get_node(insidx);
        phi = n1->is_Phi() ? n1->as_Phi() : NULL;
        if( phi == NULL ) {
          non_phi = insidx;
          break;
        }
        if (_lrg_map.find_id(n1) == lidxs.at(slidx)) {
          needs_phi = false;
          has_phi = true;
          Reachblock[slidx] = phi;
          break;
        }  // end if found correct phi
      }  // end for all phi's
      if( needs_phi || has_phi ) {
        if( needs_phi ) {
          assert(n3,"No non-NULL reaching DEF for a Phi");
          phi = new (C) PhiNode(b->head(), n3->bottom_type());
          Reachblock[slidx] = phi;
          insert_proj(b, insidx++, phi, maxlrg++);
          non_phi++;
          _lrg_map.map(phi->_idx, lidx);
          assert(_lrg_map.find_id(phi) == lidx, "Bad update on Union-Find mapping");
        }  // end if not found correct phi
        assert(phi != NULL,"Must have a Phi Node here");
        phis->push(phi);
        UPblock[slidx] = true;  // Assume new DEF is UP
        if( is_high_pressure( b, &lrgs(lidx), b->end_idx()) && !prompt_use(b,lidx) )
          UPblock[slidx] = false;
        if( !needs_split && !u3 )
          UPblock[slidx] = false;
      }  // end if phi is needed
      else {
        n1 = b->pred(1);
        pred = _cfg.get_block_for_node(n1);
        pidx = pred->_pre_order;
        Node **Ltmp = Reaches[pidx];
        bool  *Utmp = UP[pidx];
        Reachblock[slidx] = Ltmp[slidx];
        UPblock[slidx] = Utmp[slidx];
      }  // end else no Phi is needed
    }  // end for all spilling live ranges
#ifndef PRODUCT
    if(trace_spilling()) {
      tty->print("/`\nBlock %d: ", b->_pre_order);
      tty->print("Reaching Definitions after Phi handling\n");
      for( uint x = 0; x < spill_cnt; x++ ) {
        tty->print("Spill Idx %d: UP %d: Node\n",x,UPblock[x]);
        if( Reachblock[x] )
          Reachblock[x]->dump();
        else
          tty->print("Undefined\n");
      }
    }
#endif
    for( insidx = 0; insidx < spill_cnt; insidx++ ) {
      debug_defs[insidx] = (UPblock[insidx]) ? NULL : Reachblock[insidx];
      if( UPblock[insidx] )     // Memoize UP decision at block start
        UP_entry[insidx]->set( b->_pre_order );
    }
    for( insidx = 1; insidx <= b->end_idx(); insidx++ ) {
      Node *n = b->get_node(insidx);
      uint defidx = _lrg_map.find_id(n);
      uint cnt = n->req();
      if (n->is_Phi()) {
        if (defidx < _lrg_map.max_lrg_id()) {
          if( lrgs(defidx).reg() < LRG::SPILL_REG ) {
            uint i;
            Node *u = NULL;
            for( i = 1; i < cnt; i++ ) {
              if( n->in(i) != u && n->in(i) != n ) {
                if( u != NULL ) // If it's the 2nd, bail out
                  break;
                u = n->in(i);   // Else record it
              }
            }
            assert( u, "at least 1 valid input expected" );
            if (i >= cnt) {    // Found one unique input
              assert(_lrg_map.find_id(n) == _lrg_map.find_id(u), "should be the same lrg");
              n->replace_by(u); // Then replace with unique input
              n->disconnect_inputs(NULL, C);
              b->remove_node(insidx);
              insidx--;
              b->_ihrp_index--;
              b->_fhrp_index--;
            }
          }
        }
        continue;
      }
      assert( insidx > b->_ihrp_index ||
              (b->_reg_pressure < (uint)INTPRESSURE) ||
              b->_ihrp_index > 4000000 ||
              b->_ihrp_index >= b->end_idx() ||
              !b->get_node(b->_ihrp_index)->is_Proj(), "" );
      assert( insidx > b->_fhrp_index ||
              (b->_freg_pressure < (uint)FLOATPRESSURE) ||
              b->_fhrp_index > 4000000 ||
              b->_fhrp_index >= b->end_idx() ||
              !b->get_node(b->_fhrp_index)->is_Proj(), "" );
      if( (insidx == b->_ihrp_index) || (insidx == b->_fhrp_index) ) {
        for( slidx = 0; slidx < spill_cnt; slidx++ ) {
          n1 = Reachblock[slidx];
          if( n1 == NULL ) continue;
          uint lidx = lidxs.at(slidx);
          if( UPblock[slidx] ) {
            if( is_high_pressure( b, &lrgs(lidx), insidx ) &&
                !n1->rematerialize() ) {
              if( debug_defs[slidx] != NULL ) {
                Reachblock[slidx] = debug_defs[slidx];
              }
              else {
                int insert_point = insidx-1;
                while( insert_point > 0 ) {
                  Node *n = b->get_node(insert_point);
                  if (n->is_Phi()) {
                    break;
                  }
                  if (_lrg_map.live_range_id(n) == lidx) {
                    break;
                  }
                  uint i;
                  for( i = 1; i < n->req(); i++ ) {
                    if (_lrg_map.live_range_id(n->in(i)) == lidx) {
                      break;
                    }
                  }
                  if (i < n->req()) {
                    break;
                  }
                  insert_point--;
                }
                uint orig_eidx = b->end_idx();
                maxlrg = split_DEF( n1, b, insert_point, maxlrg, Reachblock, debug_defs, splits, slidx);
                if (!maxlrg) {
                  return 0;
                }
                if (b->end_idx() > orig_eidx) {
                  insidx++;
                }
              }
              UPblock[slidx] = false;
#ifndef PRODUCT
              if( trace_spilling() ) {
                tty->print("\nNew Split DOWN DEF of Spill Idx ");
                tty->print("%d, UP %d:\n",slidx,false);
                n1->dump();
              }
#endif
            }
          }  // end if LRG is UP
        }  // end for all spilling live ranges
        assert( b->get_node(insidx) == n, "got insidx set incorrectly" );
      }  // end if crossing HRP Boundry
      if (defidx >= _lrg_map.max_lrg_id()) {
        continue;
      }
      LRG &deflrg = lrgs(defidx);
      uint copyidx = n->is_Copy();
      if (copyidx && defidx == _lrg_map.live_range_id(n->in(copyidx))) {
        n->replace_by( n->in(copyidx) );
        n->set_req( copyidx, NULL );
        b->remove_node(insidx--);
        b->_ihrp_index--; // Adjust the point where we go hi-pressure
        b->_fhrp_index--;
        continue;
      }

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值