/*
 * Copyright (c) 2002, 2025, 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 "code/vmreg.inline.hpp"
#include "compiler/oopMap.hpp"
#include "memory/resourceArea.hpp"
#include "opto/addnode.hpp"
#include "opto/callnode.hpp"
#include "opto/compile.hpp"
#include "opto/machnode.hpp"
#include "opto/matcher.hpp"
#include "opto/output.hpp"
#include "opto/phase.hpp"
#include "opto/regalloc.hpp"
#include "opto/rootnode.hpp"
#include "utilities/align.hpp"

// The functions in this file builds OopMaps after all scheduling is done.
//
// OopMaps contain a list of all registers and stack-slots containing oops (so
// they can be updated by GC).  OopMaps also contain a list of derived-pointer
// base-pointer pairs.  When the base is moved, the derived pointer moves to
// follow it.  Finally, any registers holding callee-save values are also
// recorded.  These might contain oops, but only the caller knows.
//
// BuildOopMaps implements a simple forward reaching-defs solution.  At each
// GC point we'll have the reaching-def Nodes.  If the reaching Nodes are
// typed as pointers (no offset), then they are oops.  Pointers+offsets are
// derived pointers, and bases can be found from them.  Finally, we'll also
// track reaching callee-save values.  Note that a copy of a callee-save value
// "kills" it's source, so that only 1 copy of a callee-save value is alive at
// a time.
//
// We run a simple bitvector liveness pass to help trim out dead oops.  Due to
// irreducible loops, we can have a reaching def of an oop that only reaches
// along one path and no way to know if it's valid or not on the other path.
// The bitvectors are quite dense and the liveness pass is fast.
//
// At GC points, we consult this information to build OopMaps.  All reaching
// defs typed as oops are added to the OopMap.  Only 1 instance of a
// callee-save register can be recorded.  For derived pointers, we'll have to
// find and record the register holding the base.
//
// The reaching def's is a simple 1-pass worklist approach.  I tried a clever
// breadth-first approach but it was worse (showed O(n^2) in the
// pick-next-block code).
//
// The relevant data is kept in a struct of arrays (it could just as well be
// an array of structs, but the struct-of-arrays is generally a little more
// efficient).  The arrays are indexed by register number (including
// stack-slots as registers) and so is bounded by 200 to 300 elements in
// practice.  One array will map to a reaching def Node (or null for
// conflict/dead).  The other array will map to a callee-saved register or
// OptoReg::Bad for not-callee-saved.


// Structure to pass around
struct OopFlow : public ArenaObj {
  short *_callees;              // Array mapping register to callee-saved
  Node **_defs;                 // array mapping register to reaching def
                                // or null if dead/conflict
  // OopFlow structs, when not being actively modified, describe the _end_ of
  // this block.
  Block *_b;                    // Block for this struct
  OopFlow *_next;               // Next free OopFlow
                                // or null if dead/conflict
  Compile* C;

  OopFlow( short *callees, Node **defs, Compile* c ) : _callees(callees), _defs(defs),
    _b(nullptr), _next(nullptr), C(c) { }

  // Given reaching-defs for this block start, compute it for this block end
  void compute_reach( PhaseRegAlloc *regalloc, int max_reg, Dict *safehash );

  // Merge these two OopFlows into the 'this' pointer.
  void merge( OopFlow *flow, int max_reg );

  // Copy a 'flow' over an existing flow
  void clone( OopFlow *flow, int max_size);

  // Make a new OopFlow from scratch
  static OopFlow *make( Arena *A, int max_size, Compile* C );

  // Build an oopmap from the current flow info
  OopMap *build_oop_map( Node *n, int max_reg, PhaseRegAlloc *regalloc, int* live );
};

// Given reaching-defs for this block start, compute it for this block end
void OopFlow::compute_reach( PhaseRegAlloc *regalloc, int max_reg, Dict *safehash ) {

  for( uint i=0; i<_b->number_of_nodes(); i++ ) {
    Node *n = _b->get_node(i);

    if( n->jvms() ) {           // Build an OopMap here?
      JVMState *jvms = n->jvms();
      // no map needed for leaf calls
      if( n->is_MachSafePoint() && !n->is_MachCallLeaf() ) {
        int *live = (int*) (*safehash)[n];
        assert( live, "must find live" );
        n->as_MachSafePoint()->set_oop_map( build_oop_map(n,max_reg,regalloc, live) );
      }
    }

    // Assign new reaching def's.
    // Note that I padded the _defs and _callees arrays so it's legal
    // to index at _defs[OptoReg::Bad].
    OptoReg::Name first = regalloc->get_reg_first(n);
    OptoReg::Name second = regalloc->get_reg_second(n);
    _defs[first] = n;
    _defs[second] = n;

    // Pass callee-save info around copies
    int idx = n->is_Copy();
    if( idx ) {                 // Copies move callee-save info
      OptoReg::Name old_first = regalloc->get_reg_first(n->in(idx));
      OptoReg::Name old_second = regalloc->get_reg_second(n->in(idx));
      int tmp_first = _callees[old_first];
      int tmp_second = _callees[old_second];
      _callees[old_first] = OptoReg::Bad; // callee-save is moved, dead in old location
      _callees[old_second] = OptoReg::Bad;
      _callees[first] = tmp_first;
      _callees[second] = tmp_second;
    } else if( n->is_Phi() ) {  // Phis do not mod callee-saves
      assert( _callees[first] == _callees[regalloc->get_reg_first(n->in(1))], "" );
      assert( _callees[second] == _callees[regalloc->get_reg_second(n->in(1))], "" );
      assert( _callees[first] == _callees[regalloc->get_reg_first(n->in(n->req()-1))], "" );
      assert( _callees[second] == _callees[regalloc->get_reg_second(n->in(n->req()-1))], "" );
    } else {
      _callees[first] = OptoReg::Bad; // No longer holding a callee-save value
      _callees[second] = OptoReg::Bad;

      // Find base case for callee saves
      if( n->is_Proj() && n->in(0)->is_Start() ) {
        if( OptoReg::is_reg(first) &&
            regalloc->_matcher.is_save_on_entry(first) )
          _callees[first] = first;
        if( OptoReg::is_reg(second) &&
            regalloc->_matcher.is_save_on_entry(second) )
          _callees[second] = second;
      }
    }
  }
}

// Merge the given flow into the 'this' flow
void OopFlow::merge( OopFlow *flow, int max_reg ) {
  assert( _b == nullptr, "merging into a happy flow" );
  assert( flow->_b, "this flow is still alive" );
  assert( flow != this, "no self flow" );

  // Do the merge.  If there are any differences, drop to 'bottom' which
  // is OptoReg::Bad or null depending.
  for( int i=0; i<max_reg; i++ ) {
    // Merge the callee-save's
    if( _callees[i] != flow->_callees[i] )
      _callees[i] = OptoReg::Bad;
    // Merge the reaching defs
    if( _defs[i] != flow->_defs[i] )
      _defs[i] = nullptr;
  }

}

void OopFlow::clone( OopFlow *flow, int max_size ) {
  _b = flow->_b;
  memcpy( _callees, flow->_callees, sizeof(short)*max_size);
  memcpy( _defs   , flow->_defs   , sizeof(Node*)*max_size);
}

OopFlow *OopFlow::make( Arena *A, int max_size, Compile* C ) {
  short *callees = NEW_ARENA_ARRAY(A,short,max_size+1);
  Node **defs    = NEW_ARENA_ARRAY(A,Node*,max_size+1);
  DEBUG_ONLY( memset(defs,0,(max_size+1)*sizeof(Node*)) );
  OopFlow *flow = new (A) OopFlow(callees+1, defs+1, C);
  assert( &flow->_callees[OptoReg::Bad] == callees, "Ok to index at OptoReg::Bad" );
  assert( &flow->_defs   [OptoReg::Bad] == defs   , "Ok to index at OptoReg::Bad" );
  return flow;
}

static int get_live_bit( int *live, int reg ) {
  return live[reg>>LogBitsPerInt] &   (1<<(reg&(BitsPerInt-1))); }
static void set_live_bit( int *live, int reg ) {
         live[reg>>LogBitsPerInt] |=  (1<<(reg&(BitsPerInt-1))); }
static void clr_live_bit( int *live, int reg ) {
         live[reg>>LogBitsPerInt] &= ~(1<<(reg&(BitsPerInt-1))); }

// Build an oopmap from the current flow info
OopMap *OopFlow::build_oop_map( Node *n, int max_reg, PhaseRegAlloc *regalloc, int* live ) {
  int framesize = regalloc->_framesize;
  int max_inarg_slot = OptoReg::reg2stack(regalloc->_matcher._new_SP);
  DEBUG_ONLY( char *dup_check = NEW_RESOURCE_ARRAY(char,OptoReg::stack0());
              memset(dup_check,0,OptoReg::stack0()) );

  OopMap *omap = new OopMap( framesize,  max_inarg_slot );
  MachCallNode *mcall = n->is_MachCall() ? n->as_MachCall() : nullptr;
  JVMState* jvms = n->jvms();

  // For all registers do...
  for( int reg=0; reg<max_reg; reg++ ) {
    if( get_live_bit(live,reg) == 0 )
      continue;                 // Ignore if not live

    // %%% C2 can use 2 OptoRegs when the physical register is only one 64bit
    // register in that case we'll get an non-concrete register for the second
    // half. We only need to tell the map the register once!
    //
    // However for the moment we disable this change and leave things as they
    // were.

    VMReg r = OptoReg::as_VMReg(OptoReg::Name(reg), framesize, max_inarg_slot);

    // See if dead (no reaching def).
    Node *def = _defs[reg];     // Get reaching def
    assert( def, "since live better have reaching def" );

    if (def->is_MachTemp()) {
      assert(!def->bottom_type()->isa_oop_ptr(),
             "ADLC only assigns OOP types to MachTemp defs corresponding to xRegN operands");
      // Exclude MachTemp definitions even if they are typed as oops.
      continue;
    }

    // Classify the reaching def as oop, derived, callee-save, dead, or other
    const Type *t = def->bottom_type();
    if( t->isa_oop_ptr() ) {    // Oop or derived?
      assert( !OptoReg::is_valid(_callees[reg]), "oop can't be callee save" );
#ifdef _LP64
      // 64-bit pointers record oop-ishness on 2 aligned adjacent registers.
      // Make sure both are record from the same reaching def, but do not
      // put both into the oopmap.
      if( (reg&1) == 1 ) {      // High half of oop-pair?
        assert( _defs[reg-1] == _defs[reg], "both halves from same reaching def" );
        continue;               // Do not record high parts in oopmap
      }
#endif

      // Check for a legal reg name in the oopMap and bailout if it is not.
      if (!omap->legal_vm_reg_name(r)) {
        stringStream ss;
        ss.print("illegal oopMap register name: ");
        r->print_on(&ss);
        assert(false, "%s", ss.as_string());
        regalloc->C->record_method_not_compilable(ss.as_string());
        continue;
      }
      if( t->is_ptr()->_offset == 0 ) { // Not derived?
        if( mcall ) {
          // Outgoing argument GC mask responsibility belongs to the callee,
          // not the caller.  Inspect the inputs to the call, to see if
          // this live-range is one of them.
          uint cnt = mcall->tf()->domain()->cnt();
          uint j;
          for( j = TypeFunc::Parms; j < cnt; j++)
            if( mcall->in(j) == def )
              break;            // reaching def is an argument oop
          if( j < cnt )         // arg oops dont go in GC map
            continue;           // Continue on to the next register
        }
        omap->set_oop(r);
      } else {                  // Else it's derived.
        // Find the base of the derived value.
        uint i;
        // Fast, common case, scan
        for( i = jvms->oopoff(); i < n->req(); i+=2 )
          if( n->in(i) == def ) break; // Common case
        if( i == n->req() ) {   // Missed, try a more generous scan
          // Scan again, but this time peek through copies
          for( i = jvms->oopoff(); i < n->req(); i+=2 ) {
            Node *m = n->in(i); // Get initial derived value
            while( 1 ) {
              Node *d = def;    // Get initial reaching def
              while( 1 ) {      // Follow copies of reaching def to end
                if( m == d ) goto found; // breaks 3 loops
                int idx = d->is_Copy();
                if( !idx ) break;
                d = d->in(idx);     // Link through copy
              }
              int idx = m->is_Copy();
              if( !idx ) break;
              m = m->in(idx);
            }
          }
          guarantee( 0, "must find derived/base pair" );
        }
      found: ;
        Node *base = n->in(i+1); // Base is other half of pair
        int breg = regalloc->get_reg_first(base);
        VMReg b = OptoReg::as_VMReg(OptoReg::Name(breg), framesize, max_inarg_slot);

        // I record liveness at safepoints BEFORE I make the inputs
        // live.  This is because argument oops are NOT live at a
        // safepoint (or at least they cannot appear in the oopmap).
        // Thus bases of base/derived pairs might not be in the
        // liveness data but they need to appear in the oopmap.
        if( get_live_bit(live,breg) == 0 ) {// Not live?
          // Flag it, so next derived pointer won't re-insert into oopmap
          set_live_bit(live,breg);
          // Already missed our turn?
          if( breg < reg ) {
            omap->set_oop(b);
          }
        }
        omap->set_derived_oop(r, b);
      }

    } else if( t->isa_narrowoop() ) {
      assert( !OptoReg::is_valid(_callees[reg]), "oop can't be callee save" );
      // Check for a legal reg name in the oopMap and bailout if it is not.
      if (!omap->legal_vm_reg_name(r)) {
        stringStream ss;
        ss.print("illegal oopMap register name: ");
        r->print_on(&ss);
        assert(false, "%s", ss.as_string());
        regalloc->C->record_method_not_compilable(ss.as_string());
        continue;
      }
      if( mcall ) {
          // Outgoing argument GC mask responsibility belongs to the callee,
          // not the caller.  Inspect the inputs to the call, to see if
          // this live-range is one of them.
        uint cnt = mcall->tf()->domain()->cnt();
        uint j;
        for( j = TypeFunc::Parms; j < cnt; j++)
          if( mcall->in(j) == def )
            break;            // reaching def is an argument oop
        if( j < cnt )         // arg oops dont go in GC map
          continue;           // Continue on to the next register
      }
      omap->set_narrowoop(r);
    } else if( OptoReg::is_valid(_callees[reg])) { // callee-save?
      // It's a callee-save value
      assert( dup_check[_callees[reg]]==0, "trying to callee save same reg twice" );
      DEBUG_ONLY( dup_check[_callees[reg]]=1; )
      VMReg callee = OptoReg::as_VMReg(OptoReg::Name(_callees[reg]));
      omap->set_callee_saved(r, callee);

    } else {
      // Other - some reaching non-oop value
#ifdef ASSERT
      if (t->isa_rawptr()) {
        ResourceMark rm;
        Unique_Node_List worklist;
        worklist.push(def);
        for (uint i = 0; i < worklist.size(); i++) {
          Node* m = worklist.at(i);
          if (C->cfg()->_raw_oops.member(m)) {
            def->dump();
            m->dump();
            n->dump();
            assert(false, "there should be an oop in OopMap instead of a live raw oop at safepoint");
          }
          // Check users as well because def might be spilled
          for (DUIterator_Fast jmax, j = m->fast_outs(jmax); j < jmax; j++) {
            Node* u = m->fast_out(j);
            if ((u->is_SpillCopy() && u->in(1) == m) || u->is_Phi()) {
              worklist.push(u);
            }
          }
        }
      }
#endif
    }

  }

#ifdef ASSERT
  /* Nice, Intel-only assert
  int cnt_callee_saves=0;
  int reg2 = 0;
  while (OptoReg::is_reg(reg2)) {
    if( dup_check[reg2] != 0) cnt_callee_saves++;
    assert( cnt_callee_saves==3 || cnt_callee_saves==5, "missed some callee-save" );
    reg2++;
  }
  */
#endif

#ifdef ASSERT
  bool has_derived_oops = false;
  for( OopMapStream oms1(omap); !oms1.is_done(); oms1.next()) {
    OopMapValue omv1 = oms1.current();
    if (omv1.type() != OopMapValue::derived_oop_value) {
      continue;
    }
    has_derived_oops = true;
    bool found = false;
    for( OopMapStream oms2(omap); !oms2.is_done(); oms2.next()) {
      OopMapValue omv2 = oms2.current();
      if (omv2.type() != OopMapValue::oop_value) {
        continue;
      }
      if( omv1.content_reg() == omv2.reg() ) {
        found = true;
        break;
      }
    }
    assert(has_derived_oops == omap->has_derived_oops(), "");
    assert( found, "derived with no base in oopmap" );
  }

  int num_oops = 0;
  for (OopMapStream oms2(omap); !oms2.is_done(); oms2.next()) {
    OopMapValue omv = oms2.current();
    if (omv.type() == OopMapValue::oop_value || omv.type() == OopMapValue::narrowoop_value) {
      num_oops++;
    }
  }
  assert(num_oops == omap->num_oops(), "num_oops: %d omap->num_oops(): %d", num_oops, omap->num_oops());
#endif

  return omap;
}

// Compute backwards liveness on registers
static void do_liveness(PhaseRegAlloc* regalloc, PhaseCFG* cfg, Block_List* worklist, int max_reg_ints, Arena* A, Dict* safehash) {
  int* live = NEW_ARENA_ARRAY(A, int, (cfg->number_of_blocks() + 1) * max_reg_ints);
  int* tmp_live = &live[cfg->number_of_blocks() * max_reg_ints];
  Node* root = cfg->get_root_node();
  // On CISC platforms, get the node representing the stack pointer  that regalloc
  // used for spills
  Node *fp = NodeSentinel;
  if (UseCISCSpill && root->req() > 1) {
    fp = root->in(1)->in(TypeFunc::FramePtr);
  }
  memset(live, 0, cfg->number_of_blocks() * (max_reg_ints << LogBytesPerInt));
  // Push preds onto worklist
  for (uint i = 1; i < root->req(); i++) {
    Block* block = cfg->get_block_for_node(root->in(i));
    worklist->push(block);
  }

  // ZKM.jar includes tiny infinite loops which are unreached from below.
  // If we missed any blocks, we'll retry here after pushing all missed
  // blocks on the worklist.  Normally this outer loop never trips more
  // than once.
  while (1) {

    while( worklist->size() ) { // Standard worklist algorithm
      Block *b = worklist->rpop();

      // Copy first successor into my tmp_live space
      int s0num = b->_succs[0]->_pre_order;
      int *t = &live[s0num*max_reg_ints];
      for( int i=0; i<max_reg_ints; i++ )
        tmp_live[i] = t[i];

      // OR in the remaining live registers
      for( uint j=1; j<b->_num_succs; j++ ) {
        uint sjnum = b->_succs[j]->_pre_order;
        int *t = &live[sjnum*max_reg_ints];
        for( int i=0; i<max_reg_ints; i++ )
          tmp_live[i] |= t[i];
      }

      // Now walk tmp_live up the block backwards, computing live
      for( int k=b->number_of_nodes()-1; k>=0; k-- ) {
        Node *n = b->get_node(k);
        // KILL def'd bits
        int first = regalloc->get_reg_first(n);
        int second = regalloc->get_reg_second(n);
        if( OptoReg::is_valid(first) ) clr_live_bit(tmp_live,first);
        if( OptoReg::is_valid(second) ) clr_live_bit(tmp_live,second);

        MachNode *m = n->is_Mach() ? n->as_Mach() : nullptr;

        // Check if m is potentially a CISC alternate instruction (i.e, possibly
        // synthesized by RegAlloc from a conventional instruction and a
        // spilled input)
        bool is_cisc_alternate = false;
        if (UseCISCSpill && m) {
          is_cisc_alternate = m->is_cisc_alternate();
        }

        // GEN use'd bits
        for( uint l=1; l<n->req(); l++ ) {
          Node *def = n->in(l);
          assert(def != nullptr, "input edge required");
          int first = regalloc->get_reg_first(def);
          int second = regalloc->get_reg_second(def);
          //If peephole had removed the node,do not set live bit for it.
          if (!(def->is_Mach() && def->as_Mach()->get_removed())) {
            if (OptoReg::is_valid(first)) set_live_bit(tmp_live,first);
            if (OptoReg::is_valid(second)) set_live_bit(tmp_live,second);
          }
          // If we use the stack pointer in a cisc-alternative instruction,
          // check for use as a memory operand.  Then reconstruct the RegName
          // for this stack location, and set the appropriate bit in the
          // live vector 4987749.
          if (is_cisc_alternate && def == fp) {
            const TypePtr *adr_type = nullptr;
            intptr_t offset;
            const Node* base = m->get_base_and_disp(offset, adr_type);
            if (base == NodeSentinel) {
              // Machnode has multiple memory inputs. We are unable to reason
              // with these, but are presuming (with trepidation) that not any of
              // them are oops. This can be fixed by making get_base_and_disp()
              // look at a specific input instead of all inputs.
              assert(!def->bottom_type()->isa_oop_ptr(), "expecting non-oop mem input");
            } else if (base != fp || offset == Type::OffsetBot) {
              // Do nothing: the fp operand is either not from a memory use
              // (base == nullptr) OR the fp is used in a non-memory context
              // (base is some other register) OR the offset is not constant,
              // so it is not a stack slot.
            } else {
              assert(offset >= 0, "unexpected negative offset");
              offset -= (offset % jintSize);  // count the whole word
              int stack_reg = regalloc->offset2reg(offset);
              if (OptoReg::is_stack(stack_reg)) {
                set_live_bit(tmp_live, stack_reg);
              } else {
                assert(false, "stack_reg not on stack?");
              }
            }
          }
        }

        if( n->jvms() ) {       // Record liveness at safepoint

          // This placement of this stanza means inputs to calls are
          // considered live at the callsite's OopMap.  Argument oops are
          // hence live, but NOT included in the oopmap.  See cutout in
          // build_oop_map.  Debug oops are live (and in OopMap).
          int *n_live = NEW_ARENA_ARRAY(A, int, max_reg_ints);
          for( int l=0; l<max_reg_ints; l++ )
            n_live[l] = tmp_live[l];
          safehash->Insert(n,n_live);
        }

      }

      // Now at block top, see if we have any changes.  If so, propagate
      // to prior blocks.
      int *old_live = &live[b->_pre_order*max_reg_ints];
      int l;
      for( l=0; l<max_reg_ints; l++ )
        if( tmp_live[l] != old_live[l] )
          break;
      if( l<max_reg_ints ) {     // Change!
        // Copy in new value
        for( l=0; l<max_reg_ints; l++ )
          old_live[l] = tmp_live[l];
        // Push preds onto worklist
        for (l = 1; l < (int)b->num_preds(); l++) {
          Block* block = cfg->get_block_for_node(b->pred(l));
          worklist->push(block);
        }
      }
    }

    // Scan for any missing safepoints.  Happens to infinite loops
    // ala ZKM.jar
    uint i;
    for (i = 1; i < cfg->number_of_blocks(); i++) {
      Block* block = cfg->get_block(i);
      uint j;
      for (j = 1; j < block->number_of_nodes(); j++) {
        if (block->get_node(j)->jvms() && (*safehash)[block->get_node(j)] == nullptr) {
           break;
        }
      }
      if (j < block->number_of_nodes()) {
        break;
      }
    }
    if (i == cfg->number_of_blocks()) {
      break;                    // Got 'em all
    }

    if (PrintOpto && Verbose) {
      tty->print_cr("retripping live calc");
    }

    // Force the issue (expensively): recheck everybody
    for (i = 1; i < cfg->number_of_blocks(); i++) {
      worklist->push(cfg->get_block(i));
    }
  }
}

// Collect GC mask info - where are all the OOPs?
void PhaseOutput::BuildOopMaps() {
  Compile::TracePhase tp(_t_buildOopMaps);
  // Can't resource-mark because I need to leave all those OopMaps around,
  // or else I need to resource-mark some arena other than the default.
  // ResourceMark rm;              // Reclaim all OopFlows when done
  int max_reg = C->regalloc()->_max_reg; // Current array extent

  Arena *A = Thread::current()->resource_area();
  Block_List worklist;          // Worklist of pending blocks

  int max_reg_ints = align_up(max_reg, BitsPerInt)>>LogBitsPerInt;
  Dict *safehash = nullptr;        // Used for assert only
  // Compute a backwards liveness per register.  Needs a bitarray of
  // #blocks x (#registers, rounded up to ints)
  safehash = new Dict(cmpkey,hashkey,A);
  do_liveness( C->regalloc(), C->cfg(), &worklist, max_reg_ints, A, safehash );
  OopFlow *free_list = nullptr;    // Free, unused

  // Array mapping blocks to completed oopflows
  OopFlow **flows = NEW_ARENA_ARRAY(A, OopFlow*, C->cfg()->number_of_blocks());
  memset( flows, 0, C->cfg()->number_of_blocks() * sizeof(OopFlow*) );


  // Do the first block 'by hand' to prime the worklist
  Block *entry = C->cfg()->get_block(1);
  OopFlow *rootflow = OopFlow::make(A,max_reg,C);
  // Initialize to 'bottom' (not 'top')
  memset( rootflow->_callees, OptoReg::Bad, max_reg*sizeof(short) );
  memset( rootflow->_defs   ,            0, max_reg*sizeof(Node*) );
  flows[entry->_pre_order] = rootflow;

  // Do the first block 'by hand' to prime the worklist
  rootflow->_b = entry;
  rootflow->compute_reach( C->regalloc(), max_reg, safehash );
  for( uint i=0; i<entry->_num_succs; i++ )
    worklist.push(entry->_succs[i]);

  // Now worklist contains blocks which have some, but perhaps not all,
  // predecessors visited.
  while( worklist.size() ) {
    // Scan for a block with all predecessors visited, or any randoms slob
    // otherwise.  All-preds-visited order allows me to recycle OopFlow
    // structures rapidly and cut down on the memory footprint.
    // Note: not all predecessors might be visited yet (must happen for
    // irreducible loops).  This is OK, since every live value must have the
    // SAME reaching def for the block, so any reaching def is OK.
    uint i;

    Block *b = worklist.pop();
    // Ignore root block
    if (b == C->cfg()->get_root_block()) {
      continue;
    }
    // Block is already done?  Happens if block has several predecessors,
    // he can get on the worklist more than once.
    if( flows[b->_pre_order] ) continue;

    // If this block has a visited predecessor AND that predecessor has this
    // last block as his only undone child, we can move the OopFlow from the
    // pred to this block.  Otherwise we have to grab a new OopFlow.
    OopFlow *flow = nullptr;       // Flag for finding optimized flow
    Block *pred = (Block*)((intptr_t)0xdeadbeef);
    // Scan this block's preds to find a done predecessor
    for (uint j = 1; j < b->num_preds(); j++) {
      Block* p = C->cfg()->get_block_for_node(b->pred(j));
      OopFlow *p_flow = flows[p->_pre_order];
      if( p_flow ) {            // Predecessor is done
        assert( p_flow->_b == p, "cross check" );
        pred = p;               // Record some predecessor
        // If all successors of p are done except for 'b', then we can carry
        // p_flow forward to 'b' without copying, otherwise we have to draw
        // from the free_list and clone data.
        uint k;
        for( k=0; k<p->_num_succs; k++ )
          if( !flows[p->_succs[k]->_pre_order] &&
              p->_succs[k] != b )
            break;

        // Either carry-forward the now-unused OopFlow for b's use
        // or draw a new one from the free list
        if( k==p->_num_succs ) {
          flow = p_flow;
          break;                // Found an ideal pred, use him
        }
      }
    }

    if( flow ) {
      // We have an OopFlow that's the last-use of a predecessor.
      // Carry it forward.
    } else {                    // Draw a new OopFlow from the freelist
      if( !free_list )
        free_list = OopFlow::make(A,max_reg,C);
      flow = free_list;
      assert( flow->_b == nullptr, "oopFlow is not free" );
      free_list = flow->_next;
      flow->_next = nullptr;

      // Copy/clone over the data
      flow->clone(flows[pred->_pre_order], max_reg);
    }

    // Mark flow for block.  Blocks can only be flowed over once,
    // because after the first time they are guarded from entering
    // this code again.
    assert( flow->_b == pred, "have some prior flow" );
    flow->_b = nullptr;

    // Now push flow forward
    flows[b->_pre_order] = flow;// Mark flow for this block
    flow->_b = b;
    flow->compute_reach( C->regalloc(), max_reg, safehash );

    // Now push children onto worklist
    for( i=0; i<b->_num_succs; i++ )
      worklist.push(b->_succs[i]);

  }
}
