/*
 * Copyright (c) 2005, 2015, Oracle and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 *
 */

#include "precompiled.hpp"
#include "ci/bcEscapeAnalyzer.hpp"
#include "compiler/compileLog.hpp"
#include "libadt/vectset.hpp"
#include "memory/allocation.hpp"
#include "opto/c2compiler.hpp"
#include "opto/callnode.hpp"
#include "opto/cfgnode.hpp"
#include "opto/compile.hpp"
#include "opto/escape.hpp"
#include "opto/phaseX.hpp"
#include "opto/rootnode.hpp"

ConnectionGraph::ConnectionGraph(Compile * C, PhaseIterGVN *igvn) :
  _nodes(C->comp_arena(), C->unique(), C->unique(), NULL),
  _in_worklist(C->comp_arena()),
  _next_pidx(0),
  _collecting(true),
  _verify(false),
  _compile(C),
  _igvn(igvn),
  _node_map(C->comp_arena()) {
  // Add unknown java object.
  add_java_object(C->top(), PointsToNode::GlobalEscape);
  phantom_obj = ptnode_adr(C->top()->_idx)->as_JavaObject();
  // Add ConP(#NULL) and ConN(#NULL) nodes.
  Node* oop_null = igvn->zerocon(T_OBJECT);
  assert(oop_null->_idx < nodes_size(), "should be created already");
  add_java_object(oop_null, PointsToNode::NoEscape);
  null_obj = ptnode_adr(oop_null->_idx)->as_JavaObject();
  if (UseCompressedOops) {
    Node* noop_null = igvn->zerocon(T_NARROWOOP);
    assert(noop_null->_idx < nodes_size(), "should be created already");
    map_ideal_node(noop_null, null_obj);
  }
  _pcmp_neq = NULL; // Should be initialized
  _pcmp_eq  = NULL;
}

bool ConnectionGraph::has_candidates(Compile *C) {
  // EA brings benefits only when the code has allocations and/or locks which
  // are represented by ideal Macro nodes.
  int cnt = C->macro_count();
  for (int i = 0; i < cnt; i++) {
    Node *n = C->macro_node(i);
    if (n->is_Allocate())
      return true;
    if (n->is_Lock()) {
      Node* obj = n->as_Lock()->obj_node()->uncast();
      if (!(obj->is_Parm() || obj->is_Con()))
        return true;
    }
    if (n->is_CallStaticJava() &&
        n->as_CallStaticJava()->is_boxing_method()) {
      return true;
    }
  }
  return false;
}

void ConnectionGraph::do_analysis(Compile *C, PhaseIterGVN *igvn) {
  Compile::TracePhase t2("escapeAnalysis", &Phase::_t_escapeAnalysis, true);
  ResourceMark rm;

  // Add ConP#NULL and ConN#NULL nodes before ConnectionGraph construction
  // to create space for them in ConnectionGraph::_nodes[].
  Node* oop_null = igvn->zerocon(T_OBJECT);
  Node* noop_null = igvn->zerocon(T_NARROWOOP);
  ConnectionGraph* congraph = new(C->comp_arena()) ConnectionGraph(C, igvn);
  // Perform escape analysis
  if (congraph->compute_escape()) {
    // There are non escaping objects.
    C->set_congraph(congraph);
  }
  // Cleanup.
  if (oop_null->outcnt() == 0)
    igvn->hash_delete(oop_null);
  if (noop_null->outcnt() == 0)
    igvn->hash_delete(noop_null);
}

bool ConnectionGraph::compute_escape() {
  Compile* C = _compile;
  PhaseGVN* igvn = _igvn;

  // Worklists used by EA.
  Unique_Node_List delayed_worklist;
  GrowableArray<Node*> alloc_worklist;
  GrowableArray<Node*> ptr_cmp_worklist;
  GrowableArray<Node*> storestore_worklist;
  GrowableArray<PointsToNode*>   ptnodes_worklist;
  GrowableArray<JavaObjectNode*> java_objects_worklist;
  GrowableArray<JavaObjectNode*> non_escaped_worklist;
  GrowableArray<FieldNode*>      oop_fields_worklist;
  DEBUG_ONLY( GrowableArray<Node*> addp_worklist; )

  { Compile::TracePhase t3("connectionGraph", &Phase::_t_connectionGraph, true);

  // 1. Populate Connection Graph (CG) with PointsTo nodes.
  ideal_nodes.map(C->live_nodes(), NULL);  // preallocate space
  // Initialize worklist
  if (C->root() != NULL) {
    ideal_nodes.push(C->root());
  }
  // Processed ideal nodes are unique on ideal_nodes list
  // but several ideal nodes are mapped to the phantom_obj.
  // To avoid duplicated entries on the following worklists
  // add the phantom_obj only once to them.
  ptnodes_worklist.append(phantom_obj);
  java_objects_worklist.append(phantom_obj);
  for( uint next = 0; next < ideal_nodes.size(); ++next ) {
    Node* n = ideal_nodes.at(next);
    // Create PointsTo nodes and add them to Connection Graph. Called
    // only once per ideal node since ideal_nodes is Unique_Node list.
    add_node_to_connection_graph(n, &delayed_worklist);
    PointsToNode* ptn = ptnode_adr(n->_idx);
    if (ptn != NULL && ptn != phantom_obj) {
      ptnodes_worklist.append(ptn);
      if (ptn->is_JavaObject()) {
        java_objects_worklist.append(ptn->as_JavaObject());
        if ((n->is_Allocate() || n->is_CallStaticJava()) &&
            (ptn->escape_state() < PointsToNode::GlobalEscape)) {
          // Only allocations and java static calls results are interesting.
          non_escaped_worklist.append(ptn->as_JavaObject());
        }
      } else if (ptn->is_Field() && ptn->as_Field()->is_oop()) {
        oop_fields_worklist.append(ptn->as_Field());
      }
    }
    if (n->is_MergeMem()) {
      // Collect all MergeMem nodes to add memory slices for
      // scalar replaceable objects in split_unique_types().
      _mergemem_worklist.append(n->as_MergeMem());
    } else if (OptimizePtrCompare && n->is_Cmp() &&
               (n->Opcode() == Op_CmpP || n->Opcode() == Op_CmpN)) {
      // Collect compare pointers nodes.
      ptr_cmp_worklist.append(n);
    } else if (n->is_MemBarStoreStore()) {
      // Collect all MemBarStoreStore nodes so that depending on the
      // escape status of the associated Allocate node some of them
      // may be eliminated.
      storestore_worklist.append(n);
    } else if (n->is_MemBar() && (n->Opcode() == Op_MemBarRelease) &&
               (n->req() > MemBarNode::Precedent)) {
      record_for_optimizer(n);
#ifdef ASSERT
    } else if (n->is_AddP()) {
      // Collect address nodes for graph verification.
      addp_worklist.append(n);
#endif
    }
    for (DUIterator_Fast imax, i = n->fast_outs(imax); i < imax; i++) {
      Node* m = n->fast_out(i);   // Get user
      ideal_nodes.push(m);
    }
  }
  if (non_escaped_worklist.length() == 0) {
    _collecting = false;
    return false; // Nothing to do.
  }
  // Add final simple edges to graph.
  while(delayed_worklist.size() > 0) {
    Node* n = delayed_worklist.pop();
    add_final_edges(n);
  }
  int ptnodes_length = ptnodes_worklist.length();

#ifdef ASSERT
  if (VerifyConnectionGraph) {
    // Verify that no new simple edges could be created and all
    // local vars has edges.
    _verify = true;
    for (int next = 0; next < ptnodes_length; ++next) {
      PointsToNode* ptn = ptnodes_worklist.at(next);
      add_final_edges(ptn->ideal_node());
      if (ptn->is_LocalVar() && ptn->edge_count() == 0) {
        ptn->dump();
        assert(ptn->as_LocalVar()->edge_count() > 0, "sanity");
      }
    }
    _verify = false;
  }
#endif
  // Bytecode analyzer BCEscapeAnalyzer, used for Call nodes
  // processing, calls to CI to resolve symbols (types, fields, methods)
  // referenced in bytecode. During symbol resolution VM may throw
  // an exception which CI cleans and converts to compilation failure.
  if (C->failing())  return false;

  // 2. Finish Graph construction by propagating references to all
  //    java objects through graph.
  if (!complete_connection_graph(ptnodes_worklist, non_escaped_worklist,
                                 java_objects_worklist, oop_fields_worklist)) {
    // All objects escaped or hit time or iterations limits.
    _collecting = false;
    return false;
  }

  // 3. Adjust scalar_replaceable state of nonescaping objects and push
  //    scalar replaceable allocations on alloc_worklist for processing
  //    in split_unique_types().
  int non_escaped_length = non_escaped_worklist.length();
  for (int next = 0; next < non_escaped_length; next++) {
    JavaObjectNode* ptn = non_escaped_worklist.at(next);
    bool noescape = (ptn->escape_state() == PointsToNode::NoEscape);
    Node* n = ptn->ideal_node();
    if (n->is_Allocate()) {
      n->as_Allocate()->_is_non_escaping = noescape;
    }
    if (n->is_CallStaticJava()) {
      n->as_CallStaticJava()->_is_non_escaping = noescape;
    }
    if (noescape && ptn->scalar_replaceable()) {
      adjust_scalar_replaceable_state(ptn);
      if (ptn->scalar_replaceable()) {
        alloc_worklist.append(ptn->ideal_node());
      }
    }
  }

#ifdef ASSERT
  if (VerifyConnectionGraph) {
    // Verify that graph is complete - no new edges could be added or needed.
    verify_connection_graph(ptnodes_worklist, non_escaped_worklist,
                            java_objects_worklist, addp_worklist);
  }
  assert(C->unique() == nodes_size(), "no new ideal nodes should be added during ConnectionGraph build");
  assert(null_obj->escape_state() == PointsToNode::NoEscape &&
         null_obj->edge_count() == 0 &&
         !null_obj->arraycopy_src() &&
         !null_obj->arraycopy_dst(), "sanity");
#endif

  _collecting = false;

  } // TracePhase t3("connectionGraph")

  // 4. Optimize ideal graph based on EA information.
  bool has_non_escaping_obj = (non_escaped_worklist.length() > 0);
  if (has_non_escaping_obj) {
    optimize_ideal_graph(ptr_cmp_worklist, storestore_worklist);
  }

#ifndef PRODUCT
  if (PrintEscapeAnalysis) {
    dump(ptnodes_worklist); // Dump ConnectionGraph
  }
#endif

  bool has_scalar_replaceable_candidates = (alloc_worklist.length() > 0);
#ifdef ASSERT
  if (VerifyConnectionGraph) {
    int alloc_length = alloc_worklist.length();
    for (int next = 0; next < alloc_length; ++next) {
      Node* n = alloc_worklist.at(next);
      PointsToNode* ptn = ptnode_adr(n->_idx);
      assert(ptn->escape_state() == PointsToNode::NoEscape && ptn->scalar_replaceable(), "sanity");
    }
  }
#endif

  // 5. Separate memory graph for scalar replaceable allcations.
  if (has_scalar_replaceable_candidates &&
      C->AliasLevel() >= 3 && EliminateAllocations) {
    // Now use the escape information to create unique types for
    // scalar replaceable objects.
    split_unique_types(alloc_worklist);
    if (C->failing())  return false;
    C->print_method(PHASE_AFTER_EA, 2);

#ifdef ASSERT
  } else if (Verbose && (PrintEscapeAnalysis || PrintEliminateAllocations)) {
    tty->print("=== No allocations eliminated for ");
    C->method()->print_short_name();
    if(!EliminateAllocations) {
      tty->print(" since EliminateAllocations is off ===");
    } else if(!has_scalar_replaceable_candidates) {
      tty->print(" since there are no scalar replaceable candidates ===");
    } else if(C->AliasLevel() < 3) {
      tty->print(" since AliasLevel < 3 ===");
    }
    tty->cr();
#endif
  }
  return has_non_escaping_obj;
}

// Utility function for nodes that load an object
void ConnectionGraph::add_objload_to_connection_graph(Node *n, Unique_Node_List *delayed_worklist) {
  // Using isa_ptr() instead of isa_oopptr() for LoadP and Phi because
  // ThreadLocal has RawPtr type.
  const Type* t = _igvn->type(n);
  if (t->make_ptr() != NULL) {
    Node* adr = n->in(MemNode::Address);
#ifdef ASSERT
    if (!adr->is_AddP()) {
      assert(_igvn->type(adr)->isa_rawptr(), "sanity");
    } else {
      assert((ptnode_adr(adr->_idx) == NULL ||
              ptnode_adr(adr->_idx)->as_Field()->is_oop()), "sanity");
    }
#endif
    add_local_var_and_edge(n, PointsToNode::NoEscape,
                           adr, delayed_worklist);
  }
}

// Populate Connection Graph with PointsTo nodes and create simple
// connection graph edges.
void ConnectionGraph::add_node_to_connection_graph(Node *n, Unique_Node_List *delayed_worklist) {
  assert(!_verify, "this method sould not be called for verification");
  PhaseGVN* igvn = _igvn;
  uint n_idx = n->_idx;
  PointsToNode* n_ptn = ptnode_adr(n_idx);
  if (n_ptn != NULL)
    return; // No need to redefine PointsTo node during first iteration.

  if (n->is_Call()) {
    // Arguments to allocation and locking don't escape.
    if (n->is_AbstractLock()) {
      // Put Lock and Unlock nodes on IGVN worklist to process them during
      // first IGVN optimization when escape information is still available.
      record_for_optimizer(n);
    } else if (n->is_Allocate()) {
      add_call_node(n->as_Call());
      record_for_optimizer(n);
    } else {
      if (n->is_CallStaticJava()) {
        const char* name = n->as_CallStaticJava()->_name;
        if (name != NULL && strcmp(name, "uncommon_trap") == 0)
          return; // Skip uncommon traps
      }
      // Don't mark as processed since call's arguments have to be processed.
      delayed_worklist->push(n);
      // Check if a call returns an object.
      if ((n->as_Call()->returns_pointer() &&
           n->as_Call()->proj_out(TypeFunc::Parms) != NULL) ||
          (n->is_CallStaticJava() &&
           n->as_CallStaticJava()->is_boxing_method())) {
        add_call_node(n->as_Call());
      }
    }
    return;
  }
  // Put this check here to process call arguments since some call nodes
  // point to phantom_obj.
  if (n_ptn == phantom_obj || n_ptn == null_obj)
    return; // Skip predefined nodes.

  int opcode = n->Opcode();
  switch (opcode) {
    case Op_AddP: {
      Node* base = get_addp_base(n);
      PointsToNode* ptn_base = ptnode_adr(base->_idx);
      // Field nodes are created for all field types. They are used in
      // adjust_scalar_replaceable_state() and split_unique_types().
      // Note, non-oop fields will have only base edges in Connection
      // Graph because such fields are not used for oop loads and stores.
      int offset = address_offset(n, igvn);
      add_field(n, PointsToNode::NoEscape, offset);
      if (ptn_base == NULL) {
        delayed_worklist->push(n); // Process it later.
      } else {
        n_ptn = ptnode_adr(n_idx);
        add_base(n_ptn->as_Field(), ptn_base);
      }
      break;
    }
    case Op_CastX2P: {
      map_ideal_node(n, phantom_obj);
      break;
    }
    case Op_CastPP:
    case Op_CheckCastPP:
    case Op_EncodeP:
    case Op_DecodeN:
    case Op_EncodePKlass:
    case Op_DecodeNKlass: {
      add_local_var_and_edge(n, PointsToNode::NoEscape,
                             n->in(1), delayed_worklist);
      break;
    }
    case Op_CMoveP: {
      add_local_var(n, PointsToNode::NoEscape);
      // Do not add edges during first iteration because some could be
      // not defined yet.
      delayed_worklist->push(n);
      break;
    }
    case Op_ConP:
    case Op_ConN:
    case Op_ConNKlass: {
      // assume all oop constants globally escape except for null
      PointsToNode::EscapeState es;
      const Type* t = igvn->type(n);
      if (t == TypePtr::NULL_PTR || t == TypeNarrowOop::NULL_PTR) {
        es = PointsToNode::NoEscape;
      } else {
        es = PointsToNode::GlobalEscape;
      }
      add_java_object(n, es);
      break;
    }
    case Op_CreateEx: {
      // assume that all exception objects globally escape
      map_ideal_node(n, phantom_obj);
      break;
    }
    case Op_LoadKlass:
    case Op_LoadNKlass: {
      // Unknown class is loaded
      map_ideal_node(n, phantom_obj);
      break;
    }
    case Op_LoadP:
    case Op_LoadN:
    case Op_LoadPLocked: {
      add_objload_to_connection_graph(n, delayed_worklist);
      break;
    }
    case Op_Parm: {
      map_ideal_node(n, phantom_obj);
      break;
    }
    case Op_PartialSubtypeCheck: {
      // Produces Null or notNull and is used in only in CmpP so
      // phantom_obj could be used.
      map_ideal_node(n, phantom_obj); // Result is unknown
      break;
    }
    case Op_Phi: {
      // Using isa_ptr() instead of isa_oopptr() for LoadP and Phi because
      // ThreadLocal has RawPtr type.
      const Type* t = n->as_Phi()->type();
      if (t->make_ptr() != NULL) {
        add_local_var(n, PointsToNode::NoEscape);
        // Do not add edges during first iteration because some could be
        // not defined yet.
        delayed_worklist->push(n);
      }
      break;
    }
    case Op_Proj: {
      // we are only interested in the oop result projection from a call
      if (n->as_Proj()->_con == TypeFunc::Parms && n->in(0)->is_Call() &&
          n->in(0)->as_Call()->returns_pointer()) {
        add_local_var_and_edge(n, PointsToNode::NoEscape,
                               n->in(0), delayed_worklist);
      }
      break;
    }
    case Op_Rethrow: // Exception object escapes
    case Op_Return: {
      if (n->req() > TypeFunc::Parms &&
          igvn->type(n->in(TypeFunc::Parms))->isa_oopptr()) {
        // Treat Return value as LocalVar with GlobalEscape escape state.
        add_local_var_and_edge(n, PointsToNode::GlobalEscape,
                               n->in(TypeFunc::Parms), delayed_worklist);
      }
      break;
    }
    case Op_GetAndSetP:
    case Op_GetAndSetN: {
      add_objload_to_connection_graph(n, delayed_worklist);
      // fallthrough
    }
    case Op_StoreP:
    case Op_StoreN:
    case Op_StoreNKlass:
    case Op_StorePConditional:
    case Op_CompareAndSwapP:
    case Op_CompareAndSwapN: {
      Node* adr = n->in(MemNode::Address);
      const Type *adr_type = igvn->type(adr);
      adr_type = adr_type->make_ptr();
      if (adr_type == NULL) {
        break; // skip dead nodes
      }
      if (adr_type->isa_oopptr() ||
          (opcode == Op_StoreP || opcode == Op_StoreN || opcode == Op_StoreNKlass) &&
                        (adr_type == TypeRawPtr::NOTNULL &&
                         adr->in(AddPNode::Address)->is_Proj() &&
                         adr->in(AddPNode::Address)->in(0)->is_Allocate())) {
        delayed_worklist->push(n); // Process it later.
#ifdef ASSERT
        assert(adr->is_AddP(), "expecting an AddP");
        if (adr_type == TypeRawPtr::NOTNULL) {
          // Verify a raw address for a store captured by Initialize node.
          int offs = (int)igvn->find_intptr_t_con(adr->in(AddPNode::Offset), Type::OffsetBot);
          assert(offs != Type::OffsetBot, "offset must be a constant");
        }
#endif
      } else {
        // Ignore copy the displaced header to the BoxNode (OSR compilation).
        if (adr->is_BoxLock())
          break;
        // Stored value escapes in unsafe access.
        if ((opcode == Op_StoreP) && (adr_type == TypeRawPtr::BOTTOM)) {
          // Pointer stores in G1 barriers looks like unsafe access.
          // Ignore such stores to be able scalar replace non-escaping
          // allocations.
          if (UseG1GC && adr->is_AddP()) {
            Node* base = get_addp_base(adr);
            if (base->Opcode() == Op_LoadP &&
                base->in(MemNode::Address)->is_AddP()) {
              adr = base->in(MemNode::Address);
              Node* tls = get_addp_base(adr);
              if (tls->Opcode() == Op_ThreadLocal) {
                int offs = (int)igvn->find_intptr_t_con(adr->in(AddPNode::Offset), Type::OffsetBot);
                if (offs == in_bytes(JavaThread::satb_mark_queue_offset() +
                                     PtrQueue::byte_offset_of_buf())) {
                  break; // G1 pre barier previous oop value store.
                }
                if (offs == in_bytes(JavaThread::dirty_card_queue_offset() +
                                     PtrQueue::byte_offset_of_buf())) {
                  break; // G1 post barier card address store.
                }
              }
            }
          }
          delayed_worklist->push(n); // Process unsafe access later.
          break;
        }
#ifdef ASSERT
        n->dump(1);
        assert(false, "not unsafe or G1 barrier raw StoreP");
#endif
      }
      break;
    }
    case Op_AryEq:
    case Op_StrComp:
    case Op_StrEquals:
    case Op_StrIndexOf:
    case Op_EncodeISOArray: {
      add_local_var(n, PointsToNode::ArgEscape);
      delayed_worklist->push(n); // Process it later.
      break;
    }
    case Op_ThreadLocal: {
      add_java_object(n, PointsToNode::ArgEscape);
      break;
    }
    default:
      ; // Do nothing for nodes not related to EA.
  }
  return;
}

#ifdef ASSERT
#define ELSE_FAIL(name)                               \
      /* Should not be called for not pointer type. */  \
      n->dump(1);                                       \
      assert(false, name);                              \
      break;
#else
#define ELSE_FAIL(name) \
      break;
#endif

// Add final simple edges to graph.
void ConnectionGraph::add_final_edges(Node *n) {
  PointsToNode* n_ptn = ptnode_adr(n->_idx);
#ifdef ASSERT
  if (_verify && n_ptn->is_JavaObject())
    return; // This method does not change graph for JavaObject.
#endif

  if (n->is_Call()) {
    process_call_arguments(n->as_Call());
    return;
  }
  assert(n->is_Store() || n->is_LoadStore() ||
         (n_ptn != NULL) && (n_ptn->ideal_node() != NULL),
         "node should be registered already");
  int opcode = n->Opcode();
  switch (opcode) {
    case Op_AddP: {
      Node* base = get_addp_base(n);
      PointsToNode* ptn_base = ptnode_adr(base->_idx);
      assert(ptn_base != NULL, "field's base should be registered");
      add_base(n_ptn->as_Field(), ptn_base);
      break;
    }
    case Op_CastPP:
    case Op_CheckCastPP:
    case Op_EncodeP:
    case Op_DecodeN:
    case Op_EncodePKlass:
    case Op_DecodeNKlass: {
      add_local_var_and_edge(n, PointsToNode::NoEscape,
                             n->in(1), NULL);
      break;
    }
    case Op_CMoveP: {
      for (uint i = CMoveNode::IfFalse; i < n->req(); i++) {
        Node* in = n->in(i);
        if (in == NULL)
          continue;  // ignore NULL
        Node* uncast_in = in->uncast();
        if (uncast_in->is_top() || uncast_in == n)
          continue;  // ignore top or inputs which go back this node
        PointsToNode* ptn = ptnode_adr(in->_idx);
        assert(ptn != NULL, "node should be registered");
        add_edge(n_ptn, ptn);
      }
      break;
    }
    case Op_LoadP:
    case Op_LoadN:
    case Op_LoadPLocked: {
      // Using isa_ptr() instead of isa_oopptr() for LoadP and Phi because
      // ThreadLocal has RawPtr type.
      const Type* t = _igvn->type(n);
      if (t->make_ptr() != NULL) {
        Node* adr = n->in(MemNode::Address);
        add_local_var_and_edge(n, PointsToNode::NoEscape, adr, NULL);
        break;
      }
      ELSE_FAIL("Op_LoadP");
    }
    case Op_Phi: {
      // Using isa_ptr() instead of isa_oopptr() for LoadP and Phi because
      // ThreadLocal has RawPtr type.
      const Type* t = n->as_Phi()->type();
      if (t->make_ptr() != NULL) {
        for (uint i = 1; i < n->req(); i++) {
          Node* in = n->in(i);
          if (in == NULL)
            continue;  // ignore NULL
          Node* uncast_in = in->uncast();
          if (uncast_in->is_top() || uncast_in == n)
            continue;  // ignore top or inputs which go back this node
          PointsToNode* ptn = ptnode_adr(in->_idx);
          assert(ptn != NULL, "node should be registered");
          add_edge(n_ptn, ptn);
        }
        break;
      }
      ELSE_FAIL("Op_Phi");
    }
    case Op_Proj: {
      // we are only interested in the oop result projection from a call
      if (n->as_Proj()->_con == TypeFunc::Parms && n->in(0)->is_Call() &&
          n->in(0)->as_Call()->returns_pointer()) {
        add_local_var_and_edge(n, PointsToNode::NoEscape, n->in(0), NULL);
        break;
      }
      ELSE_FAIL("Op_Proj");
    }
    case Op_Rethrow: // Exception object escapes
    case Op_Return: {
      if (n->req() > TypeFunc::Parms &&
          _igvn->type(n->in(TypeFunc::Parms))->isa_oopptr()) {
        // Treat Return value as LocalVar with GlobalEscape escape state.
        add_local_var_and_edge(n, PointsToNode::GlobalEscape,
                               n->in(TypeFunc::Parms), NULL);
        break;
      }
      ELSE_FAIL("Op_Return");
    }
    case Op_StoreP:
    case Op_StoreN:
    case Op_StoreNKlass:
    case Op_StorePConditional:
    case Op_CompareAndSwapP:
    case Op_CompareAndSwapN:
    case Op_GetAndSetP:
    case Op_GetAndSetN: {
      Node* adr = n->in(MemNode::Address);
      const Type *adr_type = _igvn->type(adr);
      adr_type = adr_type->make_ptr();
#ifdef ASSERT
      if (adr_type == NULL) {
        n->dump(1);
        assert(adr_type != NULL, "dead node should not be on list");
        break;
      }
#endif
      if (opcode == Op_GetAndSetP || opcode == Op_GetAndSetN) {
        add_local_var_and_edge(n, PointsToNode::NoEscape, adr, NULL);
      }
      if (adr_type->isa_oopptr() ||
          (opcode == Op_StoreP || opcode == Op_StoreN || opcode == Op_StoreNKlass) &&
                        (adr_type == TypeRawPtr::NOTNULL &&
                         adr->in(AddPNode::Address)->is_Proj() &&
                         adr->in(AddPNode::Address)->in(0)->is_Allocate())) {
        // Point Address to Value
        PointsToNode* adr_ptn = ptnode_adr(adr->_idx);
        assert(adr_ptn != NULL &&
               adr_ptn->as_Field()->is_oop(), "node should be registered");
        Node *val = n->in(MemNode::ValueIn);
        PointsToNode* ptn = ptnode_adr(val->_idx);
        assert(ptn != NULL, "node should be registered");
        add_edge(adr_ptn, ptn);
        break;
      } else if ((opcode == Op_StoreP) && (adr_type == TypeRawPtr::BOTTOM)) {
        // Stored value escapes in unsafe access.
        Node *val = n->in(MemNode::ValueIn);
        PointsToNode* ptn = ptnode_adr(val->_idx);
        assert(ptn != NULL, "node should be registered");
        set_escape_state(ptn, PointsToNode::GlobalEscape);
        // Add edge to object for unsafe access with offset.
        PointsToNode* adr_ptn = ptnode_adr(adr->_idx);
        assert(adr_ptn != NULL, "node should be registered");
        if (adr_ptn->is_Field()) {
          assert(adr_ptn->as_Field()->is_oop(), "should be oop field");
          add_edge(adr_ptn, ptn);
        }
        break;
      }
      ELSE_FAIL("Op_StoreP");
    }
    case Op_AryEq:
    case Op_StrComp:
    case Op_StrEquals:
    case Op_StrIndexOf:
    case Op_EncodeISOArray: {
      // char[] arrays passed to string intrinsic do not escape but
      // they are not scalar replaceable. Adjust escape state for them.
      // Start from in(2) edge since in(1) is memory edge.
      for (uint i = 2; i < n->req(); i++) {
        Node* adr = n->in(i);
        const Type* at = _igvn->type(adr);
        if (!adr->is_top() && at->isa_ptr()) {
          assert(at == Type::TOP || at == TypePtr::NULL_PTR ||
                 at->isa_ptr() != NULL, "expecting a pointer");
          if (adr->is_AddP()) {
            adr = get_addp_base(adr);
          }
          PointsToNode* ptn = ptnode_adr(adr->_idx);
          assert(ptn != NULL, "node should be registered");
          add_edge(n_ptn, ptn);
        }
      }
      break;
    }
    default: {
      // This method should be called only for EA specific nodes which may
      // miss some edges when they were created.
#ifdef ASSERT
      n->dump(1);
#endif
      guarantee(false, "unknown node");
    }
  }
  return;
}

void ConnectionGraph::add_call_node(CallNode* call) {
  assert(call->returns_pointer(), "only for call which returns pointer");
  uint call_idx = call->_idx;
  if (call->is_Allocate()) {
    Node* k = call->in(AllocateNode::KlassNode);
    const TypeKlassPtr* kt = k->bottom_type()->isa_klassptr();
    assert(kt != NULL, "TypeKlassPtr  required.");
    ciKlass* cik = kt->klass();
    PointsToNode::EscapeState es = PointsToNode::NoEscape;
    bool scalar_replaceable = true;
    if (call->is_AllocateArray()) {
      if (!cik->is_array_klass()) { // StressReflectiveCode
        es = PointsToNode::GlobalEscape;
      } else {
        int length = call->in(AllocateNode::ALength)->find_int_con(-1);
        if (length < 0 || length > EliminateAllocationArraySizeLimit) {
          // Not scalar replaceable if the length is not constant or too big.
          scalar_replaceable = false;
        }
      }
    } else {  // Allocate instance
      if (cik->is_subclass_of(_compile->env()->Thread_klass()) ||
          cik->is_subclass_of(_compile->env()->Reference_klass()) ||
         !cik->is_instance_klass() || // StressReflectiveCode
          cik->as_instance_klass()->has_finalizer()) {
        es = PointsToNode::GlobalEscape;
      }
    }
    add_java_object(call, es);
    PointsToNode* ptn = ptnode_adr(call_idx);
    if (!scalar_replaceable && ptn->scalar_replaceable()) {
      ptn->set_scalar_replaceable(false);
    }
  } else if (call->is_CallStaticJava()) {
    // Call nodes could be different types:
    //
    // 1. CallDynamicJavaNode (what happened during call is unknown):
    //
    //    - mapped to GlobalEscape JavaObject node if oop is returned;
    //
    //    - all oop arguments are escaping globally;
    //
    // 2. CallStaticJavaNode (execute bytecode analysis if possible):
    //
    //    - the same as CallDynamicJavaNode if can't do bytecode analysis;
    //
    //    - mapped to GlobalEscape JavaObject node if unknown oop is returned;
    //    - mapped to NoEscape JavaObject node if non-escaping object allocated
    //      during call is returned;
    //    - mapped to ArgEscape LocalVar node pointed to object arguments
    //      which are returned and does not escape during call;
    //
    //    - oop arguments escaping status is defined by bytecode analysis;
    //
    // For a static call, we know exactly what method is being called.
    // Use bytecode estimator to record whether the call's return value escapes.
    ciMethod* meth = call->as_CallJava()->method();
    if (meth == NULL) {
      const char* name = call->as_CallStaticJava()->_name;
      assert(strncmp(name, "_multianewarray", 15) == 0, "TODO: add failed case check");
      // Returns a newly allocated unescaped object.
      add_java_object(call, PointsToNode::NoEscape);
      ptnode_adr(call_idx)->set_scalar_replaceable(false);
    } else if (meth->is_boxing_method()) {
      // Returns boxing object
      PointsToNode::EscapeState es;
      vmIntrinsics::ID intr = meth->intrinsic_id();
      if (intr == vmIntrinsics::_floatValue || intr == vmIntrinsics::_doubleValue) {
        // It does not escape if object is always allocated.
        es = PointsToNode::NoEscape;
      } else {
        // It escapes globally if object could be loaded from cache.
        es = PointsToNode::GlobalEscape;
      }
      add_java_object(call, es);
    } else {
      BCEscapeAnalyzer* call_analyzer = meth->get_bcea();
      call_analyzer->copy_dependencies(_compile->dependencies());
      if (call_analyzer->is_return_allocated()) {
        // Returns a newly allocated unescaped object, simply
        // update dependency information.
        // Mark it as NoEscape so that objects referenced by
        // it's fields will be marked as NoEscape at least.
        add_java_object(call, PointsToNode::NoEscape);
        ptnode_adr(call_idx)->set_scalar_replaceable(false);
      } else {
        // Determine whether any arguments are returned.
        const TypeTuple* d = call->tf()->domain();
        bool ret_arg = false;
        for (uint i = TypeFunc::Parms; i < d->cnt(); i++) {
          if (d->field_at(i)->isa_ptr() != NULL &&
              call_analyzer->is_arg_returned(i - TypeFunc::Parms)) {
            ret_arg = true;
            break;
          }
        }
        if (ret_arg) {
          add_local_var(call, PointsToNode::ArgEscape);
        } else {
          // Returns unknown object.
          map_ideal_node(call, phantom_obj);
        }
      }
    }
  } else {
    // An other type of call, assume the worst case:
    // returned value is unknown and globally escapes.
    assert(call->Opcode() == Op_CallDynamicJava, "add failed case check");
    map_ideal_node(call, phantom_obj);
  }
}

void ConnectionGraph::process_call_arguments(CallNode *call) {
    bool is_arraycopy = false;
    switch (call->Opcode()) {
#ifdef ASSERT
    case Op_Allocate:
    case Op_AllocateArray:
    case Op_Lock:
    case Op_Unlock:
      assert(false, "should be done already");
      break;
#endif
    case Op_CallLeafNoFP:
      is_arraycopy = (call->as_CallLeaf()->_name != NULL &&
                      strstr(call->as_CallLeaf()->_name, "arraycopy") != 0);
      // fall through
    case Op_CallLeaf: {
      // Stub calls, objects do not escape but they are not scale replaceable.
      // Adjust escape state for outgoing arguments.
      const TypeTuple * d = call->tf()->domain();
      bool src_has_oops = false;
      for (uint i = TypeFunc::Parms; i < d->cnt(); i++) {
        const Type* at = d->field_at(i);
        Node *arg = call->in(i);
        const Type *aat = _igvn->type(arg);
        if (arg->is_top() || !at->isa_ptr() || !aat->isa_ptr())
          continue;
        if (arg->is_AddP()) {
          //
          // The inline_native_clone() case when the arraycopy stub is called
          // after the allocation before Initialize and CheckCastPP nodes.
          // Or normal arraycopy for object arrays case.
          //
          // Set AddP's base (Allocate) as not scalar replaceable since
          // pointer to the base (with offset) is passed as argument.
          //
          arg = get_addp_base(arg);
        }
        PointsToNode* arg_ptn = ptnode_adr(arg->_idx);
        assert(arg_ptn != NULL, "should be registered");
        PointsToNode::EscapeState arg_esc = arg_ptn->escape_state();
        if (is_arraycopy || arg_esc < PointsToNode::ArgEscape) {
          assert(aat == Type::TOP || aat == TypePtr::NULL_PTR ||
                 aat->isa_ptr() != NULL, "expecting an Ptr");
          bool arg_has_oops = aat->isa_oopptr() &&
                              (aat->isa_oopptr()->klass() == NULL || aat->isa_instptr() ||
                               (aat->isa_aryptr() && aat->isa_aryptr()->klass()->is_obj_array_klass()));
          if (i == TypeFunc::Parms) {
            src_has_oops = arg_has_oops;
          }
          //
          // src or dst could be j.l.Object when other is basic type array:
          //
          //   arraycopy(char[],0,Object*,0,size);
          //   arraycopy(Object*,0,char[],0,size);
          //
          // Don't add edges in such cases.
          //
          bool arg_is_arraycopy_dest = src_has_oops && is_arraycopy &&
                                       arg_has_oops && (i > TypeFunc::Parms);
#ifdef ASSERT
          if (!(is_arraycopy ||
                (call->as_CallLeaf()->_name != NULL &&
                 (strcmp(call->as_CallLeaf()->_name, "g1_wb_pre")  == 0 ||
                  strcmp(call->as_CallLeaf()->_name, "g1_wb_post") == 0 ||
                  strcmp(call->as_CallLeaf()->_name, "updateBytesCRC32") == 0 ||
                  strcmp(call->as_CallLeaf()->_name, "aescrypt_encryptBlock") == 0 ||
                  strcmp(call->as_CallLeaf()->_name, "aescrypt_decryptBlock") == 0 ||
                  strcmp(call->as_CallLeaf()->_name, "cipherBlockChaining_encryptAESCrypt") == 0 ||
                  strcmp(call->as_CallLeaf()->_name, "cipherBlockChaining_decryptAESCrypt") == 0 ||
                  strcmp(call->as_CallLeaf()->_name, "sha1_implCompress") == 0 ||
                  strcmp(call->as_CallLeaf()->_name, "sha1_implCompressMB") == 0 ||
                  strcmp(call->as_CallLeaf()->_name, "sha256_implCompress") == 0 ||
                  strcmp(call->as_CallLeaf()->_name, "sha256_implCompressMB") == 0 ||
                  strcmp(call->as_CallLeaf()->_name, "sha512_implCompress") == 0 ||
                  strcmp(call->as_CallLeaf()->_name, "sha512_implCompressMB") == 0 ||
                  strcmp(call->as_CallLeaf()->_name, "multiplyToLen") == 0 ||
                  strcmp(call->as_CallLeaf()->_name, "squareToLen") == 0 ||
                  strcmp(call->as_CallLeaf()->_name, "mulAdd") == 0 ||
                  strcmp(call->as_CallLeaf()->_name, "montgomery_multiply") == 0 ||
                  strcmp(call->as_CallLeaf()->_name, "montgomery_square") == 0)
                 ))) {
            call->dump();
            fatal(err_msg_res("EA unexpected CallLeaf %s", call->as_CallLeaf()->_name));
          }
#endif
          // Always process arraycopy's destination object since
          // we need to add all possible edges to references in
          // source object.
          if (arg_esc >= PointsToNode::ArgEscape &&
              !arg_is_arraycopy_dest) {
            continue;
          }
          set_escape_state(arg_ptn, PointsToNode::ArgEscape);
          if (arg_is_arraycopy_dest) {
            Node* src = call->in(TypeFunc::Parms);
            if (src->is_AddP()) {
              src = get_addp_base(src);
            }
            PointsToNode* src_ptn = ptnode_adr(src->_idx);
            assert(src_ptn != NULL, "should be registered");
            if (arg_ptn != src_ptn) {
              // Special arraycopy edge:
              // A destination object's field can't have the source object
              // as base since objects escape states are not related.
              // Only escape state of destination object's fields affects
              // escape state of fields in source object.
              add_arraycopy(call, PointsToNode::ArgEscape, src_ptn, arg_ptn);
            }
          }
        }
      }
      break;
    }
    case Op_CallStaticJava: {
      // For a static call, we know exactly what method is being called.
      // Use bytecode estimator to record the call's escape affects
#ifdef ASSERT
      const char* name = call->as_CallStaticJava()->_name;
      assert((name == NULL || strcmp(name, "uncommon_trap") != 0), "normal calls only");
#endif
      ciMethod* meth = call->as_CallJava()->method();
      if ((meth != NULL) && meth->is_boxing_method()) {
        break; // Boxing methods do not modify any oops.
      }
      BCEscapeAnalyzer* call_analyzer = (meth !=NULL) ? meth->get_bcea() : NULL;
      // fall-through if not a Java method or no analyzer information
      if (call_analyzer != NULL) {
        PointsToNode* call_ptn = ptnode_adr(call->_idx);
        const TypeTuple* d = call->tf()->domain();
        for (uint i = TypeFunc::Parms; i < d->cnt(); i++) {
          const Type* at = d->field_at(i);
          int k = i - TypeFunc::Parms;
          Node* arg = call->in(i);
          PointsToNode* arg_ptn = ptnode_adr(arg->_idx);
          if (at->isa_ptr() != NULL &&
              call_analyzer->is_arg_returned(k)) {
            // The call returns arguments.
            if (call_ptn != NULL) { // Is call's result used?
              assert(call_ptn->is_LocalVar(), "node should be registered");
              assert(arg_ptn != NULL, "node should be registered");
              add_edge(call_ptn, arg_ptn);
            }
          }
          if (at->isa_oopptr() != NULL &&
              arg_ptn->escape_state() < PointsToNode::GlobalEscape) {
            if (!call_analyzer->is_arg_stack(k)) {
              // The argument global escapes
              set_escape_state(arg_ptn, PointsToNode::GlobalEscape);
            } else {
              set_escape_state(arg_ptn, PointsToNode::ArgEscape);
              if (!call_analyzer->is_arg_local(k)) {
                // The argument itself doesn't escape, but any fields might
                set_fields_escape_state(arg_ptn, PointsToNode::GlobalEscape);
              }
            }
          }
        }
        if (call_ptn != NULL && call_ptn->is_LocalVar()) {
          // The call returns arguments.
          assert(call_ptn->edge_count() > 0, "sanity");
          if (!call_analyzer->is_return_local()) {
            // Returns also unknown object.
            add_edge(call_ptn, phantom_obj);
          }
        }
        break;
      }
    }
    default: {
      // Fall-through here if not a Java method or no analyzer information
      // or some other type of call, assume the worst case: all arguments
      // globally escape.
      const TypeTuple* d = call->tf()->domain();
      for (uint i = TypeFunc::Parms; i < d->cnt(); i++) {
        const Type* at = d->field_at(i);
        if (at->isa_oopptr() != NULL) {
          Node* arg = call->in(i);
          if (arg->is_AddP()) {
            arg = get_addp_base(arg);
          }
          assert(ptnode_adr(arg->_idx) != NULL, "should be defined already");
          set_escape_state(ptnode_adr(arg->_idx), PointsToNode::GlobalEscape);
        }
      }
    }
  }
}


// Finish Graph construction.
bool ConnectionGraph::complete_connection_graph(
                         GrowableArray<PointsToNode*>&   ptnodes_worklist,
                         GrowableArray<JavaObjectNode*>& non_escaped_worklist,
                         GrowableArray<JavaObjectNode*>& java_objects_worklist,
                         GrowableArray<FieldNode*>&      oop_fields_worklist) {
  // Normally only 1-3 passes needed to build Connection Graph depending
  // on graph complexity. Observed 8 passes in jvm2008 compiler.compiler.
  // Set limit to 20 to catch situation when something did go wrong and
  // bailout Escape Analysis.
  // Also limit build time to 20 sec (60 in debug VM), EscapeAnalysisTimeout flag.
#define CG_BUILD_ITER_LIMIT 20

  // Propagate GlobalEscape and ArgEscape escape states and check that
  // we still have non-escaping objects. The method pushs on _worklist
  // Field nodes which reference phantom_object.
  if (!find_non_escaped_objects(ptnodes_worklist, non_escaped_worklist)) {
    return false; // Nothing to do.
  }
  // Now propagate references to all JavaObject nodes.
  int java_objects_length = java_objects_worklist.length();
  elapsedTimer time;
  bool timeout = false;
  int new_edges = 1;
  int iterations = 0;
  do {
    while ((new_edges > 0) &&
           (iterations++ < CG_BUILD_ITER_LIMIT)) {
      double start_time = time.seconds();
      time.start();
      new_edges = 0;
      // Propagate references to phantom_object for nodes pushed on _worklist
      // by find_non_escaped_objects() and find_field_value().
      new_edges += add_java_object_edges(phantom_obj, false);
      for (int next = 0; next < java_objects_length; ++next) {
        JavaObjectNode* ptn = java_objects_worklist.at(next);
        new_edges += add_java_object_edges(ptn, true);

#define SAMPLE_SIZE 4
        if ((next % SAMPLE_SIZE) == 0) {
          // Each 4 iterations calculate how much time it will take
          // to complete graph construction.
          time.stop();
          // Poll for requests from shutdown mechanism to quiesce compiler
          // because Connection graph construction may take long time.
          CompileBroker::maybe_block();
          double stop_time = time.seconds();
          double time_per_iter = (stop_time - start_time) / (double)SAMPLE_SIZE;
          double time_until_end = time_per_iter * (double)(java_objects_length - next);
          if ((start_time + time_until_end) >= EscapeAnalysisTimeout) {
            timeout = true;
            break; // Timeout
          }
          start_time = stop_time;
          time.start();
        }
#undef SAMPLE_SIZE

      }
      if (timeout) break;
      if (new_edges > 0) {
        // Update escape states on each iteration if graph was updated.
        if (!find_non_escaped_objects(ptnodes_worklist, non_escaped_worklist)) {
          return false; // Nothing to do.
        }
      }
      time.stop();
      if (time.seconds() >= EscapeAnalysisTimeout) {
        timeout = true;
        break;
      }
    }
    if ((iterations < CG_BUILD_ITER_LIMIT) && !timeout) {
      time.start();
      // Find fields which have unknown value.
      int fields_length = oop_fields_worklist.length();
      for (int next = 0; next < fields_length; next++) {
        FieldNode* field = oop_fields_worklist.at(next);
        if (field->edge_count() == 0) {
          new_edges += find_field_value(field);
          // This code may added new edges to phantom_object.
          // Need an other cycle to propagate references to phantom_object.
        }
      }
      time.stop();
      if (time.seconds() >= EscapeAnalysisTimeout) {
        timeout = true;
        break;
      }
    } else {
      new_edges = 0; // Bailout
    }
  } while (new_edges > 0);

  // Bailout if passed limits.
  if ((iterations >= CG_BUILD_ITER_LIMIT) || timeout) {
    Compile* C = _compile;
    if (C->log() != NULL) {
      C->log()->begin_elem("connectionGraph_bailout reason='reached ");
      C->log()->text("%s", timeout ? "time" : "iterations");
      C->log()->end_elem(" limit'");
    }
    assert(ExitEscapeAnalysisOnTimeout, err_msg_res("infinite EA connection graph build (%f sec, %d iterations) with %d nodes and worklist size %d",
           time.seconds(), iterations, nodes_size(), ptnodes_worklist.length()));
    // Possible infinite build_connection_graph loop,
    // bailout (no changes to ideal graph were made).
    return false;
  }
#ifdef ASSERT
  if (Verbose && PrintEscapeAnalysis) {
    tty->print_cr("EA: %d iterations to build connection graph with %d nodes and worklist size %d",
                  iterations, nodes_size(), ptnodes_worklist.length());
  }
#endif

#undef CG_BUILD_ITER_LIMIT

  // Find fields initialized by NULL for non-escaping Allocations.
  int non_escaped_length = non_escaped_worklist.length();
  for (int next = 0; next < non_escaped_length; next++) {
    JavaObjectNode* ptn = non_escaped_worklist.at(next);
    PointsToNode::EscapeState es = ptn->escape_state();
    assert(es <= PointsToNode::ArgEscape, "sanity");
    if (es == PointsToNode::NoEscape) {
      if (find_init_values(ptn, null_obj, _igvn) > 0) {
        // Adding references to NULL object does not change escape states
        // since it does not escape. Also no fields are added to NULL object.
        add_java_object_edges(null_obj, false);
      }
    }
    Node* n = ptn->ideal_node();
    if (n->is_Allocate()) {
      // The object allocated by this Allocate node will never be
      // seen by an other thread. Mark it so that when it is
      // expanded no MemBarStoreStore is added.
      InitializeNode* ini = n->as_Allocate()->initialization();
      if (ini != NULL)
        ini->set_does_not_escape();
    }
  }
  return true; // Finished graph construction.
}

// Propagate GlobalEscape and ArgEscape escape states to all nodes
// and check that we still have non-escaping java objects.
bool ConnectionGraph::find_non_escaped_objects(GrowableArray<PointsToNode*>& ptnodes_worklist,
                                               GrowableArray<JavaObjectNode*>& non_escaped_worklist) {
  GrowableArray<PointsToNode*> escape_worklist;
  // First, put all nodes with GlobalEscape and ArgEscape states on worklist.
  int ptnodes_length = ptnodes_worklist.length();
  for (int next = 0; next < ptnodes_length; ++next) {
    PointsToNode* ptn = ptnodes_worklist.at(next);
    if (ptn->escape_state() >= PointsToNode::ArgEscape ||
        ptn->fields_escape_state() >= PointsToNode::ArgEscape) {
      escape_worklist.push(ptn);
    }
  }
  // Set escape states to referenced nodes (edges list).
  while (escape_worklist.length() > 0) {
    PointsToNode* ptn = escape_worklist.pop();
    PointsToNode::EscapeState es  = ptn->escape_state();
    PointsToNode::EscapeState field_es = ptn->fields_escape_state();
    if (ptn->is_Field() && ptn->as_Field()->is_oop() &&
        es >= PointsToNode::ArgEscape) {
      // GlobalEscape or ArgEscape state of field means it has unknown value.
      if (add_edge(ptn, phantom_obj)) {
        // New edge was added
        add_field_uses_to_worklist(ptn->as_Field());
      }
    }
    for (EdgeIterator i(ptn); i.has_next(); i.next()) {
      PointsToNode* e = i.get();
      if (e->is_Arraycopy()) {
        assert(ptn->arraycopy_dst(), "sanity");
        // Propagate only fields escape state through arraycopy edge.
        if (e->fields_escape_state() < field_es) {
          set_fields_escape_state(e, field_es);
          escape_worklist.push(e);
        }
      } else if (es >= field_es) {
        // fields_escape_state is also set to 'es' if it is less than 'es'.
        if (e->escape_state() < es) {
          set_escape_state(e, es);
          escape_worklist.push(e);
        }
      } else {
        // Propagate field escape state.
        bool es_changed = false;
        if (e->fields_escape_state() < field_es) {
          set_fields_escape_state(e, field_es);
          es_changed = true;
        }
        if ((e->escape_state() < field_es) &&
            e->is_Field() && ptn->is_JavaObject() &&
            e->as_Field()->is_oop()) {
          // Change escape state of referenced fileds.
          set_escape_state(e, field_es);
          es_changed = true;;
        } else if (e->escape_state() < es) {
          set_escape_state(e, es);
          es_changed = true;;
        }
        if (es_changed) {
          escape_worklist.push(e);
        }
      }
    }
  }
  // Remove escaped objects from non_escaped list.
  for (int next = non_escaped_worklist.length()-1; next >= 0 ; --next) {
    JavaObjectNode* ptn = non_escaped_worklist.at(next);
    if (ptn->escape_state() >= PointsToNode::GlobalEscape) {
      non_escaped_worklist.delete_at(next);
    }
    if (ptn->escape_state() == PointsToNode::NoEscape) {
      // Find fields in non-escaped allocations which have unknown value.
      find_init_values(ptn, phantom_obj, NULL);
    }
  }
  return (non_escaped_worklist.length() > 0);
}

// Add all references to JavaObject node by walking over all uses.
int ConnectionGraph::add_java_object_edges(JavaObjectNode* jobj, bool populate_worklist) {
  int new_edges = 0;
  if (populate_worklist) {
    // Populate _worklist by uses of jobj's uses.
    for (UseIterator i(jobj); i.has_next(); i.next()) {
      PointsToNode* use = i.get();
      if (use->is_Arraycopy())
        continue;
      add_uses_to_worklist(use);
      if (use->is_Field() && use->as_Field()->is_oop()) {
        // Put on worklist all field's uses (loads) and
        // related field nodes (same base and offset).
        add_field_uses_to_worklist(use->as_Field());
      }
    }
  }
  for (int l = 0; l < _worklist.length(); l++) {
    PointsToNode* use = _worklist.at(l);
    if (PointsToNode::is_base_use(use)) {
      // Add reference from jobj to field and from field to jobj (field's base).
      use = PointsToNode::get_use_node(use)->as_Field();
      if (add_base(use->as_Field(), jobj)) {
        new_edges++;
      }
      continue;
    }
    assert(!use->is_JavaObject(), "sanity");
    if (use->is_Arraycopy()) {
      if (jobj == null_obj) // NULL object does not have field edges
        continue;
      // Added edge from Arraycopy node to arraycopy's source java object
      if (add_edge(use, jobj)) {
        jobj->set_arraycopy_src();
        new_edges++;
      }
      // and stop here.
      continue;
    }
    if (!add_edge(use, jobj))
      continue; // No new edge added, there was such edge already.
    new_edges++;
    if (use->is_LocalVar()) {
      add_uses_to_worklist(use);
      if (use->arraycopy_dst()) {
        for (EdgeIterator i(use); i.has_next(); i.next()) {
          PointsToNode* e = i.get();
          if (e->is_Arraycopy()) {
            if (jobj == null_obj) // NULL object does not have field edges
              continue;
            // Add edge from arraycopy's destination java object to Arraycopy node.
            if (add_edge(jobj, e)) {
              new_edges++;
              jobj->set_arraycopy_dst();
            }
          }
        }
      }
    } else {
      // Added new edge to stored in field values.
      // Put on worklist all field's uses (loads) and
      // related field nodes (same base and offset).
      add_field_uses_to_worklist(use->as_Field());
    }
  }
  _worklist.clear();
  _in_worklist.Reset();
  return new_edges;
}

// Put on worklist all related field nodes.
void ConnectionGraph::add_field_uses_to_worklist(FieldNode* field) {
  assert(field->is_oop(), "sanity");
  int offset = field->offset();
  add_uses_to_worklist(field);
  // Loop over all bases of this field and push on worklist Field nodes
  // with the same offset and base (since they may reference the same field).
  for (BaseIterator i(field); i.has_next(); i.next()) {
    PointsToNode* base = i.get();
    add_fields_to_worklist(field, base);
    // Check if the base was source object of arraycopy and go over arraycopy's
    // destination objects since values stored to a field of source object are
    // accessable by uses (loads) of fields of destination objects.
    if (base->arraycopy_src()) {
      for (UseIterator j(base); j.has_next(); j.next()) {
        PointsToNode* arycp = j.get();
        if (arycp->is_Arraycopy()) {
          for (UseIterator k(arycp); k.has_next(); k.next()) {
            PointsToNode* abase = k.get();
            if (abase->arraycopy_dst() && abase != base) {
              // Look for the same arracopy reference.
              add_fields_to_worklist(field, abase);
            }
          }
        }
      }
    }
  }
}

// Put on worklist all related field nodes.
void ConnectionGraph::add_fields_to_worklist(FieldNode* field, PointsToNode* base) {
  int offset = field->offset();
  if (base->is_LocalVar()) {
    for (UseIterator j(base); j.has_next(); j.next()) {
      PointsToNode* f = j.get();
      if (PointsToNode::is_base_use(f)) { // Field
        f = PointsToNode::get_use_node(f);
        if (f == field || !f->as_Field()->is_oop())
          continue;
        int offs = f->as_Field()->offset();
        if (offs == offset || offset == Type::OffsetBot || offs == Type::OffsetBot) {
          add_to_worklist(f);
        }
      }
    }
  } else {
    assert(base->is_JavaObject(), "sanity");
    if (// Skip phantom_object since it is only used to indicate that
        // this field's content globally escapes.
        (base != phantom_obj) &&
        // NULL object node does not have fields.
        (base != null_obj)) {
      for (EdgeIterator i(base); i.has_next(); i.next()) {
        PointsToNode* f = i.get();
        // Skip arraycopy edge since store to destination object field
        // does not update value in source object field.
        if (f->is_Arraycopy()) {
          assert(base->arraycopy_dst(), "sanity");
          continue;
        }
        if (f == field || !f->as_Field()->is_oop())
          continue;
        int offs = f->as_Field()->offset();
        if (offs == offset || offset == Type::OffsetBot || offs == Type::OffsetBot) {
          add_to_worklist(f);
        }
      }
    }
  }
}

// Find fields which have unknown value.
int ConnectionGraph::find_field_value(FieldNode* field) {
  // Escaped fields should have init value already.
  assert(field->escape_state() == PointsToNode::NoEscape, "sanity");
  int new_edges = 0;
  for (BaseIterator i(field); i.has_next(); i.next()) {
    PointsToNode* base = i.get();
    if (base->is_JavaObject()) {
      // Skip Allocate's fields which will be processed later.
      if (base->ideal_node()->is_Allocate())
        return 0;
      assert(base == null_obj, "only NULL ptr base expected here");
    }
  }
  if (add_edge(field, phantom_obj)) {
    // New edge was added
    new_edges++;
    add_field_uses_to_worklist(field);
  }
  return new_edges;
}

// Find fields initializing values for allocations.
int ConnectionGraph::find_init_values(JavaObjectNode* pta, PointsToNode* init_val, PhaseTransform* phase) {
  assert(pta->escape_state() == PointsToNode::NoEscape, "Not escaped Allocate nodes only");
  int new_edges = 0;
  Node* alloc = pta->ideal_node();
  if (init_val == phantom_obj) {
    // Do nothing for Allocate nodes since its fields values are "known".
    if (alloc->is_Allocate())
      return 0;
    assert(alloc->as_CallStaticJava(), "sanity");
#ifdef ASSERT
    if (alloc->as_CallStaticJava()->method() == NULL) {
      const char* name = alloc->as_CallStaticJava()->_name;
      assert(strncmp(name, "_multianewarray", 15) == 0, "sanity");
    }
#endif
    // Non-escaped allocation returned from Java or runtime call have
    // unknown values in fields.
    for (EdgeIterator i(pta); i.has_next(); i.next()) {
      PointsToNode* field = i.get();
      if (field->is_Field() && field->as_Field()->is_oop()) {
        if (add_edge(field, phantom_obj)) {
          // New edge was added
          new_edges++;
          add_field_uses_to_worklist(field->as_Field());
        }
      }
    }
    return new_edges;
  }
  assert(init_val == null_obj, "sanity");
  // Do nothing for Call nodes since its fields values are unknown.
  if (!alloc->is_Allocate())
    return 0;

  InitializeNode* ini = alloc->as_Allocate()->initialization();
  Compile* C = _compile;
  bool visited_bottom_offset = false;
  GrowableArray<int> offsets_worklist;

  // Check if an oop field's initializing value is recorded and add
  // a corresponding NULL if field's value if it is not recorded.
  // Connection Graph does not record a default initialization by NULL
  // captured by Initialize node.
  //
  for (EdgeIterator i(pta); i.has_next(); i.next()) {
    PointsToNode* field = i.get(); // Field (AddP)
    if (!field->is_Field() || !field->as_Field()->is_oop())
      continue; // Not oop field
    int offset = field->as_Field()->offset();
    if (offset == Type::OffsetBot) {
      if (!visited_bottom_offset) {
        // OffsetBot is used to reference array's element,
        // always add reference to NULL to all Field nodes since we don't
        // known which element is referenced.
        if (add_edge(field, null_obj)) {
          // New edge was added
          new_edges++;
          add_field_uses_to_worklist(field->as_Field());
          visited_bottom_offset = true;
        }
      }
    } else {
      // Check only oop fields.
      const Type* adr_type = field->ideal_node()->as_AddP()->bottom_type();
      if (adr_type->isa_rawptr()) {
#ifdef ASSERT
        // Raw pointers are used for initializing stores so skip it
        // since it should be recorded already
        Node* base = get_addp_base(field->ideal_node());
        assert(adr_type->isa_rawptr() && base->is_Proj() &&
               (base->in(0) == alloc),"unexpected pointer type");
#endif
        continue;
      }
      if (!offsets_worklist.contains(offset)) {
        offsets_worklist.append(offset);
        Node* value = NULL;
        if (ini != NULL) {
          // StoreP::memory_type() == T_ADDRESS
          BasicType ft = UseCompressedOops ? T_NARROWOOP : T_ADDRESS;
          Node* store = ini->find_captured_store(offset, type2aelembytes(ft, true), phase);
          // Make sure initializing store has the same type as this AddP.
          // This AddP may reference non existing field because it is on a
          // dead branch of bimorphic call which is not eliminated yet.
          if (store != NULL && store->is_Store() &&
              store->as_Store()->memory_type() == ft) {
            value = store->in(MemNode::ValueIn);
#ifdef ASSERT
            if (VerifyConnectionGraph) {
              // Verify that AddP already points to all objects the value points to.
              PointsToNode* val = ptnode_adr(value->_idx);
              assert((val != NULL), "should be processed already");
              PointsToNode* missed_obj = NULL;
              if (val->is_JavaObject()) {
                if (!field->points_to(val->as_JavaObject())) {
                  missed_obj = val;
                }
              } else {
                if (!val->is_LocalVar() || (val->edge_count() == 0)) {
                  tty->print_cr("----------init store has invalid value -----");
                  store->dump();
                  val->dump();
                  assert(val->is_LocalVar() && (val->edge_count() > 0), "should be processed already");
                }
                for (EdgeIterator j(val); j.has_next(); j.next()) {
                  PointsToNode* obj = j.get();
                  if (obj->is_JavaObject()) {
                    if (!field->points_to(obj->as_JavaObject())) {
                      missed_obj = obj;
                      break;
                    }
                  }
                }
              }
              if (missed_obj != NULL) {
                tty->print_cr("----------field---------------------------------");
                field->dump();
                tty->print_cr("----------missed referernce to object-----------");
                missed_obj->dump();
                tty->print_cr("----------object referernced by init store -----");
                store->dump();
                val->dump();
                assert(!field->points_to(missed_obj->as_JavaObject()), "missed JavaObject reference");
              }
            }
#endif
          } else {
            // There could be initializing stores which follow allocation.
            // For example, a volatile field store is not collected
            // by Initialize node.
            //
            // Need to check for dependent loads to separate such stores from
            // stores which follow loads. For now, add initial value NULL so
            // that compare pointers optimization works correctly.
          }
        }
        if (value == NULL) {
          // A field's initializing value was not recorded. Add NULL.
          if (add_edge(field, null_obj)) {
            // New edge was added
            new_edges++;
            add_field_uses_to_worklist(field->as_Field());
          }
        }
      }
    }
  }
  return new_edges;
}

// Adjust scalar_replaceable state after Connection Graph is built.
void ConnectionGraph::adjust_scalar_replaceable_state(JavaObjectNode* jobj) {
  // Search for non-escaping objects which are not scalar replaceable
  // and mark them to propagate the state to referenced objects.

  // 1. An object is not scalar replaceable if the field into which it is
  // stored has unknown offset (stored into unknown element of an array).
  //
  for (UseIterator i(jobj); i.has_next(); i.next()) {
    PointsToNode* use = i.get();
    assert(!use->is_Arraycopy(), "sanity");
    if (use->is_Field()) {
      FieldNode* field = use->as_Field();
      assert(field->is_oop() && field->scalar_replaceable() &&
             field->fields_escape_state() == PointsToNode::NoEscape, "sanity");
      if (field->offset() == Type::OffsetBot) {
        jobj->set_scalar_replaceable(false);
        return;
      }
      // 2. An object is not scalar replaceable if the field into which it is
      // stored has multiple bases one of which is null.
      if (field->base_count() > 1) {
        for (BaseIterator i(field); i.has_next(); i.next()) {
          PointsToNode* base = i.get();
          if (base == null_obj) {
            jobj->set_scalar_replaceable(false);
            return;
          }
        }
      }
    }
    assert(use->is_Field() || use->is_LocalVar(), "sanity");
    // 3. An object is not scalar replaceable if it is merged with other objects.
    for (EdgeIterator j(use); j.has_next(); j.next()) {
      PointsToNode* ptn = j.get();
      if (ptn->is_JavaObject() && ptn != jobj) {
        // Mark all objects.
        jobj->set_scalar_replaceable(false);
         ptn->set_scalar_replaceable(false);
      }
    }
    if (!jobj->scalar_replaceable()) {
      return;
    }
  }

  for (EdgeIterator j(jobj); j.has_next(); j.next()) {
    // Non-escaping object node should point only to field nodes.
    FieldNode* field = j.get()->as_Field();
    int offset = field->as_Field()->offset();

    // 4. An object is not scalar replaceable if it has a field with unknown
    // offset (array's element is accessed in loop).
    if (offset == Type::OffsetBot) {
      jobj->set_scalar_replaceable(false);
      return;
    }
    // 5. Currently an object is not scalar replaceable if a LoadStore node
    // access its field since the field value is unknown after it.
    //
    Node* n = field->ideal_node();
    for (DUIterator_Fast imax, i = n->fast_outs(imax); i < imax; i++) {
      if (n->fast_out(i)->is_LoadStore()) {
        jobj->set_scalar_replaceable(false);
        return;
      }
    }

    // 6. Or the address may point to more then one object. This may produce
    // the false positive result (set not scalar replaceable)
    // since the flow-insensitive escape analysis can't separate
    // the case when stores overwrite the field's value from the case
    // when stores happened on different control branches.
    //
    // Note: it will disable scalar replacement in some cases:
    //
    //    Point p[] = new Point[1];
    //    p[0] = new Point(); // Will be not scalar replaced
    //
    // but it will save us from incorrect optimizations in next cases:
    //
    //    Point p[] = new Point[1];
    //    if ( x ) p[0] = new Point(); // Will be not scalar replaced
    //
    if (field->base_count() > 1) {
      for (BaseIterator i(field); i.has_next(); i.next()) {
        PointsToNode* base = i.get();
        // Don't take into account LocalVar nodes which
        // may point to only one object which should be also
        // this field's base by now.
        if (base->is_JavaObject() && base != jobj) {
          // Mark all bases.
          jobj->set_scalar_replaceable(false);
          base->set_scalar_replaceable(false);
        }
      }
    }
  }
}

#ifdef ASSERT
void ConnectionGraph::verify_connection_graph(
                         GrowableArray<PointsToNode*>&   ptnodes_worklist,
                         GrowableArray<JavaObjectNode*>& non_escaped_worklist,
                         GrowableArray<JavaObjectNode*>& java_objects_worklist,
                         GrowableArray<Node*>& addp_worklist) {
  // Verify that graph is complete - no new edges could be added.
  int java_objects_length = java_objects_worklist.length();
  int non_escaped_length  = non_escaped_worklist.length();
  int new_edges = 0;
  for (int next = 0; next < java_objects_length; ++next) {
    JavaObjectNode* ptn = java_objects_worklist.at(next);
    new_edges += add_java_object_edges(ptn, true);
  }
  assert(new_edges == 0, "graph was not complete");
  // Verify that escape state is final.
  int length = non_escaped_worklist.length();
  find_non_escaped_objects(ptnodes_worklist, non_escaped_worklist);
  assert((non_escaped_length == non_escaped_worklist.length()) &&
         (non_escaped_length == length) &&
         (_worklist.length() == 0), "escape state was not final");

  // Verify fields information.
  int addp_length = addp_worklist.length();
  for (int next = 0; next < addp_length; ++next ) {
    Node* n = addp_worklist.at(next);
    FieldNode* field = ptnode_adr(n->_idx)->as_Field();
    if (field->is_oop()) {
      // Verify that field has all bases
      Node* base = get_addp_base(n);
      PointsToNode* ptn = ptnode_adr(base->_idx);
      if (ptn->is_JavaObject()) {
        assert(field->has_base(ptn->as_JavaObject()), "sanity");
      } else {
        assert(ptn->is_LocalVar(), "sanity");
        for (EdgeIterator i(ptn); i.has_next(); i.next()) {
          PointsToNode* e = i.get();
          if (e->is_JavaObject()) {
            assert(field->has_base(e->as_JavaObject()), "sanity");
          }
        }
      }
      // Verify that all fields have initializing values.
      if (field->edge_count() == 0) {
        tty->print_cr("----------field does not have references----------");
        field->dump();
        for (BaseIterator i(field); i.has_next(); i.next()) {
          PointsToNode* base = i.get();
          tty->print_cr("----------field has next base---------------------");
          base->dump();
          if (base->is_JavaObject() && (base != phantom_obj) && (base != null_obj)) {
            tty->print_cr("----------base has fields-------------------------");
            for (EdgeIterator j(base); j.has_next(); j.next()) {
              j.get()->dump();
            }
            tty->print_cr("----------base has references---------------------");
            for (UseIterator j(base); j.has_next(); j.next()) {
              j.get()->dump();
            }
          }
        }
        for (UseIterator i(field); i.has_next(); i.next()) {
          i.get()->dump();
        }
        assert(field->edge_count() > 0, "sanity");
      }
    }
  }
}
#endif

// Optimize ideal graph.
void ConnectionGraph::optimize_ideal_graph(GrowableArray<Node*>& ptr_cmp_worklist,
                                           GrowableArray<Node*>& storestore_worklist) {
  Compile* C = _compile;
  PhaseIterGVN* igvn = _igvn;
  if (EliminateLocks) {
    // Mark locks before changing ideal graph.
    int cnt = C->macro_count();
    for( int i=0; i < cnt; i++ ) {
      Node *n = C->macro_node(i);
      if (n->is_AbstractLock()) { // Lock and Unlock nodes
        AbstractLockNode* alock = n->as_AbstractLock();
        if (!alock->is_non_esc_obj()) {
          if (not_global_escape(alock->obj_node())) {
            assert(!alock->is_eliminated() || alock->is_coarsened(), "sanity");
            // The lock could be marked eliminated by lock coarsening
            // code during first IGVN before EA. Replace coarsened flag
            // to eliminate all associated locks/unlocks.
#ifdef ASSERT
            alock->log_lock_optimization(C, "eliminate_lock_set_non_esc3");
#endif
            alock->set_non_esc_obj();
          }
        }
      }
    }
  }

  if (OptimizePtrCompare) {
    // Add ConI(#CC_GT) and ConI(#CC_EQ).
    _pcmp_neq = igvn->makecon(TypeInt::CC_GT);
    _pcmp_eq = igvn->makecon(TypeInt::CC_EQ);
    // Optimize objects compare.
    while (ptr_cmp_worklist.length() != 0) {
      Node *n = ptr_cmp_worklist.pop();
      Node *res = optimize_ptr_compare(n);
      if (res != NULL) {
#ifndef PRODUCT
        if (PrintOptimizePtrCompare) {
          tty->print_cr("++++ Replaced: %d %s(%d,%d) --> %s", n->_idx, (n->Opcode() == Op_CmpP ? "CmpP" : "CmpN"), n->in(1)->_idx, n->in(2)->_idx, (res == _pcmp_eq ? "EQ" : "NotEQ"));
          if (Verbose) {
            n->dump(1);
          }
        }
#endif
        igvn->replace_node(n, res);
      }
    }
    // cleanup
    if (_pcmp_neq->outcnt() == 0)
      igvn->hash_delete(_pcmp_neq);
    if (_pcmp_eq->outcnt()  == 0)
      igvn->hash_delete(_pcmp_eq);
  }

  // For MemBarStoreStore nodes added in library_call.cpp, check
  // escape status of associated AllocateNode and optimize out
  // MemBarStoreStore node if the allocated object never escapes.
  while (storestore_worklist.length() != 0) {
    Node *n = storestore_worklist.pop();
    MemBarStoreStoreNode *storestore = n ->as_MemBarStoreStore();
    Node *alloc = storestore->in(MemBarNode::Precedent)->in(0);
    assert (alloc->is_Allocate(), "storestore should point to AllocateNode");
    if (not_global_escape(alloc)) {
      MemBarNode* mb = MemBarNode::make(C, Op_MemBarCPUOrder, Compile::AliasIdxBot);
      mb->init_req(TypeFunc::Memory, storestore->in(TypeFunc::Memory));
      mb->init_req(TypeFunc::Control, storestore->in(TypeFunc::Control));
      igvn->register_new_node_with_optimizer(mb);
      igvn->replace_node(storestore, mb);
    }
  }
}

// Optimize objects compare.
Node* ConnectionGraph::optimize_ptr_compare(Node* n) {
  assert(OptimizePtrCompare, "sanity");
  PointsToNode* ptn1 = ptnode_adr(n->in(1)->_idx);
  PointsToNode* ptn2 = ptnode_adr(n->in(2)->_idx);
  JavaObjectNode* jobj1 = unique_java_object(n->in(1));
  JavaObjectNode* jobj2 = unique_java_object(n->in(2));
  assert(ptn1->is_JavaObject() || ptn1->is_LocalVar(), "sanity");
  assert(ptn2->is_JavaObject() || ptn2->is_LocalVar(), "sanity");

  // Check simple cases first.
  if (jobj1 != NULL) {
    if (jobj1->escape_state() == PointsToNode::NoEscape) {
      if (jobj1 == jobj2) {
        // Comparing the same not escaping object.
        return _pcmp_eq;
      }
      Node* obj = jobj1->ideal_node();
      // Comparing not escaping allocation.
      if ((obj->is_Allocate() || obj->is_CallStaticJava()) &&
          !ptn2->points_to(jobj1)) {
        return _pcmp_neq; // This includes nullness check.
      }
    }
  }
  if (jobj2 != NULL) {
    if (jobj2->escape_state() == PointsToNode::NoEscape) {
      Node* obj = jobj2->ideal_node();
      // Comparing not escaping allocation.
      if ((obj->is_Allocate() || obj->is_CallStaticJava()) &&
          !ptn1->points_to(jobj2)) {
        return _pcmp_neq; // This includes nullness check.
      }
    }
  }
  if (jobj1 != NULL && jobj1 != phantom_obj &&
      jobj2 != NULL && jobj2 != phantom_obj &&
      jobj1->ideal_node()->is_Con() &&
      jobj2->ideal_node()->is_Con()) {
    // Klass or String constants compare. Need to be careful with
    // compressed pointers - compare types of ConN and ConP instead of nodes.
    const Type* t1 = jobj1->ideal_node()->get_ptr_type();
    const Type* t2 = jobj2->ideal_node()->get_ptr_type();
    if (t1->make_ptr() == t2->make_ptr()) {
      return _pcmp_eq;
    } else {
      return _pcmp_neq;
    }
  }
  if (ptn1->meet(ptn2)) {
    return NULL; // Sets are not disjoint
  }

  // Sets are disjoint.
  bool set1_has_unknown_ptr = ptn1->points_to(phantom_obj);
  bool set2_has_unknown_ptr = ptn2->points_to(phantom_obj);
  bool set1_has_null_ptr    = ptn1->points_to(null_obj);
  bool set2_has_null_ptr    = ptn2->points_to(null_obj);
  if (set1_has_unknown_ptr && set2_has_null_ptr ||
      set2_has_unknown_ptr && set1_has_null_ptr) {
    // Check nullness of unknown object.
    return NULL;
  }

  // Disjointness by itself is not sufficient since
  // alias analysis is not complete for escaped objects.
  // Disjoint sets are definitely unrelated only when
  // at least one set has only not escaping allocations.
  if (!set1_has_unknown_ptr && !set1_has_null_ptr) {
    if (ptn1->non_escaping_allocation()) {
      return _pcmp_neq;
    }
  }
  if (!set2_has_unknown_ptr && !set2_has_null_ptr) {
    if (ptn2->non_escaping_allocation()) {
      return _pcmp_neq;
    }
  }
  return NULL;
}

// Connection Graph constuction functions.

void ConnectionGraph::add_local_var(Node *n, PointsToNode::EscapeState es) {
  PointsToNode* ptadr = _nodes.at(n->_idx);
  if (ptadr != NULL) {
    assert(ptadr->is_LocalVar() && ptadr->ideal_node() == n, "sanity");
    return;
  }
  Compile* C = _compile;
  ptadr = new (C->comp_arena()) LocalVarNode(this, n, es);
  _nodes.at_put(n->_idx, ptadr);
}

void ConnectionGraph::add_java_object(Node *n, PointsToNode::EscapeState es) {
  PointsToNode* ptadr = _nodes.at(n->_idx);
  if (ptadr != NULL) {
    assert(ptadr->is_JavaObject() && ptadr->ideal_node() == n, "sanity");
    return;
  }
  Compile* C = _compile;
  ptadr = new (C->comp_arena()) JavaObjectNode(this, n, es);
  _nodes.at_put(n->_idx, ptadr);
}

void ConnectionGraph::add_field(Node *n, PointsToNode::EscapeState es, int offset) {
  PointsToNode* ptadr = _nodes.at(n->_idx);
  if (ptadr != NULL) {
    assert(ptadr->is_Field() && ptadr->ideal_node() == n, "sanity");
    return;
  }
  bool unsafe = false;
  bool is_oop = is_oop_field(n, offset, &unsafe);
  if (unsafe) {
    es = PointsToNode::GlobalEscape;
  }
  Compile* C = _compile;
  FieldNode* field = new (C->comp_arena()) FieldNode(this, n, es, offset, is_oop);
  _nodes.at_put(n->_idx, field);
}

void ConnectionGraph::add_arraycopy(Node *n, PointsToNode::EscapeState es,
                                    PointsToNode* src, PointsToNode* dst) {
  assert(!src->is_Field() && !dst->is_Field(), "only for JavaObject and LocalVar");
  assert((src != null_obj) && (dst != null_obj), "not for ConP NULL");
  PointsToNode* ptadr = _nodes.at(n->_idx);
  if (ptadr != NULL) {
    assert(ptadr->is_Arraycopy() && ptadr->ideal_node() == n, "sanity");
    return;
  }
  Compile* C = _compile;
  ptadr = new (C->comp_arena()) ArraycopyNode(this, n, es);
  _nodes.at_put(n->_idx, ptadr);
  // Add edge from arraycopy node to source object.
  (void)add_edge(ptadr, src);
  src->set_arraycopy_src();
  // Add edge from destination object to arraycopy node.
  (void)add_edge(dst, ptadr);
  dst->set_arraycopy_dst();
}

bool ConnectionGraph::is_oop_field(Node* n, int offset, bool* unsafe) {
  const Type* adr_type = n->as_AddP()->bottom_type();
  BasicType bt = T_INT;
  if (offset == Type::OffsetBot) {
    // Check only oop fields.
    if (!adr_type->isa_aryptr() ||
        (adr_type->isa_aryptr()->klass() == NULL) ||
         adr_type->isa_aryptr()->klass()->is_obj_array_klass()) {
      // OffsetBot is used to reference array's element. Ignore first AddP.
      if (find_second_addp(n, n->in(AddPNode::Base)) == NULL) {
        bt = T_OBJECT;
      }
    }
  } else if (offset != oopDesc::klass_offset_in_bytes()) {
    if (adr_type->isa_instptr()) {
      ciField* field = _compile->alias_type(adr_type->isa_instptr())->field();
      if (field != NULL) {
        bt = field->layout_type();
      } else {
        // Check for unsafe oop field access
        for (DUIterator_Fast imax, i = n->fast_outs(imax); i < imax; i++) {
          int opcode = n->fast_out(i)->Opcode();
          if (opcode == Op_StoreP || opcode == Op_LoadP ||
              opcode == Op_StoreN || opcode == Op_LoadN) {
            bt = T_OBJECT;
            (*unsafe) = true;
            break;
          }
        }
      }
    } else if (adr_type->isa_aryptr()) {
      if (offset == arrayOopDesc::length_offset_in_bytes()) {
        // Ignore array length load.
      } else if (find_second_addp(n, n->in(AddPNode::Base)) != NULL) {
        // Ignore first AddP.
      } else {
        const Type* elemtype = adr_type->isa_aryptr()->elem();
        bt = elemtype->array_element_basic_type();
      }
    } else if (adr_type->isa_rawptr() || adr_type->isa_klassptr()) {
      // Allocation initialization, ThreadLocal field access, unsafe access
      for (DUIterator_Fast imax, i = n->fast_outs(imax); i < imax; i++) {
        int opcode = n->fast_out(i)->Opcode();
        if (opcode == Op_StoreP || opcode == Op_LoadP ||
            opcode == Op_StoreN || opcode == Op_LoadN) {
          bt = T_OBJECT;
          break;
        }
      }
    }
  }
  return (bt == T_OBJECT || bt == T_NARROWOOP || bt == T_ARRAY);
}

// Returns unique pointed java object or NULL.
JavaObjectNode* ConnectionGraph::unique_java_object(Node *n) {
  assert(!_collecting, "should not call when contructed graph");
  // If the node was created after the escape computation we can't answer.
  uint idx = n->_idx;
  if (idx >= nodes_size()) {
    return NULL;
  }
  PointsToNode* ptn = ptnode_adr(idx);
  if (ptn->is_JavaObject()) {
    return ptn->as_JavaObject();
  }
  assert(ptn->is_LocalVar(), "sanity");
  // Check all java objects it points to.
  JavaObjectNode* jobj = NULL;
  for (EdgeIterator i(ptn); i.has_next(); i.next()) {
    PointsToNode* e = i.get();
    if (e->is_JavaObject()) {
      if (jobj == NULL) {
        jobj = e->as_JavaObject();
      } else if (jobj != e) {
        return NULL;
      }
    }
  }
  return jobj;
}

// Return true if this node points only to non-escaping allocations.
bool PointsToNode::non_escaping_allocation() {
  if (is_JavaObject()) {
    Node* n = ideal_node();
    if (n->is_Allocate() || n->is_CallStaticJava()) {
      return (escape_state() == PointsToNode::NoEscape);
    } else {
      return false;
    }
  }
  assert(is_LocalVar(), "sanity");
  // Check all java objects it points to.
  for (EdgeIterator i(this); i.has_next(); i.next()) {
    PointsToNode* e = i.get();
    if (e->is_JavaObject()) {
      Node* n = e->ideal_node();
      if ((e->escape_state() != PointsToNode::NoEscape) ||
          !(n->is_Allocate() || n->is_CallStaticJava())) {
        return false;
      }
    }
  }
  return true;
}

// Return true if we know the node does not escape globally.
bool ConnectionGraph::not_global_escape(Node *n) {
  assert(!_collecting, "should not call during graph construction");
  // If the node was created after the escape computation we can't answer.
  uint idx = n->_idx;
  if (idx >= nodes_size()) {
    return false;
  }
  PointsToNode* ptn = ptnode_adr(idx);
  PointsToNode::EscapeState es = ptn->escape_state();
  // If we have already computed a value, return it.
  if (es >= PointsToNode::GlobalEscape)
    return false;
  if (ptn->is_JavaObject()) {
    return true; // (es < PointsToNode::GlobalEscape);
  }
  assert(ptn->is_LocalVar(), "sanity");
  // Check all java objects it points to.
  for (EdgeIterator i(ptn); i.has_next(); i.next()) {
    if (i.get()->escape_state() >= PointsToNode::GlobalEscape)
      return false;
  }
  return true;
}


// Helper functions

// Return true if this node points to specified node or nodes it points to.
bool PointsToNode::points_to(JavaObjectNode* ptn) const {
  if (is_JavaObject()) {
    return (this == ptn);
  }
  assert(is_LocalVar() || is_Field(), "sanity");
  for (EdgeIterator i(this); i.has_next(); i.next()) {
    if (i.get() == ptn)
      return true;
  }
  return false;
}

// Return true if one node points to an other.
bool PointsToNode::meet(PointsToNode* ptn) {
  if (this == ptn) {
    return true;
  } else if (ptn->is_JavaObject()) {
    return this->points_to(ptn->as_JavaObject());
  } else if (this->is_JavaObject()) {
    return ptn->points_to(this->as_JavaObject());
  }
  assert(this->is_LocalVar() && ptn->is_LocalVar(), "sanity");
  int ptn_count =  ptn->edge_count();
  for (EdgeIterator i(this); i.has_next(); i.next()) {
    PointsToNode* this_e = i.get();
    for (int j = 0; j < ptn_count; j++) {
      if (this_e == ptn->edge(j))
        return true;
    }
  }
  return false;
}

#ifdef ASSERT
// Return true if bases point to this java object.
bool FieldNode::has_base(JavaObjectNode* jobj) const {
  for (BaseIterator i(this); i.has_next(); i.next()) {
    if (i.get() == jobj)
      return true;
  }
  return false;
}
#endif

int ConnectionGraph::address_offset(Node* adr, PhaseTransform *phase) {
  const Type *adr_type = phase->type(adr);
  if (adr->is_AddP() && adr_type->isa_oopptr() == NULL &&
      adr->in(AddPNode::Address)->is_Proj() &&
      adr->in(AddPNode::Address)->in(0)->is_Allocate()) {
    // We are computing a raw address for a store captured by an Initialize
    // compute an appropriate address type. AddP cases #3 and #5 (see below).
    int offs = (int)phase->find_intptr_t_con(adr->in(AddPNode::Offset), Type::OffsetBot);
    assert(offs != Type::OffsetBot ||
           adr->in(AddPNode::Address)->in(0)->is_AllocateArray(),
           "offset must be a constant or it is initialization of array");
    return offs;
  }
  const TypePtr *t_ptr = adr_type->isa_ptr();
  assert(t_ptr != NULL, "must be a pointer type");
  return t_ptr->offset();
}

Node* ConnectionGraph::get_addp_base(Node *addp) {
  assert(addp->is_AddP(), "must be AddP");
  //
  // AddP cases for Base and Address inputs:
  // case #1. Direct object's field reference:
  //     Allocate
  //       |
  //     Proj #5 ( oop result )
  //       |
  //     CheckCastPP (cast to instance type)
  //      | |
  //     AddP  ( base == address )
  //
  // case #2. Indirect object's field reference:
  //      Phi
  //       |
  //     CastPP (cast to instance type)
  //      | |
  //     AddP  ( base == address )
  //
  // case #3. Raw object's field reference for Initialize node:
  //      Allocate
  //        |
  //      Proj #5 ( oop result )
  //  top   |
  //     \  |
  //     AddP  ( base == top )
  //
  // case #4. Array's element reference:
  //   {CheckCastPP | CastPP}
  //     |  | |
  //     |  AddP ( array's element offset )
  //     |  |
  //     AddP ( array's offset )
  //
  // case #5. Raw object's field reference for arraycopy stub call:
  //          The inline_native_clone() case when the arraycopy stub is called
  //          after the allocation before Initialize and CheckCastPP nodes.
  //      Allocate
  //        |
  //      Proj #5 ( oop result )
  //       | |
  //       AddP  ( base == address )
  //
  // case #6. Constant Pool, ThreadLocal, CastX2P or
  //          Raw object's field reference:
  //      {ConP, ThreadLocal, CastX2P, raw Load}
  //  top   |
  //     \  |
  //     AddP  ( base == top )
  //
  // case #7. Klass's field reference.
  //      LoadKlass
  //       | |
  //       AddP  ( base == address )
  //
  // case #8. narrow Klass's field reference.
  //      LoadNKlass
  //       |
  //      DecodeN
  //       | |
  //       AddP  ( base == address )
  //
  Node *base = addp->in(AddPNode::Base);
  if (base->uncast()->is_top()) { // The AddP case #3 and #6.
    base = addp->in(AddPNode::Address);
    while (base->is_AddP()) {
      // Case #6 (unsafe access) may have several chained AddP nodes.
      assert(base->in(AddPNode::Base)->uncast()->is_top(), "expected unsafe access address only");
      base = base->in(AddPNode::Address);
    }
    Node* uncast_base = base->uncast();
    int opcode = uncast_base->Opcode();
    assert(opcode == Op_ConP || opcode == Op_ThreadLocal ||
           opcode == Op_CastX2P || uncast_base->is_DecodeNarrowPtr() ||
           (uncast_base->is_Mem() && (uncast_base->bottom_type()->isa_rawptr() != NULL)) ||
           (uncast_base->is_Proj() && uncast_base->in(0)->is_Allocate()), "sanity");
  }
  return base;
}

Node* ConnectionGraph::find_second_addp(Node* addp, Node* n) {
  assert(addp->is_AddP() && addp->outcnt() > 0, "Don't process dead nodes");
  Node* addp2 = addp->raw_out(0);
  if (addp->outcnt() == 1 && addp2->is_AddP() &&
      addp2->in(AddPNode::Base) == n &&
      addp2->in(AddPNode::Address) == addp) {
    assert(addp->in(AddPNode::Base) == n, "expecting the same base");
    //
    // Find array's offset to push it on worklist first and
    // as result process an array's element offset first (pushed second)
    // to avoid CastPP for the array's offset.
    // Otherwise the inserted CastPP (LocalVar) will point to what
    // the AddP (Field) points to. Which would be wrong since
    // the algorithm expects the CastPP has the same point as
    // as AddP's base CheckCastPP (LocalVar).
    //
    //    ArrayAllocation
    //     |
    //    CheckCastPP
    //     |
    //    memProj (from ArrayAllocation CheckCastPP)
    //     |  ||
    //     |  ||   Int (element index)
    //     |  ||    |   ConI (log(element size))
    //     |  ||    |   /
    //     |  ||   LShift
    //     |  ||  /
    //     |  AddP (array's element offset)
    //     |  |
    //     |  | ConI (array's offset: #12(32-bits) or #24(64-bits))
    //     | / /
    //     AddP (array's offset)
    //      |
    //     Load/Store (memory operation on array's element)
    //
    return addp2;
  }
  return NULL;
}

//
// Adjust the type and inputs of an AddP which computes the
// address of a field of an instance
//
bool ConnectionGraph::split_AddP(Node *addp, Node *base) {
  PhaseGVN* igvn = _igvn;
  const TypeOopPtr *base_t = igvn->type(base)->isa_oopptr();
  assert(base_t != NULL && base_t->is_known_instance(), "expecting instance oopptr");
  const TypeOopPtr *t = igvn->type(addp)->isa_oopptr();
  if (t == NULL) {
    // We are computing a raw address for a store captured by an Initialize
    // compute an appropriate address type (cases #3 and #5).
    assert(igvn->type(addp) == TypeRawPtr::NOTNULL, "must be raw pointer");
    assert(addp->in(AddPNode::Address)->is_Proj(), "base of raw address must be result projection from allocation");
    intptr_t offs = (int)igvn->find_intptr_t_con(addp->in(AddPNode::Offset), Type::OffsetBot);
    assert(offs != Type::OffsetBot, "offset must be a constant");
    t = base_t->add_offset(offs)->is_oopptr();
  }
  int inst_id =  base_t->instance_id();
  assert(!t->is_known_instance() || t->instance_id() == inst_id,
                             "old type must be non-instance or match new type");

  // The type 't' could be subclass of 'base_t'.
  // As result t->offset() could be large then base_t's size and it will
  // cause the failure in add_offset() with narrow oops since TypeOopPtr()
  // constructor verifies correctness of the offset.
  //
  // It could happened on subclass's branch (from the type profiling
  // inlining) which was not eliminated during parsing since the exactness
  // of the allocation type was not propagated to the subclass type check.
  //
  // Or the type 't' could be not related to 'base_t' at all.
  // It could happened when CHA type is different from MDO type on a dead path
  // (for example, from instanceof check) which is not collapsed during parsing.
  //
  // Do nothing for such AddP node and don't process its users since
  // this code branch will go away.
  //
  if (!t->is_known_instance() &&
      !base_t->klass()->is_subtype_of(t->klass())) {
     return false; // bail out
  }
  const TypeOopPtr *tinst = base_t->add_offset(t->offset())->is_oopptr();
  // Do NOT remove the next line: ensure a new alias index is allocated
  // for the instance type. Note: C++ will not remove it since the call
  // has side effect.
  int alias_idx = _compile->get_alias_index(tinst);
  igvn->set_type(addp, tinst);
  // record the allocation in the node map
  set_map(addp, get_map(base->_idx));
  // Set addp's Base and Address to 'base'.
  Node *abase = addp->in(AddPNode::Base);
  Node *adr   = addp->in(AddPNode::Address);
  if (adr->is_Proj() && adr->in(0)->is_Allocate() &&
      adr->in(0)->_idx == (uint)inst_id) {
    // Skip AddP cases #3 and #5.
  } else {
    assert(!abase->is_top(), "sanity"); // AddP case #3
    if (abase != base) {
      igvn->hash_delete(addp);
      addp->set_req(AddPNode::Base, base);
      if (abase == adr) {
        addp->set_req(AddPNode::Address, base);
      } else {
        // AddP case #4 (adr is array's element offset AddP node)
#ifdef ASSERT
        const TypeOopPtr *atype = igvn->type(adr)->isa_oopptr();
        assert(adr->is_AddP() && atype != NULL &&
               atype->instance_id() == inst_id, "array's element offset should be processed first");
#endif
      }
      igvn->hash_insert(addp);
    }
  }
  // Put on IGVN worklist since at least addp's type was changed above.
  record_for_optimizer(addp);
  return true;
}

//
// Create a new version of orig_phi if necessary. Returns either the newly
// created phi or an existing phi.  Sets create_new to indicate whether a new
// phi was created.  Cache the last newly created phi in the node map.
//
PhiNode *ConnectionGraph::create_split_phi(PhiNode *orig_phi, int alias_idx, GrowableArray<PhiNode *>  &orig_phi_worklist, bool &new_created) {
  Compile *C = _compile;
  PhaseGVN* igvn = _igvn;
  new_created = false;
  int phi_alias_idx = C->get_alias_index(orig_phi->adr_type());
  // nothing to do if orig_phi is bottom memory or matches alias_idx
  if (phi_alias_idx == alias_idx) {
    return orig_phi;
  }
  // Have we recently created a Phi for this alias index?
  PhiNode *result = get_map_phi(orig_phi->_idx);
  if (result != NULL && C->get_alias_index(result->adr_type()) == alias_idx) {
    return result;
  }
  // Previous check may fail when the same wide memory Phi was split into Phis
  // for different memory slices. Search all Phis for this region.
  if (result != NULL) {
    Node* region = orig_phi->in(0);
    for (DUIterator_Fast imax, i = region->fast_outs(imax); i < imax; i++) {
      Node* phi = region->fast_out(i);
      if (phi->is_Phi() &&
          C->get_alias_index(phi->as_Phi()->adr_type()) == alias_idx) {
        assert(phi->_idx >= nodes_size(), "only new Phi per instance memory slice");
        return phi->as_Phi();
      }
    }
  }
  if (C->live_nodes() + 2*NodeLimitFudgeFactor > C->max_node_limit()) {
    if (C->do_escape_analysis() == true && !C->failing()) {
      // Retry compilation without escape analysis.
      // If this is the first failure, the sentinel string will "stick"
      // to the Compile object, and the C2Compiler will see it and retry.
      C->record_failure(C2Compiler::retry_no_escape_analysis());
    }
    return NULL;
  }
  orig_phi_worklist.append_if_missing(orig_phi);
  const TypePtr *atype = C->get_adr_type(alias_idx);
  result = PhiNode::make(orig_phi->in(0), NULL, Type::MEMORY, atype);
  C->copy_node_notes_to(result, orig_phi);
  igvn->set_type(result, result->bottom_type());
  record_for_optimizer(result);
  set_map(orig_phi, result);
  new_created = true;
  return result;
}

//
// Return a new version of Memory Phi "orig_phi" with the inputs having the
// specified alias index.
//
PhiNode *ConnectionGraph::split_memory_phi(PhiNode *orig_phi, int alias_idx, GrowableArray<PhiNode *>  &orig_phi_worklist) {
  assert(alias_idx != Compile::AliasIdxBot, "can't split out bottom memory");
  Compile *C = _compile;
  PhaseGVN* igvn = _igvn;
  bool new_phi_created;
  PhiNode *result = create_split_phi(orig_phi, alias_idx, orig_phi_worklist, new_phi_created);
  if (!new_phi_created) {
    return result;
  }
  GrowableArray<PhiNode *>  phi_list;
  GrowableArray<uint>  cur_input;
  PhiNode *phi = orig_phi;
  uint idx = 1;
  bool finished = false;
  while(!finished) {
    while (idx < phi->req()) {
      Node *mem = find_inst_mem(phi->in(idx), alias_idx, orig_phi_worklist);
      if (mem != NULL && mem->is_Phi()) {
        PhiNode *newphi = create_split_phi(mem->as_Phi(), alias_idx, orig_phi_worklist, new_phi_created);
        if (new_phi_created) {
          // found an phi for which we created a new split, push current one on worklist and begin
          // processing new one
          phi_list.push(phi);
          cur_input.push(idx);
          phi = mem->as_Phi();
          result = newphi;
          idx = 1;
          continue;
        } else {
          mem = newphi;
        }
      }
      if (C->failing()) {
        return NULL;
      }
      result->set_req(idx++, mem);
    }
#ifdef ASSERT
    // verify that the new Phi has an input for each input of the original
    assert( phi->req() == result->req(), "must have same number of inputs.");
    assert( result->in(0) != NULL && result->in(0) == phi->in(0), "regions must match");
#endif
    // Check if all new phi's inputs have specified alias index.
    // Otherwise use old phi.
    for (uint i = 1; i < phi->req(); i++) {
      Node* in = result->in(i);
      assert((phi->in(i) == NULL) == (in == NULL), "inputs must correspond.");
    }
    // we have finished processing a Phi, see if there are any more to do
    finished = (phi_list.length() == 0 );
    if (!finished) {
      phi = phi_list.pop();
      idx = cur_input.pop();
      PhiNode *prev_result = get_map_phi(phi->_idx);
      prev_result->set_req(idx++, result);
      result = prev_result;
    }
  }
  return result;
}

//
// The next methods are derived from methods in MemNode.
//
Node* ConnectionGraph::step_through_mergemem(MergeMemNode *mmem, int alias_idx, const TypeOopPtr *toop) {
  Node *mem = mmem;
  // TypeOopPtr::NOTNULL+any is an OOP with unknown offset - generally
  // means an array I have not precisely typed yet.  Do not do any
  // alias stuff with it any time soon.
  if (toop->base() != Type::AnyPtr &&
      !(toop->klass() != NULL &&
        toop->klass()->is_java_lang_Object() &&
        toop->offset() == Type::OffsetBot)) {
    mem = mmem->memory_at(alias_idx);
    // Update input if it is progress over what we have now
  }
  return mem;
}

//
// Move memory users to their memory slices.
//
void ConnectionGraph::move_inst_mem(Node* n, GrowableArray<PhiNode *>  &orig_phis) {
  Compile* C = _compile;
  PhaseGVN* igvn = _igvn;
  const TypePtr* tp = igvn->type(n->in(MemNode::Address))->isa_ptr();
  assert(tp != NULL, "ptr type");
  int alias_idx = C->get_alias_index(tp);
  int general_idx = C->get_general_index(alias_idx);

  // Move users first
  for (DUIterator_Fast imax, i = n->fast_outs(imax); i < imax; i++) {
    Node* use = n->fast_out(i);
    if (use->is_MergeMem()) {
      MergeMemNode* mmem = use->as_MergeMem();
      assert(n == mmem->memory_at(alias_idx), "should be on instance memory slice");
      if (n != mmem->memory_at(general_idx) || alias_idx == general_idx) {
        continue; // Nothing to do
      }
      // Replace previous general reference to mem node.
      uint orig_uniq = C->unique();
      Node* m = find_inst_mem(n, general_idx, orig_phis);
      assert(orig_uniq == C->unique(), "no new nodes");
      mmem->set_memory_at(general_idx, m);
      --imax;
      --i;
    } else if (use->is_MemBar()) {
      assert(!use->is_Initialize(), "initializing stores should not be moved");
      if (use->req() > MemBarNode::Precedent &&
          use->in(MemBarNode::Precedent) == n) {
        // Don't move related membars.
        record_for_optimizer(use);
        continue;
      }
      tp = use->as_MemBar()->adr_type()->isa_ptr();
      if (tp != NULL && C->get_alias_index(tp) == alias_idx ||
          alias_idx == general_idx) {
        continue; // Nothing to do
      }
      // Move to general memory slice.
      uint orig_uniq = C->unique();
      Node* m = find_inst_mem(n, general_idx, orig_phis);
      assert(orig_uniq == C->unique(), "no new nodes");
      igvn->hash_delete(use);
      imax -= use->replace_edge(n, m);
      igvn->hash_insert(use);
      record_for_optimizer(use);
      --i;
#ifdef ASSERT
    } else if (use->is_Mem()) {
      if (use->Opcode() == Op_StoreCM && use->in(MemNode::OopStore) == n) {
        // Don't move related cardmark.
        continue;
      }
      // Memory nodes should have new memory input.
      tp = igvn->type(use->in(MemNode::Address))->isa_ptr();
      assert(tp != NULL, "ptr type");
      int idx = C->get_alias_index(tp);
      assert(get_map(use->_idx) != NULL || idx == alias_idx,
             "Following memory nodes should have new memory input or be on the same memory slice");
    } else if (use->is_Phi()) {
      // Phi nodes should be split and moved already.
      tp = use->as_Phi()->adr_type()->isa_ptr();
      assert(tp != NULL, "ptr type");
      int idx = C->get_alias_index(tp);
      assert(idx == alias_idx, "Following Phi nodes should be on the same memory slice");
    } else {
      use->dump();
      assert(false, "should not be here");
#endif
    }
  }
}

//
// Search memory chain of "mem" to find a MemNode whose address
// is the specified alias index.
//
Node* ConnectionGraph::find_inst_mem(Node *orig_mem, int alias_idx, GrowableArray<PhiNode *>  &orig_phis) {
  if (orig_mem == NULL)
    return orig_mem;
  Compile* C = _compile;
  PhaseGVN* igvn = _igvn;
  const TypeOopPtr *toop = C->get_adr_type(alias_idx)->isa_oopptr();
  bool is_instance = (toop != NULL) && toop->is_known_instance();
  Node *start_mem = C->start()->proj_out(TypeFunc::Memory);
  Node *prev = NULL;
  Node *result = orig_mem;
  while (prev != result) {
    prev = result;
    if (result == start_mem)
      break;  // hit one of our sentinels
    if (result->is_Mem()) {
      const Type *at = igvn->type(result->in(MemNode::Address));
      if (at == Type::TOP)
        break; // Dead
      assert (at->isa_ptr() != NULL, "pointer type required.");
      int idx = C->get_alias_index(at->is_ptr());
      if (idx == alias_idx)
        break; // Found
      if (!is_instance && (at->isa_oopptr() == NULL ||
                           !at->is_oopptr()->is_known_instance())) {
        break; // Do not skip store to general memory slice.
      }
      result = result->in(MemNode::Memory);
    }
    if (!is_instance)
      continue;  // don't search further for non-instance types
    // skip over a call which does not affect this memory slice
    if (result->is_Proj() && result->as_Proj()->_con == TypeFunc::Memory) {
      Node *proj_in = result->in(0);
      if (proj_in->is_Allocate() && proj_in->_idx == (uint)toop->instance_id()) {
        break;  // hit one of our sentinels
      } else if (proj_in->is_Call()) {
        CallNode *call = proj_in->as_Call();
        if (!call->may_modify(toop, igvn)) {
          result = call->in(TypeFunc::Memory);
        }
      } else if (proj_in->is_Initialize()) {
        AllocateNode* alloc = proj_in->as_Initialize()->allocation();
        // Stop if this is the initialization for the object instance which
        // which contains this memory slice, otherwise skip over it.
        if (alloc == NULL || alloc->_idx != (uint)toop->instance_id()) {
          result = proj_in->in(TypeFunc::Memory);
        }
      } else if (proj_in->is_MemBar()) {
        result = proj_in->in(TypeFunc::Memory);
      }
    } else if (result->is_MergeMem()) {
      MergeMemNode *mmem = result->as_MergeMem();
      result = step_through_mergemem(mmem, alias_idx, toop);
      if (result == mmem->base_memory()) {
        // Didn't find instance memory, search through general slice recursively.
        result = mmem->memory_at(C->get_general_index(alias_idx));
        result = find_inst_mem(result, alias_idx, orig_phis);
        if (C->failing()) {
          return NULL;
        }
        mmem->set_memory_at(alias_idx, result);
      }
    } else if (result->is_Phi() &&
               C->get_alias_index(result->as_Phi()->adr_type()) != alias_idx) {
      Node *un = result->as_Phi()->unique_input(igvn);
      if (un != NULL) {
        orig_phis.append_if_missing(result->as_Phi());
        result = un;
      } else {
        break;
      }
    } else if (result->is_ClearArray()) {
      if (!ClearArrayNode::step_through(&result, (uint)toop->instance_id(), igvn)) {
        // Can not bypass initialization of the instance
        // we are looking for.
        break;
      }
      // Otherwise skip it (the call updated 'result' value).
    } else if (result->Opcode() == Op_SCMemProj) {
      Node* mem = result->in(0);
      Node* adr = NULL;
      if (mem->is_LoadStore()) {
        adr = mem->in(MemNode::Address);
      } else {
        assert(mem->Opcode() == Op_EncodeISOArray, "sanity");
        adr = mem->in(3); // Memory edge corresponds to destination array
      }
      const Type *at = igvn->type(adr);
      if (at != Type::TOP) {
        assert (at->isa_ptr() != NULL, "pointer type required.");
        int idx = C->get_alias_index(at->is_ptr());
        assert(idx != alias_idx, "Object is not scalar replaceable if a LoadStore node access its field");
        break;
      }
      result = mem->in(MemNode::Memory);
    }
  }
  if (result->is_Phi()) {
    PhiNode *mphi = result->as_Phi();
    assert(mphi->bottom_type() == Type::MEMORY, "memory phi required");
    const TypePtr *t = mphi->adr_type();
    if (!is_instance) {
      // Push all non-instance Phis on the orig_phis worklist to update inputs
      // during Phase 4 if needed.
      orig_phis.append_if_missing(mphi);
    } else if (C->get_alias_index(t) != alias_idx) {
      // Create a new Phi with the specified alias index type.
      result = split_memory_phi(mphi, alias_idx, orig_phis);
    }
  }
  // the result is either MemNode, PhiNode, InitializeNode.
  return result;
}

//
//  Convert the types of unescaped object to instance types where possible,
//  propagate the new type information through the graph, and update memory
//  edges and MergeMem inputs to reflect the new type.
//
//  We start with allocations (and calls which may be allocations)  on alloc_worklist.
//  The processing is done in 4 phases:
//
//  Phase 1:  Process possible allocations from alloc_worklist.  Create instance
//            types for the CheckCastPP for allocations where possible.
//            Propagate the the new types through users as follows:
//               casts and Phi:  push users on alloc_worklist
//               AddP:  cast Base and Address inputs to the instance type
//                      push any AddP users on alloc_worklist and push any memnode
//                      users onto memnode_worklist.
//  Phase 2:  Process MemNode's from memnode_worklist. compute new address type and
//            search the Memory chain for a store with the appropriate type
//            address type.  If a Phi is found, create a new version with
//            the appropriate memory slices from each of the Phi inputs.
//            For stores, process the users as follows:
//               MemNode:  push on memnode_worklist
//               MergeMem: push on mergemem_worklist
//  Phase 3:  Process MergeMem nodes from mergemem_worklist.  Walk each memory slice
//            moving the first node encountered of each  instance type to the
//            the input corresponding to its alias index.
//            appropriate memory slice.
//  Phase 4:  Update the inputs of non-instance memory Phis and the Memory input of memnodes.
//
// In the following example, the CheckCastPP nodes are the cast of allocation
// results and the allocation of node 29 is unescaped and eligible to be an
// instance type.
//
// We start with:
//
//     7 Parm #memory
//    10  ConI  "12"
//    19  CheckCastPP   "Foo"
//    20  AddP  _ 19 19 10  Foo+12  alias_index=4
//    29  CheckCastPP   "Foo"
//    30  AddP  _ 29 29 10  Foo+12  alias_index=4
//
//    40  StoreP  25   7  20   ... alias_index=4
//    50  StoreP  35  40  30   ... alias_index=4
//    60  StoreP  45  50  20   ... alias_index=4
//    70  LoadP    _  60  30   ... alias_index=4
//    80  Phi     75  50  60   Memory alias_index=4
//    90  LoadP    _  80  30   ... alias_index=4
//   100  LoadP    _  80  20   ... alias_index=4
//
//
// Phase 1 creates an instance type for node 29 assigning it an instance id of 24
// and creating a new alias index for node 30.  This gives:
//
//     7 Parm #memory
//    10  ConI  "12"
//    19  CheckCastPP   "Foo"
//    20  AddP  _ 19 19 10  Foo+12  alias_index=4
//    29  CheckCastPP   "Foo"  iid=24
//    30  AddP  _ 29 29 10  Foo+12  alias_index=6  iid=24
//
//    40  StoreP  25   7  20   ... alias_index=4
//    50  StoreP  35  40  30   ... alias_index=6
//    60  StoreP  45  50  20   ... alias_index=4
//    70  LoadP    _  60  30   ... alias_index=6
//    80  Phi     75  50  60   Memory alias_index=4
//    90  LoadP    _  80  30   ... alias_index=6
//   100  LoadP    _  80  20   ... alias_index=4
//
// In phase 2, new memory inputs are computed for the loads and stores,
// And a new version of the phi is created.  In phase 4, the inputs to
// node 80 are updated and then the memory nodes are updated with the
// values computed in phase 2.  This results in:
//
//     7 Parm #memory
//    10  ConI  "12"
//    19  CheckCastPP   "Foo"
//    20  AddP  _ 19 19 10  Foo+12  alias_index=4
//    29  CheckCastPP   "Foo"  iid=24
//    30  AddP  _ 29 29 10  Foo+12  alias_index=6  iid=24
//
//    40  StoreP  25  7   20   ... alias_index=4
//    50  StoreP  35  7   30   ... alias_index=6
//    60  StoreP  45  40  20   ... alias_index=4
//    70  LoadP    _  50  30   ... alias_index=6
//    80  Phi     75  40  60   Memory alias_index=4
//   120  Phi     75  50  50   Memory alias_index=6
//    90  LoadP    _ 120  30   ... alias_index=6
//   100  LoadP    _  80  20   ... alias_index=4
//
void ConnectionGraph::split_unique_types(GrowableArray<Node *>  &alloc_worklist) {
  GrowableArray<Node *>  memnode_worklist;
  GrowableArray<PhiNode *>  orig_phis;
  PhaseIterGVN  *igvn = _igvn;
  uint new_index_start = (uint) _compile->num_alias_types();
  Arena* arena = Thread::current()->resource_area();
  VectorSet visited(arena);
  ideal_nodes.clear(); // Reset for use with set_map/get_map.
  uint unique_old = _compile->unique();

  //  Phase 1:  Process possible allocations from alloc_worklist.
  //  Create instance types for the CheckCastPP for allocations where possible.
  //
  // (Note: don't forget to change the order of the second AddP node on
  //  the alloc_worklist if the order of the worklist processing is changed,
  //  see the comment in find_second_addp().)
  //
  while (alloc_worklist.length() != 0) {
    Node *n = alloc_worklist.pop();
    uint ni = n->_idx;
    if (n->is_Call()) {
      CallNode *alloc = n->as_Call();
      // copy escape information to call node
      PointsToNode* ptn = ptnode_adr(alloc->_idx);
      PointsToNode::EscapeState es = ptn->escape_state();
      // We have an allocation or call which returns a Java object,
      // see if it is unescaped.
      if (es != PointsToNode::NoEscape || !ptn->scalar_replaceable())
        continue;
      // Find CheckCastPP for the allocate or for the return value of a call
      n = alloc->result_cast();
      if (n == NULL) {            // No uses except Initialize node
        if (alloc->is_Allocate()) {
          // Set the scalar_replaceable flag for allocation
          // so it could be eliminated if it has no uses.
          alloc->as_Allocate()->_is_scalar_replaceable = true;
        }
        if (alloc->is_CallStaticJava()) {
          // Set the scalar_replaceable flag for boxing method
          // so it could be eliminated if it has no uses.
          alloc->as_CallStaticJava()->_is_scalar_replaceable = true;
        }
        continue;
      }
      if (!n->is_CheckCastPP()) { // not unique CheckCastPP.
        assert(!alloc->is_Allocate(), "allocation should have unique type");
        continue;
      }

      // The inline code for Object.clone() casts the allocation result to
      // java.lang.Object and then to the actual type of the allocated
      // object. Detect this case and use the second cast.
      // Also detect j.l.reflect.Array.newInstance(jobject, jint) case when
      // the allocation result is cast to java.lang.Object and then
      // to the actual Array type.
      if (alloc->is_Allocate() && n->as_Type()->type() == TypeInstPtr::NOTNULL
          && (alloc->is_AllocateArray() ||
              igvn->type(alloc->in(AllocateNode::KlassNode)) != TypeKlassPtr::OBJECT)) {
        Node *cast2 = NULL;
        for (DUIterator_Fast imax, i = n->fast_outs(imax); i < imax; i++) {
          Node *use = n->fast_out(i);
          if (use->is_CheckCastPP()) {
            cast2 = use;
            break;
          }
        }
        if (cast2 != NULL) {
          n = cast2;
        } else {
          // Non-scalar replaceable if the allocation type is unknown statically
          // (reflection allocation), the object can't be restored during
          // deoptimization without precise type.
          continue;
        }
      }

      const TypeOopPtr *t = igvn->type(n)->isa_oopptr();
      if (t == NULL)
        continue;  // not a TypeOopPtr
      if (!t->klass_is_exact())
        continue; // not an unique type

      if (alloc->is_Allocate()) {
        // Set the scalar_replaceable flag for allocation
        // so it could be eliminated.
        alloc->as_Allocate()->_is_scalar_replaceable = true;
      }
      if (alloc->is_CallStaticJava()) {
        // Set the scalar_replaceable flag for boxing method
        // so it could be eliminated.
        alloc->as_CallStaticJava()->_is_scalar_replaceable = true;
      }
      set_escape_state(ptnode_adr(n->_idx), es); // CheckCastPP escape state
      // in order for an object to be scalar-replaceable, it must be:
      //   - a direct allocation (not a call returning an object)
      //   - non-escaping
      //   - eligible to be a unique type
      //   - not determined to be ineligible by escape analysis
      set_map(alloc, n);
      set_map(n, alloc);
      const TypeOopPtr* tinst = t->cast_to_instance_id(ni);
      igvn->hash_delete(n);
      igvn->set_type(n,  tinst);
      n->raise_bottom_type(tinst);
      igvn->hash_insert(n);
      record_for_optimizer(n);
      if (alloc->is_Allocate() && (t->isa_instptr() || t->isa_aryptr())) {

        // First, put on the worklist all Field edges from Connection Graph
        // which is more accurate then putting immediate users from Ideal Graph.
        for (EdgeIterator e(ptn); e.has_next(); e.next()) {
          PointsToNode* tgt = e.get();
          Node* use = tgt->ideal_node();
          assert(tgt->is_Field() && use->is_AddP(),
                 "only AddP nodes are Field edges in CG");
          if (use->outcnt() > 0) { // Don't process dead nodes
            Node* addp2 = find_second_addp(use, use->in(AddPNode::Base));
            if (addp2 != NULL) {
              assert(alloc->is_AllocateArray(),"array allocation was expected");
              alloc_worklist.append_if_missing(addp2);
            }
            alloc_worklist.append_if_missing(use);
          }
        }

        // An allocation may have an Initialize which has raw stores. Scan
        // the users of the raw allocation result and push AddP users
        // on alloc_worklist.
        Node *raw_result = alloc->proj_out(TypeFunc::Parms);
        assert (raw_result != NULL, "must have an allocation result");
        for (DUIterator_Fast imax, i = raw_result->fast_outs(imax); i < imax; i++) {
          Node *use = raw_result->fast_out(i);
          if (use->is_AddP() && use->outcnt() > 0) { // Don't process dead nodes
            Node* addp2 = find_second_addp(use, raw_result);
            if (addp2 != NULL) {
              assert(alloc->is_AllocateArray(),"array allocation was expected");
              alloc_worklist.append_if_missing(addp2);
            }
            alloc_worklist.append_if_missing(use);
          } else if (use->is_MemBar()) {
            memnode_worklist.append_if_missing(use);
          }
        }
      }
    } else if (n->is_AddP()) {
      JavaObjectNode* jobj = unique_java_object(get_addp_base(n));
      if (jobj == NULL || jobj == phantom_obj) {
#ifdef ASSERT
        ptnode_adr(get_addp_base(n)->_idx)->dump();
        ptnode_adr(n->_idx)->dump();
        assert(jobj != NULL && jobj != phantom_obj, "escaped allocation");
#endif
        _compile->record_failure(C2Compiler::retry_no_escape_analysis());
        return;
      }
      Node *base = get_map(jobj->idx());  // CheckCastPP node
      if (!split_AddP(n, base)) continue; // wrong type from dead path
    } else if (n->is_Phi() ||
               n->is_CheckCastPP() ||
               n->is_EncodeP() ||
               n->is_DecodeN() ||
               (n->is_ConstraintCast() && n->Opcode() == Op_CastPP)) {
      if (visited.test_set(n->_idx)) {
        assert(n->is_Phi(), "loops only through Phi's");
        continue;  // already processed
      }
      JavaObjectNode* jobj = unique_java_object(n);
      if (jobj == NULL || jobj == phantom_obj) {
#ifdef ASSERT
        ptnode_adr(n->_idx)->dump();
        assert(jobj != NULL && jobj != phantom_obj, "escaped allocation");
#endif
        _compile->record_failure(C2Compiler::retry_no_escape_analysis());
        return;
      } else {
        Node *val = get_map(jobj->idx());   // CheckCastPP node
        TypeNode *tn = n->as_Type();
        const TypeOopPtr* tinst = igvn->type(val)->isa_oopptr();
        assert(tinst != NULL && tinst->is_known_instance() &&
               tinst->instance_id() == jobj->idx() , "instance type expected.");

        const Type *tn_type = igvn->type(tn);
        const TypeOopPtr *tn_t;
        if (tn_type->isa_narrowoop()) {
          tn_t = tn_type->make_ptr()->isa_oopptr();
        } else {
          tn_t = tn_type->isa_oopptr();
        }
        if (tn_t != NULL && tinst->klass()->is_subtype_of(tn_t->klass())) {
          if (tn_type->isa_narrowoop()) {
            tn_type = tinst->make_narrowoop();
          } else {
            tn_type = tinst;
          }
          igvn->hash_delete(tn);
          igvn->set_type(tn, tn_type);
          tn->set_type(tn_type);
          igvn->hash_insert(tn);
          record_for_optimizer(n);
        } else {
          assert(tn_type == TypePtr::NULL_PTR ||
                 tn_t != NULL && !tinst->klass()->is_subtype_of(tn_t->klass()),
                 "unexpected type");
          continue; // Skip dead path with different type
        }
      }
    } else {
      debug_only(n->dump();)
      assert(false, "EA: unexpected node");
      continue;
    }
    // push allocation's users on appropriate worklist
    for (DUIterator_Fast imax, i = n->fast_outs(imax); i < imax; i++) {
      Node *use = n->fast_out(i);
      if(use->is_Mem() && use->in(MemNode::Address) == n) {
        // Load/store to instance's field
        memnode_worklist.append_if_missing(use);
      } else if (use->is_MemBar()) {
        if (use->in(TypeFunc::Memory) == n) { // Ignore precedent edge
          memnode_worklist.append_if_missing(use);
        }
      } else if (use->is_AddP() && use->outcnt() > 0) { // No dead nodes
        Node* addp2 = find_second_addp(use, n);
        if (addp2 != NULL) {
          alloc_worklist.append_if_missing(addp2);
        }
        alloc_worklist.append_if_missing(use);
      } else if (use->is_Phi() ||
                 use->is_CheckCastPP() ||
                 use->is_EncodeNarrowPtr() ||
                 use->is_DecodeNarrowPtr() ||
                 (use->is_ConstraintCast() && use->Opcode() == Op_CastPP)) {
        alloc_worklist.append_if_missing(use);
#ifdef ASSERT
      } else if (use->is_Mem()) {
        assert(use->in(MemNode::Address) != n, "EA: missing allocation reference path");
      } else if (use->is_MergeMem()) {
        assert(_mergemem_worklist.contains(use->as_MergeMem()), "EA: missing MergeMem node in the worklist");
      } else if (use->is_SafePoint()) {
        // Look for MergeMem nodes for calls which reference unique allocation
        // (through CheckCastPP nodes) even for debug info.
        Node* m = use->in(TypeFunc::Memory);
        if (m->is_MergeMem()) {
          assert(_mergemem_worklist.contains(m->as_MergeMem()), "EA: missing MergeMem node in the worklist");
        }
      } else if (use->Opcode() == Op_EncodeISOArray) {
        if (use->in(MemNode::Memory) == n || use->in(3) == n) {
          // EncodeISOArray overwrites destination array
          memnode_worklist.append_if_missing(use);
        }
      } else {
        uint op = use->Opcode();
        if (!(op == Op_CmpP || op == Op_Conv2B ||
              op == Op_CastP2X || op == Op_StoreCM ||
              op == Op_FastLock || op == Op_AryEq || op == Op_StrComp ||
              op == Op_StrEquals || op == Op_StrIndexOf)) {
          n->dump();
          use->dump();
          assert(false, "EA: missing allocation reference path");
        }
#endif
      }
    }

  }
  // New alias types were created in split_AddP().
  uint new_index_end = (uint) _compile->num_alias_types();
  assert(unique_old == _compile->unique(), "there should be no new ideal nodes after Phase 1");

  //  Phase 2:  Process MemNode's from memnode_worklist. compute new address type and
  //            compute new values for Memory inputs  (the Memory inputs are not
  //            actually updated until phase 4.)
  if (memnode_worklist.length() == 0)
    return;  // nothing to do
  while (memnode_worklist.length() != 0) {
    Node *n = memnode_worklist.pop();
    if (visited.test_set(n->_idx))
      continue;
    if (n->is_Phi() || n->is_ClearArray()) {
      // we don't need to do anything, but the users must be pushed
    } else if (n->is_MemBar()) { // Initialize, MemBar nodes
      // we don't need to do anything, but the users must be pushed
      n = n->as_MemBar()->proj_out(TypeFunc::Memory);
      if (n == NULL)
        continue;
    } else if (n->Opcode() == Op_EncodeISOArray) {
      // get the memory projection
      for (DUIterator_Fast imax, i = n->fast_outs(imax); i < imax; i++) {
        Node *use = n->fast_out(i);
        if (use->Opcode() == Op_SCMemProj) {
          n = use;
          break;
        }
      }
      assert(n->Opcode() == Op_SCMemProj, "memory projection required");
    } else {
      assert(n->is_Mem(), "memory node required.");
      Node *addr = n->in(MemNode::Address);
      const Type *addr_t = igvn->type(addr);
      if (addr_t == Type::TOP)
        continue;
      assert (addr_t->isa_ptr() != NULL, "pointer type required.");
      int alias_idx = _compile->get_alias_index(addr_t->is_ptr());
      assert ((uint)alias_idx < new_index_end, "wrong alias index");
      Node *mem = find_inst_mem(n->in(MemNode::Memory), alias_idx, orig_phis);
      if (_compile->failing()) {
        return;
      }
      if (mem != n->in(MemNode::Memory)) {
        // We delay the memory edge update since we need old one in
        // MergeMem code below when instances memory slices are separated.
        set_map(n, mem);
      }
      if (n->is_Load()) {
        continue;  // don't push users
      } else if (n->is_LoadStore()) {
        // get the memory projection
        for (DUIterator_Fast imax, i = n->fast_outs(imax); i < imax; i++) {
          Node *use = n->fast_out(i);
          if (use->Opcode() == Op_SCMemProj) {
            n = use;
            break;
          }
        }
        assert(n->Opcode() == Op_SCMemProj, "memory projection required");
      }
    }
    // push user on appropriate worklist
    for (DUIterator_Fast imax, i = n->fast_outs(imax); i < imax; i++) {
      Node *use = n->fast_out(i);
      if (use->is_Phi() || use->is_ClearArray()) {
        memnode_worklist.append_if_missing(use);
      } else if (use->is_Mem() && use->in(MemNode::Memory) == n) {
        if (use->Opcode() == Op_StoreCM) // Ignore cardmark stores
          continue;
        memnode_worklist.append_if_missing(use);
      } else if (use->is_MemBar()) {
        if (use->in(TypeFunc::Memory) == n) { // Ignore precedent edge
          memnode_worklist.append_if_missing(use);
        }
#ifdef ASSERT
      } else if(use->is_Mem()) {
        assert(use->in(MemNode::Memory) != n, "EA: missing memory path");
      } else if (use->is_MergeMem()) {
        assert(_mergemem_worklist.contains(use->as_MergeMem()), "EA: missing MergeMem node in the worklist");
      } else if (use->Opcode() == Op_EncodeISOArray) {
        if (use->in(MemNode::Memory) == n || use->in(3) == n) {
          // EncodeISOArray overwrites destination array
          memnode_worklist.append_if_missing(use);
        }
      } else {
        uint op = use->Opcode();
        if (!(op == Op_StoreCM ||
              (op == Op_CallLeaf && use->as_CallLeaf()->_name != NULL &&
               strcmp(use->as_CallLeaf()->_name, "g1_wb_pre") == 0) ||
              op == Op_AryEq || op == Op_StrComp ||
              op == Op_StrEquals || op == Op_StrIndexOf)) {
          n->dump();
          use->dump();
          assert(false, "EA: missing memory path");
        }
#endif
      }
    }
  }

  //  Phase 3:  Process MergeMem nodes from mergemem_worklist.
  //            Walk each memory slice moving the first node encountered of each
  //            instance type to the the input corresponding to its alias index.
  uint length = _mergemem_worklist.length();
  for( uint next = 0; next < length; ++next ) {
    MergeMemNode* nmm = _mergemem_worklist.at(next);
    assert(!visited.test_set(nmm->_idx), "should not be visited before");
    // Note: we don't want to use MergeMemStream here because we only want to
    // scan inputs which exist at the start, not ones we add during processing.
    // Note 2: MergeMem may already contains instance memory slices added
    // during find_inst_mem() call when memory nodes were processed above.
    igvn->hash_delete(nmm);
    uint nslices = MIN2(nmm->req(), new_index_start);
    for (uint i = Compile::AliasIdxRaw+1; i < nslices; i++) {
      Node* mem = nmm->in(i);
      Node* cur = NULL;
      if (mem == NULL || mem->is_top())
        continue;
      // First, update mergemem by moving memory nodes to corresponding slices
      // if their type became more precise since this mergemem was created.
      while (mem->is_Mem()) {
        const Type *at = igvn->type(mem->in(MemNode::Address));
        if (at != Type::TOP) {
          assert (at->isa_ptr() != NULL, "pointer type required.");
          uint idx = (uint)_compile->get_alias_index(at->is_ptr());
          if (idx == i) {
            if (cur == NULL)
              cur = mem;
          } else {
            if (idx >= nmm->req() || nmm->is_empty_memory(nmm->in(idx))) {
              nmm->set_memory_at(idx, mem);
            }
          }
        }
        mem = mem->in(MemNode::Memory);
      }
      nmm->set_memory_at(i, (cur != NULL) ? cur : mem);
      // Find any instance of the current type if we haven't encountered
      // already a memory slice of the instance along the memory chain.
      for (uint ni = new_index_start; ni < new_index_end; ni++) {
        if((uint)_compile->get_general_index(ni) == i) {
          Node *m = (ni >= nmm->req()) ? nmm->empty_memory() : nmm->in(ni);
          if (nmm->is_empty_memory(m)) {
            Node* result = find_inst_mem(mem, ni, orig_phis);
            if (_compile->failing()) {
              return;
            }
            nmm->set_memory_at(ni, result);
          }
        }
      }
    }
    // Find the rest of instances values
    for (uint ni = new_index_start; ni < new_index_end; ni++) {
      const TypeOopPtr *tinst = _compile->get_adr_type(ni)->isa_oopptr();
      Node* result = step_through_mergemem(nmm, ni, tinst);
      if (result == nmm->base_memory()) {
        // Didn't find instance memory, search through general slice recursively.
        result = nmm->memory_at(_compile->get_general_index(ni));
        result = find_inst_mem(result, ni, orig_phis);
        if (_compile->failing()) {
          return;
        }
        nmm->set_memory_at(ni, result);
      }
    }
    igvn->hash_insert(nmm);
    record_for_optimizer(nmm);
  }

  //  Phase 4:  Update the inputs of non-instance memory Phis and
  //            the Memory input of memnodes
  // First update the inputs of any non-instance Phi's from
  // which we split out an instance Phi.  Note we don't have
  // to recursively process Phi's encounted on the input memory
  // chains as is done in split_memory_phi() since they  will
  // also be processed here.
  for (int j = 0; j < orig_phis.length(); j++) {
    PhiNode *phi = orig_phis.at(j);
    int alias_idx = _compile->get_alias_index(phi->adr_type());
    igvn->hash_delete(phi);
    for (uint i = 1; i < phi->req(); i++) {
      Node *mem = phi->in(i);
      Node *new_mem = find_inst_mem(mem, alias_idx, orig_phis);
      if (_compile->failing()) {
        return;
      }
      if (mem != new_mem) {
        phi->set_req(i, new_mem);
      }
    }
    igvn->hash_insert(phi);
    record_for_optimizer(phi);
  }

  // Update the memory inputs of MemNodes with the value we computed
  // in Phase 2 and move stores memory users to corresponding memory slices.
  // Disable memory split verification code until the fix for 6984348.
  // Currently it produces false negative results since it does not cover all cases.
#if 0 // ifdef ASSERT
  visited.Reset();
  Node_Stack old_mems(arena, _compile->unique() >> 2);
#endif
  for (uint i = 0; i < ideal_nodes.size(); i++) {
    Node*    n = ideal_nodes.at(i);
    Node* nmem = get_map(n->_idx);
    assert(nmem != NULL, "sanity");
    if (n->is_Mem()) {
#if 0 // ifdef ASSERT
      Node* old_mem = n->in(MemNode::Memory);
      if (!visited.test_set(old_mem->_idx)) {
        old_mems.push(old_mem, old_mem->outcnt());
      }
#endif
      assert(n->in(MemNode::Memory) != nmem, "sanity");
      if (!n->is_Load()) {
        // Move memory users of a store first.
        move_inst_mem(n, orig_phis);
      }
      // Now update memory input
      igvn->hash_delete(n);
      n->set_req(MemNode::Memory, nmem);
      igvn->hash_insert(n);
      record_for_optimizer(n);
    } else {
      assert(n->is_Allocate() || n->is_CheckCastPP() ||
             n->is_AddP() || n->is_Phi(), "unknown node used for set_map()");
    }
  }
#if 0 // ifdef ASSERT
  // Verify that memory was split correctly
  while (old_mems.is_nonempty()) {
    Node* old_mem = old_mems.node();
    uint  old_cnt = old_mems.index();
    old_mems.pop();
    assert(old_cnt == old_mem->outcnt(), "old mem could be lost");
  }
#endif
}

#ifndef PRODUCT
static const char *node_type_names[] = {
  "UnknownType",
  "JavaObject",
  "LocalVar",
  "Field",
  "Arraycopy"
};

static const char *esc_names[] = {
  "UnknownEscape",
  "NoEscape",
  "ArgEscape",
  "GlobalEscape"
};

void PointsToNode::dump(bool print_state) const {
  NodeType nt = node_type();
  tty->print("%s ", node_type_names[(int) nt]);
  if (print_state) {
    EscapeState es = escape_state();
    EscapeState fields_es = fields_escape_state();
    tty->print("%s(%s) ", esc_names[(int)es], esc_names[(int)fields_es]);
    if (nt == PointsToNode::JavaObject && !this->scalar_replaceable())
      tty->print("NSR ");
  }
  if (is_Field()) {
    FieldNode* f = (FieldNode*)this;
    if (f->is_oop())
      tty->print("oop ");
    if (f->offset() > 0)
      tty->print("+%d ", f->offset());
    tty->print("(");
    for (BaseIterator i(f); i.has_next(); i.next()) {
      PointsToNode* b = i.get();
      tty->print(" %d%s", b->idx(),(b->is_JavaObject() ? "P" : ""));
    }
    tty->print(" )");
  }
  tty->print("[");
  for (EdgeIterator i(this); i.has_next(); i.next()) {
    PointsToNode* e = i.get();
    tty->print(" %d%s%s", e->idx(),(e->is_JavaObject() ? "P" : (e->is_Field() ? "F" : "")), e->is_Arraycopy() ? "cp" : "");
  }
  tty->print(" [");
  for (UseIterator i(this); i.has_next(); i.next()) {
    PointsToNode* u = i.get();
    bool is_base = false;
    if (PointsToNode::is_base_use(u)) {
      is_base = true;
      u = PointsToNode::get_use_node(u)->as_Field();
    }
    tty->print(" %d%s%s", u->idx(), is_base ? "b" : "", u->is_Arraycopy() ? "cp" : "");
  }
  tty->print(" ]]  ");
  if (_node == NULL)
    tty->print_cr("<null>");
  else
    _node->dump();
}

void ConnectionGraph::dump(GrowableArray<PointsToNode*>& ptnodes_worklist) {
  bool first = true;
  int ptnodes_length = ptnodes_worklist.length();
  for (int i = 0; i < ptnodes_length; i++) {
    PointsToNode *ptn = ptnodes_worklist.at(i);
    if (ptn == NULL || !ptn->is_JavaObject())
      continue;
    PointsToNode::EscapeState es = ptn->escape_state();
    if ((es != PointsToNode::NoEscape) && !Verbose) {
      continue;
    }
    Node* n = ptn->ideal_node();
    if (n->is_Allocate() || (n->is_CallStaticJava() &&
                             n->as_CallStaticJava()->is_boxing_method())) {
      if (first) {
        tty->cr();
        tty->print("======== Connection graph for ");
        _compile->method()->print_short_name();
        tty->cr();
        first = false;
      }
      ptn->dump();
      // Print all locals and fields which reference this allocation
      for (UseIterator j(ptn); j.has_next(); j.next()) {
        PointsToNode* use = j.get();
        if (use->is_LocalVar()) {
          use->dump(Verbose);
        } else if (Verbose) {
          use->dump();
        }
      }
      tty->cr();
    }
  }
}
#endif
