diff a/src/hotspot/share/opto/parse.hpp b/src/hotspot/share/opto/parse.hpp
--- a/src/hotspot/share/opto/parse.hpp
+++ b/src/hotspot/share/opto/parse.hpp
@@ -29,10 +29,11 @@
 #include "ci/ciTypeFlow.hpp"
 #include "compiler/methodLiveness.hpp"
 #include "libadt/vectset.hpp"
 #include "oops/generateOopMap.hpp"
 #include "opto/graphKit.hpp"
+#include "opto/partialEscape.hpp"
 #include "opto/subnode.hpp"
 
 class BytecodeParseHistogram;
 class InlineTree;
 class Parse;
@@ -159,17 +160,27 @@
     uint               _count;          // how many times executed?  Currently only set by _goto's
     bool               _is_parsed;      // has this block been parsed yet?
     bool               _is_handler;     // is this block an exception handler?
     bool               _has_merged_backedge; // does this block have merged backedge?
     SafePointNode*     _start_map;      // all values flowing into this block
-    MethodLivenessResult _live_locals;  // lazily initialized liveness bitmap
+    mutable MethodLivenessResult _live_locals;  // lazily initialized liveness bitmap
     bool               _has_predicates; // Were predicates added before parsing of the loop head?
 
     int                _num_successors; // Includes only normal control flow.
     int                _all_successors; // Include exception paths also.
     Block**            _successors;
+    Block**            _predecessors;
+    Block*             _from_block;
+    int                _init_pnum;      // the pnum of Block where _state is copied from.
 
+    const MethodLivenessResult& liveness() const {
+      if (!_live_locals.is_valid()) {
+        _live_locals = flow()->outer()->method()->liveness_at_bci(start());
+      }
+      assert(_live_locals.is_valid(), "sanity check");
+      return _live_locals;
+    }
    public:
 
     // Set up the block data structure itself.
     Block(Parse* outer, int rpo);
 
@@ -187,10 +198,16 @@
     SafePointNode* start_map() const       { assert(is_merged(),"");   return _start_map; }
     void set_start_map(SafePointNode* m)   { assert(!is_merged(), ""); _start_map = m; }
 
     // True after any predecessor flows control into this block
     bool is_merged() const                 { return _start_map != nullptr; }
+    Block* from_block() const              { return _from_block; }
+    int init_pnum() const                  { return _init_pnum; }
+    PEAState& state()                      {
+      assert(is_merged(), "sanity check");
+      return _start_map->jvms()->alloc_state();
+    }
 
 #ifdef ASSERT
     // True after backedge predecessor flows control into this block
     bool has_merged_backedge() const       { return _has_merged_backedge; }
     void mark_merged_backedge(Block* pred) {
@@ -214,10 +231,16 @@
       assert((uint)i < (uint)all_successors(), "");
       return _successors[i];
     }
     Block* successor_for_bci(int bci);
 
+    Block* predecessor_at(int i) const {
+      assert(DoPartialEscapeAnalysis, "_predecessors is only available when DoPartialEscapeAnalysis is ON");
+      assert(i < _pred_count, "");
+      return _predecessors[i];
+    }
+
     int start() const                      { return flow()->start(); }
     int limit() const                      { return flow()->limit(); }
     int rpo() const                        { return flow()->rpo(); }
     int start_sp() const                   { return flow()->stack_size(); }
 
@@ -284,11 +307,11 @@
     // and all its phi nodes (if any).  The value returned is a
     // path number ("pnum").
     int add_new_path();
 
     // Initialize me by recording the parser's map.  My own map must be null.
-    void record_state(Parse* outer);
+    void record_state(Parse* outer, int pnum);
   };
 
 #ifndef PRODUCT
   // BytecodeParseHistogram collects number of bytecodes parsed, nodes constructed, and transformations.
   class BytecodeParseHistogram : public ArenaObj {
@@ -341,10 +364,11 @@
   friend class Block;
 
   // Variables which characterize this compilation as a whole:
 
   JVMState*     _caller;        // JVMS which carries incoming args & state.
+  PEAState*     _caller_state;  // current PEA state of caller
   float         _expected_uses; // expected number of calls to this code
   float         _prof_factor;   // discount applied to my profile counts
   int           _depth;         // Inline tree depth, for debug printouts
   const TypeFunc*_tf;           // My kind of function type
   int           _entry_bci;     // the osr bci or InvocationEntryBci
@@ -370,18 +394,21 @@
 #ifndef PRODUCT
   int _max_switch_depth;        // Debugging SwitchRanges.
   int _est_switch_depth;        // Debugging SwitchRanges.
 #endif
 
-  bool         _first_return;                  // true if return is the first to be parsed
+  int          _first_return;                  // true if return is the first to be parsed
   bool         _replaced_nodes_for_exceptions; // needs processing of replaced nodes in exception paths?
   uint         _new_idx;                       // any node with _idx above were new during this parsing. Used to trim the replaced nodes list.
 
  public:
   // Constructor
-  Parse(JVMState* caller, ciMethod* parse_method, float expected_uses);
+  Parse(JVMState* caller, ciMethod* parse_method, float expected_uses, PEAState* caller_state = nullptr);
 
+#ifndef PRODUCT
+  ~Parse();
+#endif
   virtual Parse* is_Parse() const { return (Parse*)this; }
 
   // Accessors.
   JVMState*     caller()        const { return _caller; }
   float         expected_uses() const { return _expected_uses; }
@@ -403,12 +430,18 @@
   void      set_wrote_stable(bool z)  { _wrote_stable = z; }
   bool         wrote_fields() const   { return _wrote_fields; }
   void     set_wrote_fields(bool z)   { _wrote_fields = z; }
   Node*    alloc_with_final() const   { return _alloc_with_final; }
   void set_alloc_with_final(Node* n)  {
-    assert((_alloc_with_final == nullptr) || (_alloc_with_final == n), "different init objects?");
-    _alloc_with_final = n;
+    if (DoPartialEscapeAnalysis) {
+      assert((_alloc_with_final == nullptr) || (_alloc_with_final == PEA()->is_alias(n)), 
+             "different init objects?");
+      _alloc_with_final = PEA()->is_alias(n);
+    } else {
+      assert((_alloc_with_final == nullptr) || (_alloc_with_final == n), "different init objects?");
+      _alloc_with_final = n;
+    }
   }
 
   Block*             block()    const { return _block; }
   ciBytecodeStream&  iter()           { return _iter; }
   Bytecodes::Code    bc()       const { return _iter.cur_bc(); }
@@ -450,11 +483,11 @@
   void  load_interpreter_state(Node* osr_buf);
 
   // Functions for managing basic blocks:
   void init_blocks();
   void load_state_from(Block* b);
-  void store_state_to(Block* b) { b->record_state(this); }
+  void store_state_to(Block* b, int pnum) { b->record_state(this, pnum); }
 
   // Parse all the basic blocks.
   void do_all_blocks();
 
   // Parse the current basic block
@@ -482,10 +515,11 @@
   // Helper: Merge the current mapping into the given basic block
   void merge_common(Block* target, int pnum);
   // Helper functions for merging individual cells.
   PhiNode *ensure_phi(       int idx, bool nocreate = false);
   PhiNode *ensure_memory_phi(int idx, bool nocreate = false);
+
   // Helper to merge the current memory state into the given basic block
   void merge_memory_edges(MergeMemNode* n, int pnum, bool nophi);
 
   // Parse this bytecode, and alter the Parsers JVM->Node mapping
   void do_one_bytecode();
