/*
 * Copyright (c) 1999, 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 "c1/c1_Canonicalizer.hpp"
#include "c1/c1_CFGPrinter.hpp"
#include "c1/c1_Compilation.hpp"
#include "c1/c1_GraphBuilder.hpp"
#include "c1/c1_InstructionPrinter.hpp"
#include "ci/ciCallSite.hpp"
#include "ci/ciField.hpp"
#include "ci/ciKlass.hpp"
#include "ci/ciMemberName.hpp"
#include "ci/ciSymbols.hpp"
#include "ci/ciUtilities.inline.hpp"
#include "classfile/javaClasses.hpp"
#include "compiler/compilationPolicy.hpp"
#include "compiler/compileBroker.hpp"
#include "compiler/compilerEvent.hpp"
#include "interpreter/bytecode.hpp"
#include "jfr/jfrEvents.hpp"
#include "memory/resourceArea.hpp"
#include "runtime/sharedRuntime.hpp"
#include "utilities/checkedCast.hpp"
#include "utilities/macros.hpp"
#if INCLUDE_JFR
#include "jfr/jfr.hpp"
#endif

class BlockListBuilder {
 private:
  Compilation* _compilation;
  IRScope*     _scope;

  BlockList    _blocks;                // internal list of all blocks
  BlockList*   _bci2block;             // mapping from bci to blocks for GraphBuilder
  GrowableArray<BlockList> _bci2block_successors; // Mapping bcis to their blocks successors while we dont have a blockend

  // fields used by mark_loops
  ResourceBitMap _active;              // for iteration of control flow graph
  ResourceBitMap _visited;             // for iteration of control flow graph
  GrowableArray<ResourceBitMap> _loop_map; // caches the information if a block is contained in a loop
  int            _next_loop_index;     // next free loop number
  int            _next_block_number;   // for reverse postorder numbering of blocks
  int            _block_id_start;

  int           bit_number(int block_id) const   { return block_id - _block_id_start; }
  // accessors
  Compilation*  compilation() const              { return _compilation; }
  IRScope*      scope() const                    { return _scope; }
  ciMethod*     method() const                   { return scope()->method(); }
  XHandlers*    xhandlers() const                { return scope()->xhandlers(); }

  // unified bailout support
  void          bailout(const char* msg) const   { compilation()->bailout(msg); }
  bool          bailed_out() const               { return compilation()->bailed_out(); }

  // helper functions
  BlockBegin* make_block_at(int bci, BlockBegin* predecessor);
  void handle_exceptions(BlockBegin* current, int cur_bci);
  void handle_jsr(BlockBegin* current, int sr_bci, int next_bci);
  void store_one(BlockBegin* current, int local);
  void store_two(BlockBegin* current, int local);
  void set_entries(int osr_bci);
  void set_leaders();

  void make_loop_header(BlockBegin* block);
  void mark_loops();
  BitMap& mark_loops(BlockBegin* b, bool in_subroutine);

  // debugging
#ifndef PRODUCT
  void print();
#endif

  int number_of_successors(BlockBegin* block);
  BlockBegin* successor_at(BlockBegin* block, int i);
  void add_successor(BlockBegin* block, BlockBegin* sux);
  bool is_successor(BlockBegin* block, BlockBegin* sux);

 public:
  // creation
  BlockListBuilder(Compilation* compilation, IRScope* scope, int osr_bci);

  // accessors for GraphBuilder
  BlockList*    bci2block() const                { return _bci2block; }
};


// Implementation of BlockListBuilder

BlockListBuilder::BlockListBuilder(Compilation* compilation, IRScope* scope, int osr_bci)
 : _compilation(compilation)
 , _scope(scope)
 , _blocks(16)
 , _bci2block(new BlockList(scope->method()->code_size(), nullptr))
 , _bci2block_successors(scope->method()->code_size())
 , _active()         // size not known yet
 , _visited()        // size not known yet
 , _loop_map() // size not known yet
 , _next_loop_index(0)
 , _next_block_number(0)
 , _block_id_start(0)
{
  set_entries(osr_bci);
  set_leaders();
  CHECK_BAILOUT();

  mark_loops();
  NOT_PRODUCT(if (PrintInitialBlockList) print());

  // _bci2block still contains blocks with _end == null and > 0 sux in _bci2block_successors.

#ifndef PRODUCT
  if (PrintCFGToFile) {
    stringStream title;
    title.print("BlockListBuilder ");
    scope->method()->print_name(&title);
    CFGPrinter::print_cfg(_bci2block, title.freeze(), false, false);
  }
#endif
}


void BlockListBuilder::set_entries(int osr_bci) {
  // generate start blocks
  BlockBegin* std_entry = make_block_at(0, nullptr);
  if (scope()->caller() == nullptr) {
    std_entry->set(BlockBegin::std_entry_flag);
  }
  if (osr_bci != -1) {
    BlockBegin* osr_entry = make_block_at(osr_bci, nullptr);
    osr_entry->set(BlockBegin::osr_entry_flag);
  }

  // generate exception entry blocks
  XHandlers* list = xhandlers();
  const int n = list->length();
  for (int i = 0; i < n; i++) {
    XHandler* h = list->handler_at(i);
    BlockBegin* entry = make_block_at(h->handler_bci(), nullptr);
    entry->set(BlockBegin::exception_entry_flag);
    h->set_entry_block(entry);
  }
}


BlockBegin* BlockListBuilder::make_block_at(int cur_bci, BlockBegin* predecessor) {
  assert(method()->bci_block_start().at(cur_bci), "wrong block starts of MethodLivenessAnalyzer");

  BlockBegin* block = _bci2block->at(cur_bci);
  if (block == nullptr) {
    block = new BlockBegin(cur_bci);
    block->init_stores_to_locals(method()->max_locals());
    _bci2block->at_put(cur_bci, block);
    _bci2block_successors.at_put_grow(cur_bci, BlockList());
    _blocks.append(block);

    assert(predecessor == nullptr || predecessor->bci() < cur_bci, "targets for backward branches must already exist");
  }

  if (predecessor != nullptr) {
    if (block->is_set(BlockBegin::exception_entry_flag)) {
      BAILOUT_("Exception handler can be reached by both normal and exceptional control flow", block);
    }

    add_successor(predecessor, block);
    block->increment_total_preds();
  }

  return block;
}


inline void BlockListBuilder::store_one(BlockBegin* current, int local) {
  current->stores_to_locals().set_bit(local);
}
inline void BlockListBuilder::store_two(BlockBegin* current, int local) {
  store_one(current, local);
  store_one(current, local + 1);
}


void BlockListBuilder::handle_exceptions(BlockBegin* current, int cur_bci) {
  // Draws edges from a block to its exception handlers
  XHandlers* list = xhandlers();
  const int n = list->length();

  for (int i = 0; i < n; i++) {
    XHandler* h = list->handler_at(i);

    if (h->covers(cur_bci)) {
      BlockBegin* entry = h->entry_block();
      assert(entry != nullptr && entry == _bci2block->at(h->handler_bci()), "entry must be set");
      assert(entry->is_set(BlockBegin::exception_entry_flag), "flag must be set");

      // add each exception handler only once
      if(!is_successor(current, entry)) {
        add_successor(current, entry);
        entry->increment_total_preds();
      }

      // stop when reaching catchall
      if (h->catch_type() == 0) break;
    }
  }
}

void BlockListBuilder::handle_jsr(BlockBegin* current, int sr_bci, int next_bci) {
  if (next_bci < method()->code_size()) {
    // start a new block after jsr-bytecode and link this block into cfg
    make_block_at(next_bci, current);
  }

  // start a new block at the subroutine entry at mark it with special flag
  BlockBegin* sr_block = make_block_at(sr_bci, current);
  if (!sr_block->is_set(BlockBegin::subroutine_entry_flag)) {
    sr_block->set(BlockBegin::subroutine_entry_flag);
  }
}


void BlockListBuilder::set_leaders() {
  bool has_xhandlers = xhandlers()->has_handlers();
  BlockBegin* current = nullptr;

  // The information which bci starts a new block simplifies the analysis
  // Without it, backward branches could jump to a bci where no block was created
  // during bytecode iteration. This would require the creation of a new block at the
  // branch target and a modification of the successor lists.
  const BitMap& bci_block_start = method()->bci_block_start();

  int end_bci = method()->code_size();

  ciBytecodeStream s(method());
  while (s.next() != ciBytecodeStream::EOBC()) {
    int cur_bci = s.cur_bci();

    if (bci_block_start.at(cur_bci)) {
      current = make_block_at(cur_bci, current);
    }
    assert(current != nullptr, "must have current block");

    if (has_xhandlers && GraphBuilder::can_trap(method(), s.cur_bc())) {
      handle_exceptions(current, cur_bci);
    }

    switch (s.cur_bc()) {
      // track stores to local variables for selective creation of phi functions
      case Bytecodes::_iinc:     store_one(current, s.get_index()); break;
      case Bytecodes::_istore:   store_one(current, s.get_index()); break;
      case Bytecodes::_lstore:   store_two(current, s.get_index()); break;
      case Bytecodes::_fstore:   store_one(current, s.get_index()); break;
      case Bytecodes::_dstore:   store_two(current, s.get_index()); break;
      case Bytecodes::_astore:   store_one(current, s.get_index()); break;
      case Bytecodes::_istore_0: store_one(current, 0); break;
      case Bytecodes::_istore_1: store_one(current, 1); break;
      case Bytecodes::_istore_2: store_one(current, 2); break;
      case Bytecodes::_istore_3: store_one(current, 3); break;
      case Bytecodes::_lstore_0: store_two(current, 0); break;
      case Bytecodes::_lstore_1: store_two(current, 1); break;
      case Bytecodes::_lstore_2: store_two(current, 2); break;
      case Bytecodes::_lstore_3: store_two(current, 3); break;
      case Bytecodes::_fstore_0: store_one(current, 0); break;
      case Bytecodes::_fstore_1: store_one(current, 1); break;
      case Bytecodes::_fstore_2: store_one(current, 2); break;
      case Bytecodes::_fstore_3: store_one(current, 3); break;
      case Bytecodes::_dstore_0: store_two(current, 0); break;
      case Bytecodes::_dstore_1: store_two(current, 1); break;
      case Bytecodes::_dstore_2: store_two(current, 2); break;
      case Bytecodes::_dstore_3: store_two(current, 3); break;
      case Bytecodes::_astore_0: store_one(current, 0); break;
      case Bytecodes::_astore_1: store_one(current, 1); break;
      case Bytecodes::_astore_2: store_one(current, 2); break;
      case Bytecodes::_astore_3: store_one(current, 3); break;

      // track bytecodes that affect the control flow
      case Bytecodes::_athrow:  // fall through
      case Bytecodes::_ret:     // fall through
      case Bytecodes::_ireturn: // fall through
      case Bytecodes::_lreturn: // fall through
      case Bytecodes::_freturn: // fall through
      case Bytecodes::_dreturn: // fall through
      case Bytecodes::_areturn: // fall through
      case Bytecodes::_return:
        current = nullptr;
        break;

      case Bytecodes::_ifeq:      // fall through
      case Bytecodes::_ifne:      // fall through
      case Bytecodes::_iflt:      // fall through
      case Bytecodes::_ifge:      // fall through
      case Bytecodes::_ifgt:      // fall through
      case Bytecodes::_ifle:      // fall through
      case Bytecodes::_if_icmpeq: // fall through
      case Bytecodes::_if_icmpne: // fall through
      case Bytecodes::_if_icmplt: // fall through
      case Bytecodes::_if_icmpge: // fall through
      case Bytecodes::_if_icmpgt: // fall through
      case Bytecodes::_if_icmple: // fall through
      case Bytecodes::_if_acmpeq: // fall through
      case Bytecodes::_if_acmpne: // fall through
      case Bytecodes::_ifnull:    // fall through
      case Bytecodes::_ifnonnull:
        if (s.next_bci() < end_bci) {
          make_block_at(s.next_bci(), current);
        }
        make_block_at(s.get_dest(), current);
        current = nullptr;
        break;

      case Bytecodes::_goto:
        make_block_at(s.get_dest(), current);
        current = nullptr;
        break;

      case Bytecodes::_goto_w:
        make_block_at(s.get_far_dest(), current);
        current = nullptr;
        break;

      case Bytecodes::_jsr:
        handle_jsr(current, s.get_dest(), s.next_bci());
        current = nullptr;
        break;

      case Bytecodes::_jsr_w:
        handle_jsr(current, s.get_far_dest(), s.next_bci());
        current = nullptr;
        break;

      case Bytecodes::_tableswitch: {
        // set block for each case
        Bytecode_tableswitch sw(&s);
        int l = sw.length();
        for (int i = 0; i < l; i++) {
          make_block_at(cur_bci + sw.dest_offset_at(i), current);
        }
        make_block_at(cur_bci + sw.default_offset(), current);
        current = nullptr;
        break;
      }

      case Bytecodes::_lookupswitch: {
        // set block for each case
        Bytecode_lookupswitch sw(&s);
        int l = sw.number_of_pairs();
        for (int i = 0; i < l; i++) {
          make_block_at(cur_bci + sw.pair_at(i).offset(), current);
        }
        make_block_at(cur_bci + sw.default_offset(), current);
        current = nullptr;
        break;
      }

      default:
        break;
    }
  }
}


void BlockListBuilder::mark_loops() {
  ResourceMark rm;

  const int number_of_blocks = _blocks.length();
  _active.initialize(number_of_blocks);
  _visited.initialize(number_of_blocks);
  _loop_map = GrowableArray<ResourceBitMap>(number_of_blocks, number_of_blocks, ResourceBitMap());
  for (int i = 0; i < number_of_blocks; i++) {
    _loop_map.at(i).initialize(number_of_blocks);
  }
  _next_loop_index = 0;
  _next_block_number = _blocks.length();

  // The loop detection algorithm works as follows:
  // - We maintain the _loop_map, where for each block we have a bitmap indicating which loops contain this block.
  // - The CFG is recursively traversed (depth-first) and if we detect a loop, we assign the loop a unique number that is stored
  // in the bitmap associated with the loop header block. Until we return back through that loop header the bitmap contains
  // only a single bit corresponding to the loop number.
  // -  The bit is then propagated for all the blocks in the loop after we exit them (post-order). There could be multiple bits
  // of course in case of nested loops.
  // -  When we exit the loop header we remove that single bit and assign the real loop state for it.
  // -  Now, the tricky part here is how we detect irreducible loops. In the algorithm above the loop state bits
  // are propagated to the predecessors. If we encounter an irreducible loop (a loop with multiple heads) we would see
  // a node with some loop bit set that would then propagate back and be never cleared because we would
  // never go back through the original loop header. Therefore if there are any irreducible loops the bits in the states
  // for these loops are going to propagate back to the root.
  BlockBegin* start = _bci2block->at(0);
  _block_id_start = start->block_id();
  BitMap& loop_state = mark_loops(start, false);
  if (!loop_state.is_empty()) {
    compilation()->set_has_irreducible_loops(true);
  }
  assert(_next_block_number >= 0, "invalid block numbers");

  // Remove dangling Resource pointers before the ResourceMark goes out-of-scope.
  _active.resize(0);
  _visited.resize(0);
  _loop_map.clear();
}

void BlockListBuilder::make_loop_header(BlockBegin* block) {
  int block_id = block->block_id();
  int block_bit = bit_number(block_id);
  if (block->is_set(BlockBegin::exception_entry_flag)) {
    // exception edges may look like loops but don't mark them as such
    // since it screws up block ordering.
    return;
  }
  if (!block->is_set(BlockBegin::parser_loop_header_flag)) {
    block->set(BlockBegin::parser_loop_header_flag);

    assert(_loop_map.at(block_bit).is_empty(), "must not be set yet");
    assert(0 <= _next_loop_index && _next_loop_index < _loop_map.length(), "_next_loop_index is too large");
    _loop_map.at(block_bit).set_bit(_next_loop_index++);
  } else {
    // block already marked as loop header
    assert(_loop_map.at(block_bit).count_one_bits() == 1, "exactly one bit must be set");
  }
}

BitMap& BlockListBuilder::mark_loops(BlockBegin* block, bool in_subroutine) {
  int block_id = block->block_id();
  int block_bit = bit_number(block_id);
  if (_visited.at(block_bit)) {
    if (_active.at(block_bit)) {
      // reached block via backward branch
      make_loop_header(block);
    }
    // return cached loop information for this block
    return _loop_map.at(block_bit);
  }

  if (block->is_set(BlockBegin::subroutine_entry_flag)) {
    in_subroutine = true;
  }

  // set active and visited bits before successors are processed
  _visited.set_bit(block_bit);
  _active.set_bit(block_bit);

  ResourceMark rm;
  ResourceBitMap loop_state(_loop_map.length());
  for (int i = number_of_successors(block) - 1; i >= 0; i--) {
    BlockBegin* sux = successor_at(block, i);
    // recursively process all successors
    loop_state.set_union(mark_loops(sux, in_subroutine));
  }

  // clear active-bit after all successors are processed
  _active.clear_bit(block_bit);

  // reverse-post-order numbering of all blocks
  block->set_depth_first_number(_next_block_number);
  _next_block_number--;

  if (!loop_state.is_empty() || in_subroutine ) {
    // block is contained at least in one loop, so phi functions are necessary
    // phi functions are also necessary for all locals stored in a subroutine
    scope()->requires_phi_function().set_union(block->stores_to_locals());
  }

  if (block->is_set(BlockBegin::parser_loop_header_flag)) {
    BitMap& header_loop_state = _loop_map.at(block_bit);
    assert(header_loop_state.count_one_bits() == 1, "exactly one bit must be set");
    // remove the bit with the loop number for the state (header is outside of the loop)
    loop_state.set_difference(header_loop_state);
  }

  // cache and return loop information for this block
  _loop_map.at(block_bit).set_from(loop_state);
  return _loop_map.at(block_bit);
}

inline int BlockListBuilder::number_of_successors(BlockBegin* block)
{
  assert(_bci2block_successors.length() > block->bci(), "sux must exist");
  return _bci2block_successors.at(block->bci()).length();
}

inline BlockBegin* BlockListBuilder::successor_at(BlockBegin* block, int i)
{
  assert(_bci2block_successors.length() > block->bci(), "sux must exist");
  return _bci2block_successors.at(block->bci()).at(i);
}

inline void BlockListBuilder::add_successor(BlockBegin* block, BlockBegin* sux)
{
  assert(_bci2block_successors.length() > block->bci(), "sux must exist");
  _bci2block_successors.at(block->bci()).append(sux);
}

inline bool BlockListBuilder::is_successor(BlockBegin* block, BlockBegin* sux) {
  assert(_bci2block_successors.length() > block->bci(), "sux must exist");
  return _bci2block_successors.at(block->bci()).contains(sux);
}

#ifndef PRODUCT

static int compare_depth_first(BlockBegin** a, BlockBegin** b) {
  return (*a)->depth_first_number() - (*b)->depth_first_number();
}

void BlockListBuilder::print() {
  tty->print("----- initial block list of BlockListBuilder for method ");
  method()->print_short_name();
  tty->cr();

  // better readability if blocks are sorted in processing order
  _blocks.sort(compare_depth_first);

  for (int i = 0; i < _blocks.length(); i++) {
    BlockBegin* cur = _blocks.at(i);
    tty->print("%4d: B%-4d bci: %-4d  preds: %-4d ", cur->depth_first_number(), cur->block_id(), cur->bci(), cur->total_preds());

    tty->print(cur->is_set(BlockBegin::std_entry_flag)               ? " std" : "    ");
    tty->print(cur->is_set(BlockBegin::osr_entry_flag)               ? " osr" : "    ");
    tty->print(cur->is_set(BlockBegin::exception_entry_flag)         ? " ex" : "   ");
    tty->print(cur->is_set(BlockBegin::subroutine_entry_flag)        ? " sr" : "   ");
    tty->print(cur->is_set(BlockBegin::parser_loop_header_flag)      ? " lh" : "   ");

    if (number_of_successors(cur) > 0) {
      tty->print("    sux: ");
      for (int j = 0; j < number_of_successors(cur); j++) {
        BlockBegin* sux = successor_at(cur, j);
        tty->print("B%d ", sux->block_id());
      }
    }
    tty->cr();
  }
}

#endif


// A simple growable array of Values indexed by ciFields
class FieldBuffer: public CompilationResourceObj {
 private:
  GrowableArray<Value> _values;

 public:
  FieldBuffer() {}

  void kill() {
    _values.trunc_to(0);
  }

  Value at(ciField* field) {
    assert(field->holder()->is_loaded(), "must be a loaded field");
    int offset = field->offset_in_bytes();
    if (offset < _values.length()) {
      return _values.at(offset);
    } else {
      return nullptr;
    }
  }

  void at_put(ciField* field, Value value) {
    assert(field->holder()->is_loaded(), "must be a loaded field");
    int offset = field->offset_in_bytes();
    _values.at_put_grow(offset, value, nullptr);
  }

};


// MemoryBuffer is fairly simple model of the current state of memory.
// It partitions memory into several pieces.  The first piece is
// generic memory where little is known about the owner of the memory.
// This is conceptually represented by the tuple <O, F, V> which says
// that the field F of object O has value V.  This is flattened so
// that F is represented by the offset of the field and the parallel
// arrays _objects and _values are used for O and V.  Loads of O.F can
// simply use V.  Newly allocated objects are kept in a separate list
// along with a parallel array for each object which represents the
// current value of its fields.  Stores of the default value to fields
// which have never been stored to before are eliminated since they
// are redundant.  Once newly allocated objects are stored into
// another object or they are passed out of the current compile they
// are treated like generic memory.

class MemoryBuffer: public CompilationResourceObj {
 private:
  FieldBuffer                 _values;
  GrowableArray<Value>        _objects;
  GrowableArray<Value>        _newobjects;
  GrowableArray<FieldBuffer*> _fields;

 public:
  MemoryBuffer() {}

  StoreField* store(StoreField* st) {
    if (!EliminateFieldAccess) {
      return st;
    }

    Value object = st->obj();
    Value value = st->value();
    ciField* field = st->field();
    if (field->holder()->is_loaded()) {
      int offset = field->offset_in_bytes();
      int index = _newobjects.find(object);
      if (index != -1) {
        // newly allocated object with no other stores performed on this field
        FieldBuffer* buf = _fields.at(index);
        if (buf->at(field) == nullptr && is_default_value(value)) {
#ifndef PRODUCT
          if (PrintIRDuringConstruction && Verbose) {
            tty->print_cr("Eliminated store for object %d:", index);
            st->print_line();
          }
#endif
          return nullptr;
        } else {
          buf->at_put(field, value);
        }
      } else {
        _objects.at_put_grow(offset, object, nullptr);
        _values.at_put(field, value);
      }

      store_value(value);
    } else {
      // if we held onto field names we could alias based on names but
      // we don't know what's being stored to so kill it all.
      kill();
    }
    return st;
  }


  // return true if this value correspond to the default value of a field.
  bool is_default_value(Value value) {
    Constant* con = value->as_Constant();
    if (con) {
      switch (con->type()->tag()) {
        case intTag:    return con->type()->as_IntConstant()->value() == 0;
        case longTag:   return con->type()->as_LongConstant()->value() == 0;
        case floatTag:  return jint_cast(con->type()->as_FloatConstant()->value()) == 0;
        case doubleTag: return jlong_cast(con->type()->as_DoubleConstant()->value()) == jlong_cast(0);
        case objectTag: return con->type() == objectNull;
        default:  ShouldNotReachHere();
      }
    }
    return false;
  }


  // return either the actual value of a load or the load itself
  Value load(LoadField* load) {
    if (!EliminateFieldAccess) {
      return load;
    }

    ciField* field = load->field();
    Value object   = load->obj();
    if (field->holder()->is_loaded() && !field->is_volatile()) {
      int offset = field->offset_in_bytes();
      Value result = nullptr;
      int index = _newobjects.find(object);
      if (index != -1) {
        result = _fields.at(index)->at(field);
      } else if (_objects.at_grow(offset, nullptr) == object) {
        result = _values.at(field);
      }
      if (result != nullptr) {
#ifndef PRODUCT
        if (PrintIRDuringConstruction && Verbose) {
          tty->print_cr("Eliminated load: ");
          load->print_line();
        }
#endif
        assert(result->type()->tag() == load->type()->tag(), "wrong types");
        return result;
      }
    }
    return load;
  }

  // Record this newly allocated object
  void new_instance(NewInstance* object) {
    int index = _newobjects.length();
    _newobjects.append(object);
    if (_fields.at_grow(index, nullptr) == nullptr) {
      _fields.at_put(index, new FieldBuffer());
    } else {
      _fields.at(index)->kill();
    }
  }

  void store_value(Value value) {
    int index = _newobjects.find(value);
    if (index != -1) {
      // stored a newly allocated object into another object.
      // Assume we've lost track of it as separate slice of memory.
      // We could do better by keeping track of whether individual
      // fields could alias each other.
      _newobjects.remove_at(index);
      // pull out the field info and store it at the end up the list
      // of field info list to be reused later.
      _fields.append(_fields.at(index));
      _fields.remove_at(index);
    }
  }

  void kill() {
    _newobjects.trunc_to(0);
    _objects.trunc_to(0);
    _values.kill();
  }
};


// Implementation of GraphBuilder's ScopeData

GraphBuilder::ScopeData::ScopeData(ScopeData* parent)
  : _parent(parent)
  , _bci2block(nullptr)
  , _scope(nullptr)
  , _has_handler(false)
  , _stream(nullptr)
  , _work_list(nullptr)
  , _caller_stack_size(-1)
  , _continuation(nullptr)
  , _parsing_jsr(false)
  , _jsr_xhandlers(nullptr)
  , _num_returns(0)
  , _cleanup_block(nullptr)
  , _cleanup_return_prev(nullptr)
  , _cleanup_state(nullptr)
  , _ignore_return(false)
{
  if (parent != nullptr) {
    _max_inline_size = (intx) ((float) NestedInliningSizeRatio * (float) parent->max_inline_size() / 100.0f);
  } else {
    _max_inline_size = C1MaxInlineSize;
  }
  if (_max_inline_size < C1MaxTrivialSize) {
    _max_inline_size = C1MaxTrivialSize;
  }
}


void GraphBuilder::kill_all() {
  if (UseLocalValueNumbering) {
    vmap()->kill_all();
  }
  _memory->kill();
}


BlockBegin* GraphBuilder::ScopeData::block_at(int bci) {
  if (parsing_jsr()) {
    // It is necessary to clone all blocks associated with a
    // subroutine, including those for exception handlers in the scope
    // of the method containing the jsr (because those exception
    // handlers may contain ret instructions in some cases).
    BlockBegin* block = bci2block()->at(bci);
    if (block != nullptr && block == parent()->bci2block()->at(bci)) {
      BlockBegin* new_block = new BlockBegin(block->bci());
      if (PrintInitialBlockList) {
        tty->print_cr("CFG: cloned block %d (bci %d) as block %d for jsr",
                      block->block_id(), block->bci(), new_block->block_id());
      }
      // copy data from cloned blocked
      new_block->set_depth_first_number(block->depth_first_number());
      if (block->is_set(BlockBegin::parser_loop_header_flag)) new_block->set(BlockBegin::parser_loop_header_flag);
      // Preserve certain flags for assertion checking
      if (block->is_set(BlockBegin::subroutine_entry_flag)) new_block->set(BlockBegin::subroutine_entry_flag);
      if (block->is_set(BlockBegin::exception_entry_flag))  new_block->set(BlockBegin::exception_entry_flag);

      // copy was_visited_flag to allow early detection of bailouts
      // if a block that is used in a jsr has already been visited before,
      // it is shared between the normal control flow and a subroutine
      // BlockBegin::try_merge returns false when the flag is set, this leads
      // to a compilation bailout
      if (block->is_set(BlockBegin::was_visited_flag))  new_block->set(BlockBegin::was_visited_flag);

      bci2block()->at_put(bci, new_block);
      block = new_block;
    }
    return block;
  } else {
    return bci2block()->at(bci);
  }
}


XHandlers* GraphBuilder::ScopeData::xhandlers() const {
  if (_jsr_xhandlers == nullptr) {
    assert(!parsing_jsr(), "");
    return scope()->xhandlers();
  }
  assert(parsing_jsr(), "");
  return _jsr_xhandlers;
}


void GraphBuilder::ScopeData::set_scope(IRScope* scope) {
  _scope = scope;
  bool parent_has_handler = false;
  if (parent() != nullptr) {
    parent_has_handler = parent()->has_handler();
  }
  _has_handler = parent_has_handler || scope->xhandlers()->has_handlers();
}


void GraphBuilder::ScopeData::set_inline_cleanup_info(BlockBegin* block,
                                                      Instruction* return_prev,
                                                      ValueStack* return_state) {
  _cleanup_block       = block;
  _cleanup_return_prev = return_prev;
  _cleanup_state       = return_state;
}


void GraphBuilder::ScopeData::add_to_work_list(BlockBegin* block) {
  if (_work_list == nullptr) {
    _work_list = new BlockList();
  }

  if (!block->is_set(BlockBegin::is_on_work_list_flag)) {
    // Do not start parsing the continuation block while in a
    // sub-scope
    if (parsing_jsr()) {
      if (block == jsr_continuation()) {
        return;
      }
    } else {
      if (block == continuation()) {
        return;
      }
    }
    block->set(BlockBegin::is_on_work_list_flag);
    _work_list->push(block);

    sort_top_into_worklist(_work_list, block);
  }
}


void GraphBuilder::sort_top_into_worklist(BlockList* worklist, BlockBegin* top) {
  assert(worklist->top() == top, "");
  // sort block descending into work list
  const int dfn = top->depth_first_number();
  assert(dfn != -1, "unknown depth first number");
  int i = worklist->length()-2;
  while (i >= 0) {
    BlockBegin* b = worklist->at(i);
    if (b->depth_first_number() < dfn) {
      worklist->at_put(i+1, b);
    } else {
      break;
    }
    i --;
  }
  if (i >= -1) worklist->at_put(i + 1, top);
}


BlockBegin* GraphBuilder::ScopeData::remove_from_work_list() {
  if (is_work_list_empty()) {
    return nullptr;
  }
  return _work_list->pop();
}


bool GraphBuilder::ScopeData::is_work_list_empty() const {
  return (_work_list == nullptr || _work_list->length() == 0);
}


void GraphBuilder::ScopeData::setup_jsr_xhandlers() {
  assert(parsing_jsr(), "");
  // clone all the exception handlers from the scope
  XHandlers* handlers = new XHandlers(scope()->xhandlers());
  const int n = handlers->length();
  for (int i = 0; i < n; i++) {
    // The XHandlers need to be adjusted to dispatch to the cloned
    // handler block instead of the default one but the synthetic
    // unlocker needs to be handled specially.  The synthetic unlocker
    // should be left alone since there can be only one and all code
    // should dispatch to the same one.
    XHandler* h = handlers->handler_at(i);
    assert(h->handler_bci() != SynchronizationEntryBCI, "must be real");
    h->set_entry_block(block_at(h->handler_bci()));
  }
  _jsr_xhandlers = handlers;
}


int GraphBuilder::ScopeData::num_returns() {
  if (parsing_jsr()) {
    return parent()->num_returns();
  }
  return _num_returns;
}


void GraphBuilder::ScopeData::incr_num_returns() {
  if (parsing_jsr()) {
    parent()->incr_num_returns();
  } else {
    ++_num_returns;
  }
}


// Implementation of GraphBuilder

#define INLINE_BAILOUT(msg)        { inline_bailout(msg); return false; }


void GraphBuilder::load_constant() {
  ciConstant con = stream()->get_constant();
  if (con.is_valid()) {
    ValueType* t = illegalType;
    ValueStack* patch_state = nullptr;
    switch (con.basic_type()) {
      case T_BOOLEAN: t = new IntConstant   (con.as_boolean()); break;
      case T_BYTE   : t = new IntConstant   (con.as_byte   ()); break;
      case T_CHAR   : t = new IntConstant   (con.as_char   ()); break;
      case T_SHORT  : t = new IntConstant   (con.as_short  ()); break;
      case T_INT    : t = new IntConstant   (con.as_int    ()); break;
      case T_LONG   : t = new LongConstant  (con.as_long   ()); break;
      case T_FLOAT  : t = new FloatConstant (con.as_float  ()); break;
      case T_DOUBLE : t = new DoubleConstant(con.as_double ()); break;
      case T_ARRAY  : // fall-through
      case T_OBJECT : {
        ciObject* obj = con.as_object();
        if (!obj->is_loaded() || (PatchALot && !stream()->is_string_constant())) {
          // A Class, MethodType, MethodHandle, Dynamic, or String.
          patch_state = copy_state_before();
          t = new ObjectConstant(obj);
        } else {
          // Might be a Class, MethodType, MethodHandle, or Dynamic constant
          // result, which might turn out to be an array.
          if (obj->is_null_object()) {
            t = objectNull;
          } else if (obj->is_array()) {
            t = new ArrayConstant(obj->as_array());
          } else {
            t = new InstanceConstant(obj->as_instance());
          }
        }
        break;
      }
      default: ShouldNotReachHere();
    }
    Value x;
    if (patch_state != nullptr) {
      // Arbitrary memory effects from running BSM or class loading (using custom loader) during linkage.
      bool kills_memory = stream()->is_dynamic_constant() ||
                          (!stream()->is_string_constant() && !method()->holder()->has_trusted_loader());
      x = new Constant(t, patch_state, kills_memory);
    } else {
      x = new Constant(t);
    }

    // Unbox the value at runtime, if needed.
    // ConstantDynamic entry can be of a primitive type, but it is cached in boxed form.
    if (patch_state != nullptr) {
      int cp_index = stream()->get_constant_pool_index();
      BasicType type = stream()->get_basic_type_for_constant_at(cp_index);
      if (is_java_primitive(type)) {
        ciInstanceKlass* box_klass = ciEnv::current()->get_box_klass_for_primitive_type(type);
        assert(box_klass->is_loaded(), "sanity");
        int offset = java_lang_boxing_object::value_offset(type);
        ciField* value_field = box_klass->get_field_by_offset(offset, false /*is_static*/);
        x = new LoadField(append(x), offset, value_field, false /*is_static*/, patch_state, false /*needs_patching*/);
        t = as_ValueType(type);
      } else {
        assert(is_reference_type(type), "not a reference: %s", type2name(type));
      }
    }

    push(t, append(x));
  } else {
    BAILOUT("could not resolve a constant");
  }
}


void GraphBuilder::load_local(ValueType* type, int index) {
  Value x = state()->local_at(index);
  assert(x != nullptr && !x->type()->is_illegal(), "access of illegal local variable");
  push(type, x);
}


void GraphBuilder::store_local(ValueType* type, int index) {
  Value x = pop(type);
  store_local(state(), x, index);
}


void GraphBuilder::store_local(ValueStack* state, Value x, int index) {
  if (parsing_jsr()) {
    // We need to do additional tracking of the location of the return
    // address for jsrs since we don't handle arbitrary jsr/ret
    // constructs. Here we are figuring out in which circumstances we
    // need to bail out.
    if (x->type()->is_address()) {
      scope_data()->set_jsr_return_address_local(index);

      // Also check parent jsrs (if any) at this time to see whether
      // they are using this local. We don't handle skipping over a
      // ret.
      for (ScopeData* cur_scope_data = scope_data()->parent();
           cur_scope_data != nullptr && cur_scope_data->parsing_jsr() && cur_scope_data->scope() == scope();
           cur_scope_data = cur_scope_data->parent()) {
        if (cur_scope_data->jsr_return_address_local() == index) {
          BAILOUT("subroutine overwrites return address from previous subroutine");
        }
      }
    } else if (index == scope_data()->jsr_return_address_local()) {
      scope_data()->set_jsr_return_address_local(-1);
    }
  }

  state->store_local(index, x);
}


void GraphBuilder::load_indexed(BasicType type) {
  // In case of in block code motion in range check elimination
  ValueStack* state_before = copy_state_indexed_access();
  compilation()->set_has_access_indexed(true);
  Value index = ipop();
  Value array = apop();
  Value length = nullptr;
  if (CSEArrayLength ||
      (array->as_Constant() != nullptr) ||
      (array->as_AccessField() && array->as_AccessField()->field()->is_constant()) ||
      (array->as_NewArray() && array->as_NewArray()->length() && array->as_NewArray()->length()->type()->is_constant()) ||
      (array->as_NewMultiArray() && array->as_NewMultiArray()->dims()->at(0)->type()->is_constant())) {
    length = append(new ArrayLength(array, state_before));
  }
  push(as_ValueType(type), append(new LoadIndexed(array, index, length, type, state_before)));
}


void GraphBuilder::store_indexed(BasicType type) {
  // In case of in block code motion in range check elimination
  ValueStack* state_before = copy_state_indexed_access();
  compilation()->set_has_access_indexed(true);
  Value value = pop(as_ValueType(type));
  Value index = ipop();
  Value array = apop();
  Value length = nullptr;
  if (CSEArrayLength ||
      (array->as_Constant() != nullptr) ||
      (array->as_AccessField() && array->as_AccessField()->field()->is_constant()) ||
      (array->as_NewArray() && array->as_NewArray()->length() && array->as_NewArray()->length()->type()->is_constant()) ||
      (array->as_NewMultiArray() && array->as_NewMultiArray()->dims()->at(0)->type()->is_constant())) {
    length = append(new ArrayLength(array, state_before));
  }
  ciType* array_type = array->declared_type();
  bool check_boolean = false;
  if (array_type != nullptr) {
    if (array_type->is_loaded() &&
      array_type->as_array_klass()->element_type()->basic_type() == T_BOOLEAN) {
      assert(type == T_BYTE, "boolean store uses bastore");
      Value mask = append(new Constant(new IntConstant(1)));
      value = append(new LogicOp(Bytecodes::_iand, value, mask));
    }
  } else if (type == T_BYTE) {
    check_boolean = true;
  }
  StoreIndexed* result = new StoreIndexed(array, index, length, type, value, state_before, check_boolean);
  append(result);
  _memory->store_value(value);

  if (type == T_OBJECT && is_profiling()) {
    // Note that we'd collect profile data in this method if we wanted it.
    compilation()->set_would_profile(true);

    if (profile_checkcasts()) {
      result->set_profiled_method(method());
      result->set_profiled_bci(bci());
      result->set_should_profile(true);
    }
  }
}


void GraphBuilder::stack_op(Bytecodes::Code code) {
  switch (code) {
    case Bytecodes::_pop:
      { state()->raw_pop();
      }
      break;
    case Bytecodes::_pop2:
      { state()->raw_pop();
        state()->raw_pop();
      }
      break;
    case Bytecodes::_dup:
      { Value w = state()->raw_pop();
        state()->raw_push(w);
        state()->raw_push(w);
      }
      break;
    case Bytecodes::_dup_x1:
      { Value w1 = state()->raw_pop();
        Value w2 = state()->raw_pop();
        state()->raw_push(w1);
        state()->raw_push(w2);
        state()->raw_push(w1);
      }
      break;
    case Bytecodes::_dup_x2:
      { Value w1 = state()->raw_pop();
        Value w2 = state()->raw_pop();
        Value w3 = state()->raw_pop();
        state()->raw_push(w1);
        state()->raw_push(w3);
        state()->raw_push(w2);
        state()->raw_push(w1);
      }
      break;
    case Bytecodes::_dup2:
      { Value w1 = state()->raw_pop();
        Value w2 = state()->raw_pop();
        state()->raw_push(w2);
        state()->raw_push(w1);
        state()->raw_push(w2);
        state()->raw_push(w1);
      }
      break;
    case Bytecodes::_dup2_x1:
      { Value w1 = state()->raw_pop();
        Value w2 = state()->raw_pop();
        Value w3 = state()->raw_pop();
        state()->raw_push(w2);
        state()->raw_push(w1);
        state()->raw_push(w3);
        state()->raw_push(w2);
        state()->raw_push(w1);
      }
      break;
    case Bytecodes::_dup2_x2:
      { Value w1 = state()->raw_pop();
        Value w2 = state()->raw_pop();
        Value w3 = state()->raw_pop();
        Value w4 = state()->raw_pop();
        state()->raw_push(w2);
        state()->raw_push(w1);
        state()->raw_push(w4);
        state()->raw_push(w3);
        state()->raw_push(w2);
        state()->raw_push(w1);
      }
      break;
    case Bytecodes::_swap:
      { Value w1 = state()->raw_pop();
        Value w2 = state()->raw_pop();
        state()->raw_push(w1);
        state()->raw_push(w2);
      }
      break;
    default:
      ShouldNotReachHere();
      break;
  }
}


void GraphBuilder::arithmetic_op(ValueType* type, Bytecodes::Code code, ValueStack* state_before) {
  Value y = pop(type);
  Value x = pop(type);
  Value res = new ArithmeticOp(code, x, y, state_before);
  push(type, append(res));
}


void GraphBuilder::negate_op(ValueType* type) {
  push(type, append(new NegateOp(pop(type))));
}


void GraphBuilder::shift_op(ValueType* type, Bytecodes::Code code) {
  Value s = ipop();
  Value x = pop(type);
  // try to simplify
  // Note: This code should go into the canonicalizer as soon as it can
  //       can handle canonicalized forms that contain more than one node.
  if (CanonicalizeNodes && code == Bytecodes::_iushr) {
    // pattern: x >>> s
    IntConstant* s1 = s->type()->as_IntConstant();
    if (s1 != nullptr) {
      // pattern: x >>> s1, with s1 constant
      ShiftOp* l = x->as_ShiftOp();
      if (l != nullptr && l->op() == Bytecodes::_ishl) {
        // pattern: (a << b) >>> s1
        IntConstant* s0 = l->y()->type()->as_IntConstant();
        if (s0 != nullptr) {
          // pattern: (a << s0) >>> s1
          const int s0c = s0->value() & 0x1F; // only the low 5 bits are significant for shifts
          const int s1c = s1->value() & 0x1F; // only the low 5 bits are significant for shifts
          if (s0c == s1c) {
            if (s0c == 0) {
              // pattern: (a << 0) >>> 0 => simplify to: a
              ipush(l->x());
            } else {
              // pattern: (a << s0c) >>> s0c => simplify to: a & m, with m constant
              assert(0 < s0c && s0c < BitsPerInt, "adjust code below to handle corner cases");
              const int m = checked_cast<int>(right_n_bits(BitsPerInt - s0c));
              Value s = append(new Constant(new IntConstant(m)));
              ipush(append(new LogicOp(Bytecodes::_iand, l->x(), s)));
            }
            return;
          }
        }
      }
    }
  }
  // could not simplify
  push(type, append(new ShiftOp(code, x, s)));
}


void GraphBuilder::logic_op(ValueType* type, Bytecodes::Code code) {
  Value y = pop(type);
  Value x = pop(type);
  push(type, append(new LogicOp(code, x, y)));
}


void GraphBuilder::compare_op(ValueType* type, Bytecodes::Code code) {
  ValueStack* state_before = copy_state_before();
  Value y = pop(type);
  Value x = pop(type);
  ipush(append(new CompareOp(code, x, y, state_before)));
}


void GraphBuilder::convert(Bytecodes::Code op, BasicType from, BasicType to) {
  push(as_ValueType(to), append(new Convert(op, pop(as_ValueType(from)), as_ValueType(to))));
}


void GraphBuilder::increment() {
  int index = stream()->get_index();
  int delta = stream()->is_wide() ? (signed short)Bytes::get_Java_u2(stream()->cur_bcp() + 4) : (signed char)(stream()->cur_bcp()[2]);
  load_local(intType, index);
  ipush(append(new Constant(new IntConstant(delta))));
  arithmetic_op(intType, Bytecodes::_iadd);
  store_local(intType, index);
}


void GraphBuilder::_goto(int from_bci, int to_bci) {
  Goto *x = new Goto(block_at(to_bci), to_bci <= from_bci);
  if (is_profiling()) {
    compilation()->set_would_profile(true);
    x->set_profiled_bci(bci());
    if (profile_branches()) {
      x->set_profiled_method(method());
      x->set_should_profile(true);
    }
  }
  append(x);
}


void GraphBuilder::if_node(Value x, If::Condition cond, Value y, ValueStack* state_before) {
  BlockBegin* tsux = block_at(stream()->get_dest());
  BlockBegin* fsux = block_at(stream()->next_bci());
  bool is_bb = tsux->bci() < stream()->cur_bci() || fsux->bci() < stream()->cur_bci();
  // In case of loop invariant code motion or predicate insertion
  // before the body of a loop the state is needed
  Instruction *i = append(new If(x, cond, false, y, tsux, fsux, (is_bb || compilation()->is_optimistic()) ? state_before : nullptr, is_bb));

  assert(i->as_Goto() == nullptr ||
         (i->as_Goto()->sux_at(0) == tsux  && i->as_Goto()->is_safepoint() == (tsux->bci() < stream()->cur_bci())) ||
         (i->as_Goto()->sux_at(0) == fsux  && i->as_Goto()->is_safepoint() == (fsux->bci() < stream()->cur_bci())),
         "safepoint state of Goto returned by canonicalizer incorrect");

  if (is_profiling()) {
    If* if_node = i->as_If();
    if (if_node != nullptr) {
      // Note that we'd collect profile data in this method if we wanted it.
      compilation()->set_would_profile(true);
      // At level 2 we need the proper bci to count backedges
      if_node->set_profiled_bci(bci());
      if (profile_branches()) {
        // Successors can be rotated by the canonicalizer, check for this case.
        if_node->set_profiled_method(method());
        if_node->set_should_profile(true);
        if (if_node->tsux() == fsux) {
          if_node->set_swapped(true);
        }
      }
      return;
    }

    // Check if this If was reduced to Goto.
    Goto *goto_node = i->as_Goto();
    if (goto_node != nullptr) {
      compilation()->set_would_profile(true);
      goto_node->set_profiled_bci(bci());
      if (profile_branches()) {
        goto_node->set_profiled_method(method());
        goto_node->set_should_profile(true);
        // Find out which successor is used.
        if (goto_node->default_sux() == tsux) {
          goto_node->set_direction(Goto::taken);
        } else if (goto_node->default_sux() == fsux) {
          goto_node->set_direction(Goto::not_taken);
        } else {
          ShouldNotReachHere();
        }
      }
      return;
    }
  }
}


void GraphBuilder::if_zero(ValueType* type, If::Condition cond) {
  Value y = append(new Constant(intZero));
  ValueStack* state_before = copy_state_before();
  Value x = ipop();
  if_node(x, cond, y, state_before);
}


void GraphBuilder::if_null(ValueType* type, If::Condition cond) {
  Value y = append(new Constant(objectNull));
  ValueStack* state_before = copy_state_before();
  Value x = apop();
  if_node(x, cond, y, state_before);
}


void GraphBuilder::if_same(ValueType* type, If::Condition cond) {
  ValueStack* state_before = copy_state_before();
  Value y = pop(type);
  Value x = pop(type);
  if_node(x, cond, y, state_before);
}


void GraphBuilder::jsr(int dest) {
  // We only handle well-formed jsrs (those which are "block-structured").
  // If the bytecodes are strange (jumping out of a jsr block) then we
  // might end up trying to re-parse a block containing a jsr which
  // has already been activated. Watch for this case and bail out.
  if (next_bci() >= method()->code_size()) {
    // This can happen if the subroutine does not terminate with a ret,
    // effectively turning the jsr into a goto.
    BAILOUT("too-complicated jsr/ret structure");
  }
  for (ScopeData* cur_scope_data = scope_data();
       cur_scope_data != nullptr && cur_scope_data->parsing_jsr() && cur_scope_data->scope() == scope();
       cur_scope_data = cur_scope_data->parent()) {
    if (cur_scope_data->jsr_entry_bci() == dest) {
      BAILOUT("too-complicated jsr/ret structure");
    }
  }

  push(addressType, append(new Constant(new AddressConstant(next_bci()))));
  if (!try_inline_jsr(dest)) {
    return; // bailed out while parsing and inlining subroutine
  }
}


void GraphBuilder::ret(int local_index) {
  if (!parsing_jsr()) BAILOUT("ret encountered while not parsing subroutine");

  if (local_index != scope_data()->jsr_return_address_local()) {
    BAILOUT("can not handle complicated jsr/ret constructs");
  }

  // Rets simply become (NON-SAFEPOINT) gotos to the jsr continuation
  append(new Goto(scope_data()->jsr_continuation(), false));
}


void GraphBuilder::table_switch() {
  Bytecode_tableswitch sw(stream());
  const int l = sw.length();
  if (CanonicalizeNodes && l == 1 && compilation()->env()->comp_level() != CompLevel_full_profile) {
    // total of 2 successors => use If instead of switch
    // Note: This code should go into the canonicalizer as soon as it can
    //       can handle canonicalized forms that contain more than one node.
    Value key = append(new Constant(new IntConstant(sw.low_key())));
    BlockBegin* tsux = block_at(bci() + sw.dest_offset_at(0));
    BlockBegin* fsux = block_at(bci() + sw.default_offset());
    bool is_bb = tsux->bci() < bci() || fsux->bci() < bci();
    // In case of loop invariant code motion or predicate insertion
    // before the body of a loop the state is needed
    ValueStack* state_before = copy_state_if_bb(is_bb);
    append(new If(ipop(), If::eql, true, key, tsux, fsux, state_before, is_bb));
  } else {
    // collect successors
    BlockList* sux = new BlockList(l + 1, nullptr);
    int i;
    bool has_bb = false;
    for (i = 0; i < l; i++) {
      sux->at_put(i, block_at(bci() + sw.dest_offset_at(i)));
      if (sw.dest_offset_at(i) < 0) has_bb = true;
    }
    // add default successor
    if (sw.default_offset() < 0) has_bb = true;
    sux->at_put(i, block_at(bci() + sw.default_offset()));
    // In case of loop invariant code motion or predicate insertion
    // before the body of a loop the state is needed
    ValueStack* state_before = copy_state_if_bb(has_bb);
    Instruction* res = append(new TableSwitch(ipop(), sux, sw.low_key(), state_before, has_bb));
#ifdef ASSERT
    if (res->as_Goto()) {
      for (i = 0; i < l; i++) {
        if (sux->at(i) == res->as_Goto()->sux_at(0)) {
          assert(res->as_Goto()->is_safepoint() == (sw.dest_offset_at(i) < 0), "safepoint state of Goto returned by canonicalizer incorrect");
        }
      }
    }
#endif
  }
}


void GraphBuilder::lookup_switch() {
  Bytecode_lookupswitch sw(stream());
  const int l = sw.number_of_pairs();
  if (CanonicalizeNodes && l == 1 && compilation()->env()->comp_level() != CompLevel_full_profile) {
    // total of 2 successors => use If instead of switch
    // Note: This code should go into the canonicalizer as soon as it can
    //       can handle canonicalized forms that contain more than one node.
    // simplify to If
    LookupswitchPair pair = sw.pair_at(0);
    Value key = append(new Constant(new IntConstant(pair.match())));
    BlockBegin* tsux = block_at(bci() + pair.offset());
    BlockBegin* fsux = block_at(bci() + sw.default_offset());
    bool is_bb = tsux->bci() < bci() || fsux->bci() < bci();
    // In case of loop invariant code motion or predicate insertion
    // before the body of a loop the state is needed
    ValueStack* state_before = copy_state_if_bb(is_bb);;
    append(new If(ipop(), If::eql, true, key, tsux, fsux, state_before, is_bb));
  } else {
    // collect successors & keys
    BlockList* sux = new BlockList(l + 1, nullptr);
    intArray* keys = new intArray(l, l, 0);
    int i;
    bool has_bb = false;
    for (i = 0; i < l; i++) {
      LookupswitchPair pair = sw.pair_at(i);
      if (pair.offset() < 0) has_bb = true;
      sux->at_put(i, block_at(bci() + pair.offset()));
      keys->at_put(i, pair.match());
    }
    // add default successor
    if (sw.default_offset() < 0) has_bb = true;
    sux->at_put(i, block_at(bci() + sw.default_offset()));
    // In case of loop invariant code motion or predicate insertion
    // before the body of a loop the state is needed
    ValueStack* state_before = copy_state_if_bb(has_bb);
    Instruction* res = append(new LookupSwitch(ipop(), sux, keys, state_before, has_bb));
#ifdef ASSERT
    if (res->as_Goto()) {
      for (i = 0; i < l; i++) {
        if (sux->at(i) == res->as_Goto()->sux_at(0)) {
          assert(res->as_Goto()->is_safepoint() == (sw.pair_at(i).offset() < 0), "safepoint state of Goto returned by canonicalizer incorrect");
        }
      }
    }
#endif
  }
}

void GraphBuilder::call_register_finalizer() {
  // If the receiver requires finalization then emit code to perform
  // the registration on return.

  // Gather some type information about the receiver
  Value receiver = state()->local_at(0);
  assert(receiver != nullptr, "must have a receiver");
  ciType* declared_type = receiver->declared_type();
  ciType* exact_type = receiver->exact_type();
  if (exact_type == nullptr &&
      receiver->as_Local() &&
      receiver->as_Local()->java_index() == 0) {
    ciInstanceKlass* ik = compilation()->method()->holder();
    if (ik->is_final()) {
      exact_type = ik;
    } else if (UseCHA && !(ik->has_subklass() || ik->is_interface())) {
      // test class is leaf class
      compilation()->dependency_recorder()->assert_leaf_type(ik);
      exact_type = ik;
    } else {
      declared_type = ik;
    }
  }

  // see if we know statically that registration isn't required
  bool needs_check = true;
  if (exact_type != nullptr) {
    needs_check = exact_type->as_instance_klass()->has_finalizer();
  } else if (declared_type != nullptr) {
    ciInstanceKlass* ik = declared_type->as_instance_klass();
    if (!Dependencies::has_finalizable_subclass(ik)) {
      compilation()->dependency_recorder()->assert_has_no_finalizable_subclasses(ik);
      needs_check = false;
    }
  }

  if (needs_check) {
    // Perform the registration of finalizable objects.
    ValueStack* state_before = copy_state_for_exception();
    load_local(objectType, 0);
    append_split(new Intrinsic(voidType, vmIntrinsics::_Object_init,
                               state()->pop_arguments(1),
                               true, state_before, true));
  }
}


void GraphBuilder::method_return(Value x, bool ignore_return) {
  if (method()->intrinsic_id() == vmIntrinsics::_Object_init) {
    call_register_finalizer();
  }

  // The conditions for a memory barrier are described in Parse::do_exits().
  bool need_mem_bar = false;
  if (method()->name() == ciSymbols::object_initializer_name() &&
       (scope()->wrote_final() || scope()->wrote_stable() ||
         (AlwaysSafeConstructors && scope()->wrote_fields()) ||
         (support_IRIW_for_not_multiple_copy_atomic_cpu && scope()->wrote_volatile()))) {
    need_mem_bar = true;
  }

  BasicType bt = method()->return_type()->basic_type();
  switch (bt) {
    case T_BYTE:
    {
      Value shift = append(new Constant(new IntConstant(24)));
      x = append(new ShiftOp(Bytecodes::_ishl, x, shift));
      x = append(new ShiftOp(Bytecodes::_ishr, x, shift));
      break;
    }
    case T_SHORT:
    {
      Value shift = append(new Constant(new IntConstant(16)));
      x = append(new ShiftOp(Bytecodes::_ishl, x, shift));
      x = append(new ShiftOp(Bytecodes::_ishr, x, shift));
      break;
    }
    case T_CHAR:
    {
      Value mask = append(new Constant(new IntConstant(0xFFFF)));
      x = append(new LogicOp(Bytecodes::_iand, x, mask));
      break;
    }
    case T_BOOLEAN:
    {
      Value mask = append(new Constant(new IntConstant(1)));
      x = append(new LogicOp(Bytecodes::_iand, x, mask));
      break;
    }
    default:
      break;
  }

  // Check to see whether we are inlining. If so, Return
  // instructions become Gotos to the continuation point.
  if (continuation() != nullptr) {

    int invoke_bci = state()->caller_state()->bci();

    if (x != nullptr  && !ignore_return) {
      ciMethod* caller = state()->scope()->caller()->method();
      Bytecodes::Code invoke_raw_bc = caller->raw_code_at_bci(invoke_bci);
      if (invoke_raw_bc == Bytecodes::_invokehandle || invoke_raw_bc == Bytecodes::_invokedynamic) {
        ciType* declared_ret_type = caller->get_declared_signature_at_bci(invoke_bci)->return_type();
        if (declared_ret_type->is_klass() && x->exact_type() == nullptr &&
            x->declared_type() != declared_ret_type && declared_ret_type != compilation()->env()->Object_klass()) {
          x = append(new TypeCast(declared_ret_type->as_klass(), x, copy_state_before()));
        }
      }
    }

    assert(!method()->is_synchronized() || InlineSynchronizedMethods, "can not inline synchronized methods yet");

    if (compilation()->env()->dtrace_method_probes()) {
      // Report exit from inline methods
      Values* args = new Values(1);
      args->push(append(new Constant(new MethodConstant(method()))));
      append(new RuntimeCall(voidType, "dtrace_method_exit", CAST_FROM_FN_PTR(address, SharedRuntime::dtrace_method_exit), args));
    }

    // If the inlined method is synchronized, the monitor must be
    // released before we jump to the continuation block.
    if (method()->is_synchronized()) {
      assert(state()->locks_size() == 1, "receiver must be locked here");
      monitorexit(state()->lock_at(0), SynchronizationEntryBCI);
    }

    if (need_mem_bar) {
      append(new MemBar(lir_membar_storestore));
    }

    // State at end of inlined method is the state of the caller
    // without the method parameters on stack, including the
    // return value, if any, of the inlined method on operand stack.
    set_state(state()->caller_state()->copy_for_parsing());
    if (x != nullptr) {
      if (!ignore_return) {
        state()->push(x->type(), x);
      }
      if (profile_return() && x->type()->is_object_kind()) {
        ciMethod* caller = state()->scope()->method();
        profile_return_type(x, method(), caller, invoke_bci);
      }
    }
    Goto* goto_callee = new Goto(continuation(), false);

    // See whether this is the first return; if so, store off some
    // of the state for later examination
    if (num_returns() == 0) {
      set_inline_cleanup_info();
    }

    // The current bci() is in the wrong scope, so use the bci() of
    // the continuation point.
    append_with_bci(goto_callee, scope_data()->continuation()->bci());
    incr_num_returns();
    return;
  }

  state()->truncate_stack(0);
  if (method()->is_synchronized()) {
    // perform the unlocking before exiting the method
    Value receiver;
    if (!method()->is_static()) {
      receiver = _initial_state->local_at(0);
    } else {
      receiver = append(new Constant(new ClassConstant(method()->holder())));
    }
    append_split(new MonitorExit(receiver, state()->unlock()));
  }

  if (need_mem_bar) {
      append(new MemBar(lir_membar_storestore));
  }

  assert(!ignore_return, "Ignoring return value works only for inlining");
  append(new Return(x));
}

Value GraphBuilder::make_constant(ciConstant field_value, ciField* field) {
  if (!field_value.is_valid())  return nullptr;

  BasicType field_type = field_value.basic_type();
  ValueType* value = as_ValueType(field_value);

  // Attach dimension info to stable arrays.
  if (FoldStableValues &&
      field->is_stable() && field_type == T_ARRAY && !field_value.is_null_or_zero()) {
    ciArray* array = field_value.as_object()->as_array();
    jint dimension = field->type()->as_array_klass()->dimension();
    value = new StableArrayConstant(array, dimension);
  }

  switch (field_type) {
    case T_ARRAY:
    case T_OBJECT:
      if (field_value.as_object()->should_be_constant()) {
        return new Constant(value);
      }
      return nullptr; // Not a constant.
    default:
      return new Constant(value);
  }
}

void GraphBuilder::access_field(Bytecodes::Code code) {
  bool will_link;
  ciField* field = stream()->get_field(will_link);
  ciInstanceKlass* holder = field->holder();
  BasicType field_type = field->type()->basic_type();
  ValueType* type = as_ValueType(field_type);
  // call will_link again to determine if the field is valid.
  const bool needs_patching = !holder->is_loaded() ||
                              !field->will_link(method(), code) ||
                              PatchALot;

  ValueStack* state_before = nullptr;
  if (!holder->is_initialized() || needs_patching) {
    // save state before instruction for debug info when
    // deoptimization happens during patching
    state_before = copy_state_before();
  }

  Value obj = nullptr;
  if (code == Bytecodes::_getstatic || code == Bytecodes::_putstatic) {
    if (state_before != nullptr) {
      // build a patching constant
      obj = new Constant(new InstanceConstant(holder->java_mirror()), state_before);
    } else {
      obj = new Constant(new InstanceConstant(holder->java_mirror()));
    }
  }

  if (code == Bytecodes::_putfield) {
    scope()->set_wrote_fields();
    if (field->is_volatile()) {
      scope()->set_wrote_volatile();
    }
    if (field->is_final()) {
      scope()->set_wrote_final();
    }
    if (field->is_stable()) {
      scope()->set_wrote_stable();
    }
  }

  const int offset = !needs_patching ? field->offset_in_bytes() : -1;
  switch (code) {
    case Bytecodes::_getstatic: {
      // check for compile-time constants, i.e., initialized static final fields
      Value constant = nullptr;
      if (field->is_static_constant() && !PatchALot) {
        ciConstant field_value = field->constant_value();
        assert(!field->is_stable() || !field_value.is_null_or_zero(),
               "stable static w/ default value shouldn't be a constant");
        constant = make_constant(field_value, field);
      }
      if (constant != nullptr) {
        push(type, append(constant));
      } else {
        if (state_before == nullptr) {
          state_before = copy_state_for_exception();
        }
        push(type, append(new LoadField(append(obj), offset, field, true,
                                        state_before, needs_patching)));
      }
      break;
    }
    case Bytecodes::_putstatic: {
      Value val = pop(type);
      if (state_before == nullptr) {
        state_before = copy_state_for_exception();
      }
      if (field->type()->basic_type() == T_BOOLEAN) {
        Value mask = append(new Constant(new IntConstant(1)));
        val = append(new LogicOp(Bytecodes::_iand, val, mask));
      }
      append(new StoreField(append(obj), offset, field, val, true, state_before, needs_patching));
      break;
    }
    case Bytecodes::_getfield: {
      // Check for compile-time constants, i.e., trusted final non-static fields.
      Value constant = nullptr;
      obj = apop();
      ObjectType* obj_type = obj->type()->as_ObjectType();
      if (field->is_constant() && obj_type->is_constant() && !PatchALot) {
        ciObject* const_oop = obj_type->constant_value();
        if (!const_oop->is_null_object() && const_oop->is_loaded()) {
          ciConstant field_value = field->constant_value_of(const_oop);
          if (field_value.is_valid()) {
            constant = make_constant(field_value, field);
            // For CallSite objects add a dependency for invalidation of the optimization.
            if (field->is_call_site_target()) {
              ciCallSite* call_site = const_oop->as_call_site();
              if (!call_site->is_fully_initialized_constant_call_site()) {
                ciMethodHandle* target = field_value.as_object()->as_method_handle();
                dependency_recorder()->assert_call_site_target_value(call_site, target);
              }
            }
          }
        }
      }
      if (constant != nullptr) {
        push(type, append(constant));
      } else {
        if (state_before == nullptr) {
          state_before = copy_state_for_exception();
        }
        LoadField* load = new LoadField(obj, offset, field, false, state_before, needs_patching);
        Value replacement = !needs_patching ? _memory->load(load) : load;
        if (replacement != load) {
          assert(replacement->is_linked() || !replacement->can_be_linked(), "should already by linked");
          // Writing an (integer) value to a boolean, byte, char or short field includes an implicit narrowing
          // conversion. Emit an explicit conversion here to get the correct field value after the write.
          BasicType bt = field->type()->basic_type();
          switch (bt) {
          case T_BOOLEAN:
          case T_BYTE:
            replacement = append(new Convert(Bytecodes::_i2b, replacement, as_ValueType(bt)));
            break;
          case T_CHAR:
            replacement = append(new Convert(Bytecodes::_i2c, replacement, as_ValueType(bt)));
            break;
          case T_SHORT:
            replacement = append(new Convert(Bytecodes::_i2s, replacement, as_ValueType(bt)));
            break;
          default:
            break;
          }
          push(type, replacement);
        } else {
          push(type, append(load));
        }
      }
      break;
    }
    case Bytecodes::_putfield: {
      Value val = pop(type);
      obj = apop();
      if (state_before == nullptr) {
        state_before = copy_state_for_exception();
      }
      if (field->type()->basic_type() == T_BOOLEAN) {
        Value mask = append(new Constant(new IntConstant(1)));
        val = append(new LogicOp(Bytecodes::_iand, val, mask));
      }
      StoreField* store = new StoreField(obj, offset, field, val, false, state_before, needs_patching);
      if (!needs_patching) store = _memory->store(store);
      if (store != nullptr) {
        append(store);
      }
      break;
    }
    default:
      ShouldNotReachHere();
      break;
  }
}


Dependencies* GraphBuilder::dependency_recorder() const {
  assert(DeoptC1, "need debug information");
  return compilation()->dependency_recorder();
}

// How many arguments do we want to profile?
Values* GraphBuilder::args_list_for_profiling(ciMethod* target, int& start, bool may_have_receiver) {
  int n = 0;
  bool has_receiver = may_have_receiver && Bytecodes::has_receiver(method()->java_code_at_bci(bci()));
  start = has_receiver ? 1 : 0;
  if (profile_arguments()) {
    ciProfileData* data = method()->method_data()->bci_to_data(bci());
    if (data != nullptr && (data->is_CallTypeData() || data->is_VirtualCallTypeData())) {
      n = data->is_CallTypeData() ? data->as_CallTypeData()->number_of_arguments() : data->as_VirtualCallTypeData()->number_of_arguments();
    }
  }
  // If we are inlining then we need to collect arguments to profile parameters for the target
  if (profile_parameters() && target != nullptr) {
    if (target->method_data() != nullptr && target->method_data()->parameters_type_data() != nullptr) {
      // The receiver is profiled on method entry so it's included in
      // the number of parameters but here we're only interested in
      // actual arguments.
      n = MAX2(n, target->method_data()->parameters_type_data()->number_of_parameters() - start);
    }
  }
  if (n > 0) {
    return new Values(n);
  }
  return nullptr;
}

void GraphBuilder::check_args_for_profiling(Values* obj_args, int expected) {
#ifdef ASSERT
  bool ignored_will_link;
  ciSignature* declared_signature = nullptr;
  ciMethod* real_target = method()->get_method_at_bci(bci(), ignored_will_link, &declared_signature);
  assert(expected == obj_args->capacity() || real_target->is_method_handle_intrinsic(), "missed on arg?");
#endif
}

// Collect arguments that we want to profile in a list
Values* GraphBuilder::collect_args_for_profiling(Values* args, ciMethod* target, bool may_have_receiver) {
  int start = 0;
  Values* obj_args = args_list_for_profiling(target, start, may_have_receiver);
  if (obj_args == nullptr) {
    return nullptr;
  }
  int s = obj_args->capacity();
  // if called through method handle invoke, some arguments may have been popped
  for (int i = start, j = 0; j < s && i < args->length(); i++) {
    if (args->at(i)->type()->is_object_kind()) {
      obj_args->push(args->at(i));
      j++;
    }
  }
  check_args_for_profiling(obj_args, s);
  return obj_args;
}

void GraphBuilder::invoke(Bytecodes::Code code) {
  bool will_link;
  ciSignature* declared_signature = nullptr;
  ciMethod*             target = stream()->get_method(will_link, &declared_signature);
  ciKlass*              holder = stream()->get_declared_method_holder();
  const Bytecodes::Code bc_raw = stream()->cur_bc_raw();
  assert(declared_signature != nullptr, "cannot be null");
  assert(will_link == target->is_loaded(), "");
  JFR_ONLY(Jfr::on_resolution(this, holder, target); CHECK_BAILOUT();)

  ciInstanceKlass* klass = target->holder();
  assert(!target->is_loaded() || klass->is_loaded(), "loaded target must imply loaded klass");

  // check if CHA possible: if so, change the code to invoke_special
  ciInstanceKlass* calling_klass = method()->holder();
  ciInstanceKlass* callee_holder = ciEnv::get_instance_klass_for_declared_method_holder(holder);
  ciInstanceKlass* actual_recv = callee_holder;

  CompileLog* log = compilation()->log();
  if (log != nullptr)
      log->elem("call method='%d' instr='%s'",
                log->identify(target),
                Bytecodes::name(code));

  // Some methods are obviously bindable without any type checks so
  // convert them directly to an invokespecial or invokestatic.
  if (target->is_loaded() && !target->is_abstract() && target->can_be_statically_bound()) {
    switch (bc_raw) {
    case Bytecodes::_invokeinterface:
      // convert to invokespecial if the target is the private interface method.
      if (target->is_private()) {
        assert(holder->is_interface(), "How did we get a non-interface method here!");
        code = Bytecodes::_invokespecial;
      }
      break;
    case Bytecodes::_invokevirtual:
      code = Bytecodes::_invokespecial;
      break;
    case Bytecodes::_invokehandle:
      code = target->is_static() ? Bytecodes::_invokestatic : Bytecodes::_invokespecial;
      break;
    default:
      break;
    }
  } else {
    if (bc_raw == Bytecodes::_invokehandle) {
      assert(!will_link, "should come here only for unlinked call");
      code = Bytecodes::_invokespecial;
    }
  }

  if (code == Bytecodes::_invokespecial) {
    // Additional receiver subtype checks for interface calls via invokespecial or invokeinterface.
    ciKlass* receiver_constraint = nullptr;

    if (bc_raw == Bytecodes::_invokeinterface) {
      receiver_constraint = holder;
    } else if (bc_raw == Bytecodes::_invokespecial && !target->is_object_initializer() && calling_klass->is_interface()) {
      receiver_constraint = calling_klass;
    }

    if (receiver_constraint != nullptr) {
      int index = state()->stack_size() - (target->arg_size_no_receiver() + 1);
      Value receiver = state()->stack_at(index);
      CheckCast* c = new CheckCast(receiver_constraint, receiver, copy_state_before());
      // go to uncommon_trap when checkcast fails
      c->set_invokespecial_receiver_check();
      state()->stack_at_put(index, append_split(c));
    }
  }

  // Push appendix argument (MethodType, CallSite, etc.), if one.
  bool patch_for_appendix = false;
  int patching_appendix_arg = 0;
  if (Bytecodes::has_optional_appendix(bc_raw) && (!will_link || PatchALot)) {
    Value arg = append(new Constant(new ObjectConstant(compilation()->env()->unloaded_ciinstance()), copy_state_before()));
    apush(arg);
    patch_for_appendix = true;
    patching_appendix_arg = (will_link && stream()->has_appendix()) ? 0 : 1;
  } else if (stream()->has_appendix()) {
    ciObject* appendix = stream()->get_appendix();
    Value arg = append(new Constant(new ObjectConstant(appendix)));
    apush(arg);
  }

  ciMethod* cha_monomorphic_target = nullptr;
  ciMethod* exact_target = nullptr;
  Value better_receiver = nullptr;
  if (UseCHA && DeoptC1 && target->is_loaded() &&
      !(// %%% FIXME: Are both of these relevant?
        target->is_method_handle_intrinsic() ||
        target->is_compiled_lambda_form()) &&
      !patch_for_appendix) {
    Value receiver = nullptr;
    ciInstanceKlass* receiver_klass = nullptr;
    bool type_is_exact = false;
    // try to find a precise receiver type
    if (will_link && !target->is_static()) {
      int index = state()->stack_size() - (target->arg_size_no_receiver() + 1);
      receiver = state()->stack_at(index);
      ciType* type = receiver->exact_type();
      if (type != nullptr && type->is_loaded()) {
        assert(!type->is_instance_klass() || !type->as_instance_klass()->is_interface(), "Must not be an interface");
        // Detects non-interface instances, primitive arrays, and some object arrays.
        // Array receivers can only call Object methods, so we should be able to allow
        // all object arrays here too, even those with unloaded types.
        receiver_klass = (ciInstanceKlass*) type;
        type_is_exact = true;
      }
      if (type == nullptr) {
        type = receiver->declared_type();
        if (type != nullptr && type->is_loaded() &&
            type->is_instance_klass() && !type->as_instance_klass()->is_interface()) {
          receiver_klass = (ciInstanceKlass*) type;
          if (receiver_klass->is_leaf_type() && !receiver_klass->is_final()) {
            // Insert a dependency on this type since
            // find_monomorphic_target may assume it's already done.
            dependency_recorder()->assert_leaf_type(receiver_klass);
            type_is_exact = true;
          }
        }
      }
    }
    if (receiver_klass != nullptr && type_is_exact &&
        receiver_klass->is_loaded() && code != Bytecodes::_invokespecial) {
      // If we have the exact receiver type we can bind directly to
      // the method to call.
      exact_target = target->resolve_invoke(calling_klass, receiver_klass);
      if (exact_target != nullptr) {
        target = exact_target;
        code = Bytecodes::_invokespecial;
      }
    }
    if (receiver_klass != nullptr &&
        receiver_klass->is_subtype_of(actual_recv) &&
        actual_recv->is_initialized()) {
      actual_recv = receiver_klass;
    }

    if ((code == Bytecodes::_invokevirtual && callee_holder->is_initialized()) ||
        (code == Bytecodes::_invokeinterface && callee_holder->is_initialized() && !actual_recv->is_interface())) {
      // Use CHA on the receiver to select a more precise method.
      cha_monomorphic_target = target->find_monomorphic_target(calling_klass, callee_holder, actual_recv);
    } else if (code == Bytecodes::_invokeinterface && callee_holder->is_loaded() && receiver != nullptr) {
      assert(callee_holder->is_interface(), "invokeinterface to non interface?");
      // If there is only one implementor of this interface then we
      // may be able bind this invoke directly to the implementing
      // klass but we need both a dependence on the single interface
      // and on the method we bind to.  Additionally since all we know
      // about the receiver type is the it's supposed to implement the
      // interface we have to insert a check that it's the class we
      // expect.  Interface types are not checked by the verifier so
      // they are roughly equivalent to Object.
      // The number of implementors for declared_interface is less or
      // equal to the number of implementors for target->holder() so
      // if number of implementors of target->holder() == 1 then
      // number of implementors for decl_interface is 0 or 1. If
      // it's 0 then no class implements decl_interface and there's
      // no point in inlining.
      ciInstanceKlass* declared_interface = callee_holder;
      ciInstanceKlass* singleton = declared_interface->unique_implementor();
      if (singleton != nullptr) {
        assert(singleton != declared_interface, "not a unique implementor");
        cha_monomorphic_target = target->find_monomorphic_target(calling_klass, declared_interface, singleton);
        if (cha_monomorphic_target != nullptr) {
          ciInstanceKlass* holder = cha_monomorphic_target->holder();
          ciInstanceKlass* constraint = (holder->is_subtype_of(singleton) ? holder : singleton); // avoid upcasts
          if (holder != compilation()->env()->Object_klass() &&
              (!type_is_exact || receiver_klass->is_subtype_of(constraint))) {
            actual_recv = declared_interface;

            // insert a check it's really the expected class.
            CheckCast* c = new CheckCast(constraint, receiver, copy_state_for_exception());
            c->set_incompatible_class_change_check();
            c->set_direct_compare(constraint->is_final());
            // pass the result of the checkcast so that the compiler has
            // more accurate type info in the inlinee
            better_receiver = append_split(c);

            dependency_recorder()->assert_unique_implementor(declared_interface, singleton);
          } else {
            cha_monomorphic_target = nullptr;
          }
        }
      }
    }
  }

  if (cha_monomorphic_target != nullptr) {
    assert(!target->can_be_statically_bound() || target == cha_monomorphic_target, "");
    assert(!cha_monomorphic_target->is_abstract(), "");
    if (!cha_monomorphic_target->can_be_statically_bound(actual_recv)) {
      // If we inlined because CHA revealed only a single target method,
      // then we are dependent on that target method not getting overridden
      // by dynamic class loading.  Be sure to test the "static" receiver
      // dest_method here, as opposed to the actual receiver, which may
      // falsely lead us to believe that the receiver is final or private.
      dependency_recorder()->assert_unique_concrete_method(actual_recv, cha_monomorphic_target, callee_holder, target);
    }
    code = Bytecodes::_invokespecial;
  }

  // check if we could do inlining
  if (!PatchALot && Inline && target->is_loaded() && !patch_for_appendix &&
      callee_holder->is_loaded()) { // the effect of symbolic reference resolution

    // callee is known => check if we have static binding
    if ((code == Bytecodes::_invokestatic && klass->is_initialized()) || // invokestatic involves an initialization barrier on declaring class
        code == Bytecodes::_invokespecial ||
        (code == Bytecodes::_invokevirtual && target->is_final_method()) ||
        code == Bytecodes::_invokedynamic) {
      // static binding => check if callee is ok
      ciMethod* inline_target = (cha_monomorphic_target != nullptr) ? cha_monomorphic_target : target;
      bool holder_known = (cha_monomorphic_target != nullptr) || (exact_target != nullptr);
      bool success = try_inline(inline_target, holder_known, false /* ignore_return */, code, better_receiver);

      CHECK_BAILOUT();
      clear_inline_bailout();

      if (success) {
        // Register dependence if JVMTI has either breakpoint
        // setting or hotswapping of methods capabilities since they may
        // cause deoptimization.
        if (compilation()->env()->jvmti_can_hotswap_or_post_breakpoint()) {
          dependency_recorder()->assert_evol_method(inline_target);
        }
        return;
      }
    } else {
      print_inlining(target, "no static binding", /*success*/ false);
    }
  } else {
    print_inlining(target, "not inlineable", /*success*/ false);
  }

  // If we attempted an inline which did not succeed because of a
  // bailout during construction of the callee graph, the entire
  // compilation has to be aborted. This is fairly rare and currently
  // seems to only occur for jasm-generated classes which contain
  // jsr/ret pairs which are not associated with finally clauses and
  // do not have exception handlers in the containing method, and are
  // therefore not caught early enough to abort the inlining without
  // corrupting the graph. (We currently bail out with a non-empty
  // stack at a ret in these situations.)
  CHECK_BAILOUT();

  // inlining not successful => standard invoke
  ValueType* result_type = as_ValueType(declared_signature->return_type());
  ValueStack* state_before = copy_state_exhandling();

  // The bytecode (code) might change in this method so we are checking this very late.
  const bool has_receiver =
    code == Bytecodes::_invokespecial   ||
    code == Bytecodes::_invokevirtual   ||
    code == Bytecodes::_invokeinterface;
  Values* args = state()->pop_arguments(target->arg_size_no_receiver() + patching_appendix_arg);
  Value recv = has_receiver ? apop() : nullptr;

  // A null check is required here (when there is a receiver) for any of the following cases
  // - invokespecial, always need a null check.
  // - invokevirtual, when the target is final and loaded. Calls to final targets will become optimized
  //   and require null checking. If the target is loaded a null check is emitted here.
  //   If the target isn't loaded the null check must happen after the call resolution. We achieve that
  //   by using the target methods unverified entry point (see CompiledIC::compute_monomorphic_entry).
  //   (The JVM specification requires that LinkageError must be thrown before a NPE. An unloaded target may
  //   potentially fail, and can't have the null check before the resolution.)
  // - A call that will be profiled. (But we can't add a null check when the target is unloaded, by the same
  //   reason as above, so calls with a receiver to unloaded targets can't be profiled.)
  //
  // Normal invokevirtual will perform the null check during lookup

  bool need_null_check = (code == Bytecodes::_invokespecial) ||
      (target->is_loaded() && (target->is_final_method() || (is_profiling() && profile_calls())));

  if (need_null_check) {
    if (recv != nullptr) {
      null_check(recv);
    }

    if (is_profiling()) {
      // Note that we'd collect profile data in this method if we wanted it.
      compilation()->set_would_profile(true);

      if (profile_calls()) {
        assert(cha_monomorphic_target == nullptr || exact_target == nullptr, "both can not be set");
        ciKlass* target_klass = nullptr;
        if (cha_monomorphic_target != nullptr) {
          target_klass = cha_monomorphic_target->holder();
        } else if (exact_target != nullptr) {
          target_klass = exact_target->holder();
        }
        profile_call(target, recv, target_klass, collect_args_for_profiling(args, nullptr, false), false);
      }
    }
  }

  Invoke* result = new Invoke(code, result_type, recv, args, target, state_before);
  // push result
  append_split(result);

  if (result_type != voidType) {
    push(result_type, result);
  }
  if (profile_return() && result_type->is_object_kind()) {
    profile_return_type(result, target);
  }
}


void GraphBuilder::new_instance(int klass_index) {
  ValueStack* state_before = copy_state_exhandling();
  ciKlass* klass = stream()->get_klass();
  assert(klass->is_instance_klass(), "must be an instance klass");
  NewInstance* new_instance = new NewInstance(klass->as_instance_klass(), state_before, stream()->is_unresolved_klass());
  _memory->new_instance(new_instance);
  apush(append_split(new_instance));
}


void GraphBuilder::new_type_array() {
  ValueStack* state_before = copy_state_exhandling();
  apush(append_split(new NewTypeArray(ipop(), (BasicType)stream()->get_index(), state_before, true)));
}


void GraphBuilder::new_object_array() {
  ciKlass* klass = stream()->get_klass();
  ValueStack* state_before = !klass->is_loaded() || PatchALot ? copy_state_before() : copy_state_exhandling();
  NewArray* n = new NewObjectArray(klass, ipop(), state_before);
  apush(append_split(n));
}


bool GraphBuilder::direct_compare(ciKlass* k) {
  if (k->is_loaded() && k->is_instance_klass() && !UseSlowPath) {
    ciInstanceKlass* ik = k->as_instance_klass();
    if (ik->is_final()) {
      return true;
    } else {
      if (DeoptC1 && UseCHA && !(ik->has_subklass() || ik->is_interface())) {
        // test class is leaf class
        dependency_recorder()->assert_leaf_type(ik);
        return true;
      }
    }
  }
  return false;
}


void GraphBuilder::check_cast(int klass_index) {
  ciKlass* klass = stream()->get_klass();
  ValueStack* state_before = !klass->is_loaded() || PatchALot ? copy_state_before() : copy_state_for_exception();
  CheckCast* c = new CheckCast(klass, apop(), state_before);
  apush(append_split(c));
  c->set_direct_compare(direct_compare(klass));

  if (is_profiling()) {
    // Note that we'd collect profile data in this method if we wanted it.
    compilation()->set_would_profile(true);

    if (profile_checkcasts()) {
      c->set_profiled_method(method());
      c->set_profiled_bci(bci());
      c->set_should_profile(true);
    }
  }
}


void GraphBuilder::instance_of(int klass_index) {
  ciKlass* klass = stream()->get_klass();
  ValueStack* state_before = !klass->is_loaded() || PatchALot ? copy_state_before() : copy_state_exhandling();
  InstanceOf* i = new InstanceOf(klass, apop(), state_before);
  ipush(append_split(i));
  i->set_direct_compare(direct_compare(klass));

  if (is_profiling()) {
    // Note that we'd collect profile data in this method if we wanted it.
    compilation()->set_would_profile(true);

    if (profile_checkcasts()) {
      i->set_profiled_method(method());
      i->set_profiled_bci(bci());
      i->set_should_profile(true);
    }
  }
}


void GraphBuilder::monitorenter(Value x, int bci) {
  // save state before locking in case of deoptimization after a NullPointerException
  ValueStack* state_before = copy_state_for_exception_with_bci(bci);
  append_with_bci(new MonitorEnter(x, state()->lock(x), state_before), bci);
  kill_all();
}


void GraphBuilder::monitorexit(Value x, int bci) {
  append_with_bci(new MonitorExit(x, state()->unlock()), bci);
  kill_all();
}


void GraphBuilder::new_multi_array(int dimensions) {
  ciKlass* klass = stream()->get_klass();
  ValueStack* state_before = !klass->is_loaded() || PatchALot ? copy_state_before() : copy_state_exhandling();

  Values* dims = new Values(dimensions, dimensions, nullptr);
  // fill in all dimensions
  int i = dimensions;
  while (i-- > 0) dims->at_put(i, ipop());
  // create array
  NewArray* n = new NewMultiArray(klass, dims, state_before);
  apush(append_split(n));
}


void GraphBuilder::throw_op(int bci) {
  // We require that the debug info for a Throw be the "state before"
  // the Throw (i.e., exception oop is still on TOS)
  ValueStack* state_before = copy_state_before_with_bci(bci);
  Throw* t = new Throw(apop(), state_before);
  // operand stack not needed after a throw
  state()->truncate_stack(0);
  append_with_bci(t, bci);
}


Instruction* GraphBuilder::append_with_bci(Instruction* instr, int bci) {
  Canonicalizer canon(compilation(), instr, bci);
  Instruction* i1 = canon.canonical();
  if (i1->is_linked() || !i1->can_be_linked()) {
    // Canonicalizer returned an instruction which was already
    // appended so simply return it.
    return i1;
  }

  if (UseLocalValueNumbering) {
    // Lookup the instruction in the ValueMap and add it to the map if
    // it's not found.
    Instruction* i2 = vmap()->find_insert(i1);
    if (i2 != i1) {
      // found an entry in the value map, so just return it.
      assert(i2->is_linked(), "should already be linked");
      return i2;
    }
    ValueNumberingEffects vne(vmap());
    i1->visit(&vne);
  }

  // i1 was not eliminated => append it
  assert(i1->next() == nullptr, "shouldn't already be linked");
  _last = _last->set_next(i1, canon.bci());

  if (++_instruction_count >= InstructionCountCutoff && !bailed_out()) {
    // set the bailout state but complete normal processing.  We
    // might do a little more work before noticing the bailout so we
    // want processing to continue normally until it's noticed.
    bailout("Method and/or inlining is too large");
  }

#ifndef PRODUCT
  if (PrintIRDuringConstruction) {
    InstructionPrinter ip;
    ip.print_line(i1);
    if (Verbose) {
      state()->print();
    }
  }
#endif

  // save state after modification of operand stack for StateSplit instructions
  StateSplit* s = i1->as_StateSplit();
  if (s != nullptr) {
    if (EliminateFieldAccess) {
      Intrinsic* intrinsic = s->as_Intrinsic();
      if (s->as_Invoke() != nullptr || (intrinsic && !intrinsic->preserves_state())) {
        _memory->kill();
      }
    }
    s->set_state(state()->copy(ValueStack::StateAfter, canon.bci()));
  }

  // set up exception handlers for this instruction if necessary
  if (i1->can_trap()) {
    i1->set_exception_handlers(handle_exception(i1));
    assert(i1->exception_state() != nullptr || !i1->needs_exception_state() || bailed_out(), "handle_exception must set exception state");
  }
  return i1;
}


Instruction* GraphBuilder::append(Instruction* instr) {
  assert(instr->as_StateSplit() == nullptr || instr->as_BlockEnd() != nullptr, "wrong append used");
  return append_with_bci(instr, bci());
}


Instruction* GraphBuilder::append_split(StateSplit* instr) {
  return append_with_bci(instr, bci());
}


void GraphBuilder::null_check(Value value) {
  if (value->as_NewArray() != nullptr || value->as_NewInstance() != nullptr) {
    return;
  } else {
    Constant* con = value->as_Constant();
    if (con) {
      ObjectType* c = con->type()->as_ObjectType();
      if (c && c->is_loaded()) {
        ObjectConstant* oc = c->as_ObjectConstant();
        if (!oc || !oc->value()->is_null_object()) {
          return;
        }
      }
    }
  }
  append(new NullCheck(value, copy_state_for_exception()));
}



XHandlers* GraphBuilder::handle_exception(Instruction* instruction) {
  if (!has_handler() && (!instruction->needs_exception_state() || instruction->exception_state() != nullptr)) {
    assert(instruction->exception_state() == nullptr
           || instruction->exception_state()->kind() == ValueStack::EmptyExceptionState
           || (instruction->exception_state()->kind() == ValueStack::ExceptionState && _compilation->env()->should_retain_local_variables()),
           "exception_state should be of exception kind");
    return new XHandlers();
  }

  XHandlers*  exception_handlers = new XHandlers();
  ScopeData*  cur_scope_data = scope_data();
  ValueStack* cur_state = instruction->state_before();
  ValueStack* prev_state = nullptr;
  int scope_count = 0;

  assert(cur_state != nullptr, "state_before must be set");
  do {
    int cur_bci = cur_state->bci();
    assert(cur_scope_data->scope() == cur_state->scope(), "scopes do not match");
    assert(cur_bci == SynchronizationEntryBCI || cur_bci == cur_scope_data->stream()->cur_bci(), "invalid bci");

    // join with all potential exception handlers
    XHandlers* list = cur_scope_data->xhandlers();
    const int n = list->length();
    for (int i = 0; i < n; i++) {
      XHandler* h = list->handler_at(i);
      if (h->covers(cur_bci)) {
        // h is a potential exception handler => join it
        compilation()->set_has_exception_handlers(true);

        BlockBegin* entry = h->entry_block();
        if (entry == block()) {
          // It's acceptable for an exception handler to cover itself
          // but we don't handle that in the parser currently.  It's
          // very rare so we bailout instead of trying to handle it.
          BAILOUT_("exception handler covers itself", exception_handlers);
        }
        assert(entry->bci() == h->handler_bci(), "must match");
        assert(entry->bci() == -1 || entry == cur_scope_data->block_at(entry->bci()), "blocks must correspond");

        // previously this was a BAILOUT, but this is not necessary
        // now because asynchronous exceptions are not handled this way.
        assert(entry->state() == nullptr || cur_state->total_locks_size() == entry->state()->total_locks_size(), "locks do not match");

        // xhandler start with an empty expression stack
        if (cur_state->stack_size() != 0) {
          // locals are preserved
          // stack will be truncated
          cur_state = cur_state->copy(ValueStack::ExceptionState, cur_state->bci());
        }
        if (instruction->exception_state() == nullptr) {
          instruction->set_exception_state(cur_state);
        }

        // Note: Usually this join must work. However, very
        // complicated jsr-ret structures where we don't ret from
        // the subroutine can cause the objects on the monitor
        // stacks to not match because blocks can be parsed twice.
        // The only test case we've seen so far which exhibits this
        // problem is caught by the infinite recursion test in
        // GraphBuilder::jsr() if the join doesn't work.
        if (!entry->try_merge(cur_state, compilation()->has_irreducible_loops())) {
          BAILOUT_("error while joining with exception handler, prob. due to complicated jsr/rets", exception_handlers);
        }

        // add current state for correct handling of phi functions at begin of xhandler
        int phi_operand = entry->add_exception_state(cur_state);

        // add entry to the list of xhandlers of this block
        _block->add_exception_handler(entry);

        // add back-edge from xhandler entry to this block
        if (!entry->is_predecessor(_block)) {
          entry->add_predecessor(_block);
        }

        // clone XHandler because phi_operand and scope_count can not be shared
        XHandler* new_xhandler = new XHandler(h);
        new_xhandler->set_phi_operand(phi_operand);
        new_xhandler->set_scope_count(scope_count);
        exception_handlers->append(new_xhandler);

        // fill in exception handler subgraph lazily
        assert(!entry->is_set(BlockBegin::was_visited_flag), "entry must not be visited yet");
        cur_scope_data->add_to_work_list(entry);

        // stop when reaching catchall
        if (h->catch_type() == 0) {
          return exception_handlers;
        }
      }
    }

    if (exception_handlers->length() == 0) {
      // This scope and all callees do not handle exceptions, so the local
      // variables of this scope are not needed. However, the scope itself is
      // required for a correct exception stack trace -> clear out the locals.
      // Stack and locals are invalidated but not truncated in caller state.
      if (prev_state != nullptr) {
        assert(instruction->exception_state() != nullptr, "missed set?");
        ValueStack::Kind exc_kind = ValueStack::empty_exception_kind(true /* caller */);
        cur_state = cur_state->copy(exc_kind, cur_state->bci());
        // reset caller exception state
        prev_state->set_caller_state(cur_state);
      } else {
        assert(instruction->exception_state() == nullptr, "already set");
        // set instruction exception state
        // truncate stack
        ValueStack::Kind exc_kind = ValueStack::empty_exception_kind();
        cur_state = cur_state->copy(exc_kind, cur_state->bci());
        instruction->set_exception_state(cur_state);
      }
    }

    // Set up iteration for next time.
    // If parsing a jsr, do not grab exception handlers from the
    // parent scopes for this method (already got them, and they
    // needed to be cloned)

    while (cur_scope_data->parsing_jsr()) {
      cur_scope_data = cur_scope_data->parent();
    }

    assert(cur_scope_data->scope() == cur_state->scope(), "scopes do not match");
    assert(cur_state->locks_size() == 0 || cur_state->locks_size() == 1, "unlocking must be done in a catchall exception handler");

    prev_state = cur_state;
    cur_state = cur_state->caller_state();
    cur_scope_data = cur_scope_data->parent();
    scope_count++;
  } while (cur_scope_data != nullptr);

  return exception_handlers;
}


// Helper class for simplifying Phis.
class PhiSimplifier : public BlockClosure {
 private:
  bool _has_substitutions;
  Value simplify(Value v);

 public:
  PhiSimplifier(BlockBegin* start) : _has_substitutions(false) {
    start->iterate_preorder(this);
    if (_has_substitutions) {
      SubstitutionResolver sr(start);
    }
  }
  void block_do(BlockBegin* b);
  bool has_substitutions() const { return _has_substitutions; }
};


Value PhiSimplifier::simplify(Value v) {
  Phi* phi = v->as_Phi();

  if (phi == nullptr) {
    // no phi function
    return v;
  } else if (v->has_subst()) {
    // already substituted; subst can be phi itself -> simplify
    return simplify(v->subst());
  } else if (phi->is_set(Phi::cannot_simplify)) {
    // already tried to simplify phi before
    return phi;
  } else if (phi->is_set(Phi::visited)) {
    // break cycles in phi functions
    return phi;
  } else if (phi->type()->is_illegal()) {
    // illegal phi functions are ignored anyway
    return phi;

  } else {
    // mark phi function as processed to break cycles in phi functions
    phi->set(Phi::visited);

    // simplify x = [y, x] and x = [y, y] to y
    Value subst = nullptr;
    int opd_count = phi->operand_count();
    for (int i = 0; i < opd_count; i++) {
      Value opd = phi->operand_at(i);
      assert(opd != nullptr, "Operand must exist!");

      if (opd->type()->is_illegal()) {
        // if one operand is illegal, the entire phi function is illegal
        phi->make_illegal();
        phi->clear(Phi::visited);
        return phi;
      }

      Value new_opd = simplify(opd);
      assert(new_opd != nullptr, "Simplified operand must exist!");

      if (new_opd != phi && new_opd != subst) {
        if (subst == nullptr) {
          subst = new_opd;
        } else {
          // no simplification possible
          phi->set(Phi::cannot_simplify);
          phi->clear(Phi::visited);
          return phi;
        }
      }
    }

    // successfully simplified phi function
    assert(subst != nullptr, "illegal phi function");
    _has_substitutions = true;
    phi->clear(Phi::visited);
    phi->set_subst(subst);

#ifndef PRODUCT
    if (PrintPhiFunctions) {
      tty->print_cr("simplified phi function %c%d to %c%d (Block B%d)", phi->type()->tchar(), phi->id(), subst->type()->tchar(), subst->id(), phi->block()->block_id());
    }
#endif

    return subst;
  }
}


void PhiSimplifier::block_do(BlockBegin* b) {
  for_each_phi_fun(b, phi,
    simplify(phi);
  );

#ifdef ASSERT
  for_each_phi_fun(b, phi,
                   assert(phi->operand_count() != 1 || phi->subst() != phi || phi->is_illegal(), "missed trivial simplification");
  );

  ValueStack* state = b->state()->caller_state();
  for_each_state_value(state, value,
    Phi* phi = value->as_Phi();
    assert(phi == nullptr || phi->block() != b, "must not have phi function to simplify in caller state");
  );
#endif
}

// This method is called after all blocks are filled with HIR instructions
// It eliminates all Phi functions of the form x = [y, y] and x = [y, x]
void GraphBuilder::eliminate_redundant_phis(BlockBegin* start) {
  PhiSimplifier simplifier(start);
}


void GraphBuilder::connect_to_end(BlockBegin* beg) {
  // setup iteration
  kill_all();
  _block = beg;
  _state = beg->state()->copy_for_parsing();
  _last  = beg;
  iterate_bytecodes_for_block(beg->bci());
}


BlockEnd* GraphBuilder::iterate_bytecodes_for_block(int bci) {
#ifndef PRODUCT
  if (PrintIRDuringConstruction) {
    tty->cr();
    InstructionPrinter ip;
    ip.print_instr(_block); tty->cr();
    ip.print_stack(_block->state()); tty->cr();
    ip.print_inline_level(_block);
    ip.print_head();
    tty->print_cr("locals size: %d stack size: %d", state()->locals_size(), state()->stack_size());
  }
#endif
  _skip_block = false;
  assert(state() != nullptr, "ValueStack missing!");
  CompileLog* log = compilation()->log();
  ciBytecodeStream s(method());
  s.reset_to_bci(bci);
  int prev_bci = bci;
  scope_data()->set_stream(&s);
  // iterate
  Bytecodes::Code code = Bytecodes::_illegal;
  bool push_exception = false;

  if (block()->is_set(BlockBegin::exception_entry_flag) && block()->next() == nullptr) {
    // first thing in the exception entry block should be the exception object.
    push_exception = true;
  }

  bool ignore_return = scope_data()->ignore_return();

  while (!bailed_out() && last()->as_BlockEnd() == nullptr &&
         (code = stream()->next()) != ciBytecodeStream::EOBC() &&
         (block_at(s.cur_bci()) == nullptr || block_at(s.cur_bci()) == block())) {
    assert(state()->kind() == ValueStack::Parsing, "invalid state kind");

    if (log != nullptr)
      log->set_context("bc code='%d' bci='%d'", (int)code, s.cur_bci());

    // Check for active jsr during OSR compilation
    if (compilation()->is_osr_compile()
        && scope()->is_top_scope()
        && parsing_jsr()
        && s.cur_bci() == compilation()->osr_bci()) {
      bailout("OSR not supported while a jsr is active");
    }

    if (push_exception) {
      apush(append(new ExceptionObject()));
      push_exception = false;
    }

    // handle bytecode
    switch (code) {
      case Bytecodes::_nop            : /* nothing to do */ break;
      case Bytecodes::_aconst_null    : apush(append(new Constant(objectNull            ))); break;
      case Bytecodes::_iconst_m1      : ipush(append(new Constant(new IntConstant   (-1)))); break;
      case Bytecodes::_iconst_0       : ipush(append(new Constant(intZero               ))); break;
      case Bytecodes::_iconst_1       : ipush(append(new Constant(intOne                ))); break;
      case Bytecodes::_iconst_2       : ipush(append(new Constant(new IntConstant   ( 2)))); break;
      case Bytecodes::_iconst_3       : ipush(append(new Constant(new IntConstant   ( 3)))); break;
      case Bytecodes::_iconst_4       : ipush(append(new Constant(new IntConstant   ( 4)))); break;
      case Bytecodes::_iconst_5       : ipush(append(new Constant(new IntConstant   ( 5)))); break;
      case Bytecodes::_lconst_0       : lpush(append(new Constant(new LongConstant  ( 0)))); break;
      case Bytecodes::_lconst_1       : lpush(append(new Constant(new LongConstant  ( 1)))); break;
      case Bytecodes::_fconst_0       : fpush(append(new Constant(new FloatConstant ( 0)))); break;
      case Bytecodes::_fconst_1       : fpush(append(new Constant(new FloatConstant ( 1)))); break;
      case Bytecodes::_fconst_2       : fpush(append(new Constant(new FloatConstant ( 2)))); break;
      case Bytecodes::_dconst_0       : dpush(append(new Constant(new DoubleConstant( 0)))); break;
      case Bytecodes::_dconst_1       : dpush(append(new Constant(new DoubleConstant( 1)))); break;
      case Bytecodes::_bipush         : ipush(append(new Constant(new IntConstant(((signed char*)s.cur_bcp())[1])))); break;
      case Bytecodes::_sipush         : ipush(append(new Constant(new IntConstant((short)Bytes::get_Java_u2(s.cur_bcp()+1))))); break;
      case Bytecodes::_ldc            : // fall through
      case Bytecodes::_ldc_w          : // fall through
      case Bytecodes::_ldc2_w         : load_constant(); break;
      case Bytecodes::_iload          : load_local(intType     , s.get_index()); break;
      case Bytecodes::_lload          : load_local(longType    , s.get_index()); break;
      case Bytecodes::_fload          : load_local(floatType   , s.get_index()); break;
      case Bytecodes::_dload          : load_local(doubleType  , s.get_index()); break;
      case Bytecodes::_aload          : load_local(instanceType, s.get_index()); break;
      case Bytecodes::_iload_0        : load_local(intType   , 0); break;
      case Bytecodes::_iload_1        : load_local(intType   , 1); break;
      case Bytecodes::_iload_2        : load_local(intType   , 2); break;
      case Bytecodes::_iload_3        : load_local(intType   , 3); break;
      case Bytecodes::_lload_0        : load_local(longType  , 0); break;
      case Bytecodes::_lload_1        : load_local(longType  , 1); break;
      case Bytecodes::_lload_2        : load_local(longType  , 2); break;
      case Bytecodes::_lload_3        : load_local(longType  , 3); break;
      case Bytecodes::_fload_0        : load_local(floatType , 0); break;
      case Bytecodes::_fload_1        : load_local(floatType , 1); break;
      case Bytecodes::_fload_2        : load_local(floatType , 2); break;
      case Bytecodes::_fload_3        : load_local(floatType , 3); break;
      case Bytecodes::_dload_0        : load_local(doubleType, 0); break;
      case Bytecodes::_dload_1        : load_local(doubleType, 1); break;
      case Bytecodes::_dload_2        : load_local(doubleType, 2); break;
      case Bytecodes::_dload_3        : load_local(doubleType, 3); break;
      case Bytecodes::_aload_0        : load_local(objectType, 0); break;
      case Bytecodes::_aload_1        : load_local(objectType, 1); break;
      case Bytecodes::_aload_2        : load_local(objectType, 2); break;
      case Bytecodes::_aload_3        : load_local(objectType, 3); break;
      case Bytecodes::_iaload         : load_indexed(T_INT   ); break;
      case Bytecodes::_laload         : load_indexed(T_LONG  ); break;
      case Bytecodes::_faload         : load_indexed(T_FLOAT ); break;
      case Bytecodes::_daload         : load_indexed(T_DOUBLE); break;
      case Bytecodes::_aaload         : load_indexed(T_OBJECT); break;
      case Bytecodes::_baload         : load_indexed(T_BYTE  ); break;
      case Bytecodes::_caload         : load_indexed(T_CHAR  ); break;
      case Bytecodes::_saload         : load_indexed(T_SHORT ); break;
      case Bytecodes::_istore         : store_local(intType   , s.get_index()); break;
      case Bytecodes::_lstore         : store_local(longType  , s.get_index()); break;
      case Bytecodes::_fstore         : store_local(floatType , s.get_index()); break;
      case Bytecodes::_dstore         : store_local(doubleType, s.get_index()); break;
      case Bytecodes::_astore         : store_local(objectType, s.get_index()); break;
      case Bytecodes::_istore_0       : store_local(intType   , 0); break;
      case Bytecodes::_istore_1       : store_local(intType   , 1); break;
      case Bytecodes::_istore_2       : store_local(intType   , 2); break;
      case Bytecodes::_istore_3       : store_local(intType   , 3); break;
      case Bytecodes::_lstore_0       : store_local(longType  , 0); break;
      case Bytecodes::_lstore_1       : store_local(longType  , 1); break;
      case Bytecodes::_lstore_2       : store_local(longType  , 2); break;
      case Bytecodes::_lstore_3       : store_local(longType  , 3); break;
      case Bytecodes::_fstore_0       : store_local(floatType , 0); break;
      case Bytecodes::_fstore_1       : store_local(floatType , 1); break;
      case Bytecodes::_fstore_2       : store_local(floatType , 2); break;
      case Bytecodes::_fstore_3       : store_local(floatType , 3); break;
      case Bytecodes::_dstore_0       : store_local(doubleType, 0); break;
      case Bytecodes::_dstore_1       : store_local(doubleType, 1); break;
      case Bytecodes::_dstore_2       : store_local(doubleType, 2); break;
      case Bytecodes::_dstore_3       : store_local(doubleType, 3); break;
      case Bytecodes::_astore_0       : store_local(objectType, 0); break;
      case Bytecodes::_astore_1       : store_local(objectType, 1); break;
      case Bytecodes::_astore_2       : store_local(objectType, 2); break;
      case Bytecodes::_astore_3       : store_local(objectType, 3); break;
      case Bytecodes::_iastore        : store_indexed(T_INT   ); break;
      case Bytecodes::_lastore        : store_indexed(T_LONG  ); break;
      case Bytecodes::_fastore        : store_indexed(T_FLOAT ); break;
      case Bytecodes::_dastore        : store_indexed(T_DOUBLE); break;
      case Bytecodes::_aastore        : store_indexed(T_OBJECT); break;
      case Bytecodes::_bastore        : store_indexed(T_BYTE  ); break;
      case Bytecodes::_castore        : store_indexed(T_CHAR  ); break;
      case Bytecodes::_sastore        : store_indexed(T_SHORT ); break;
      case Bytecodes::_pop            : // fall through
      case Bytecodes::_pop2           : // fall through
      case Bytecodes::_dup            : // fall through
      case Bytecodes::_dup_x1         : // fall through
      case Bytecodes::_dup_x2         : // fall through
      case Bytecodes::_dup2           : // fall through
      case Bytecodes::_dup2_x1        : // fall through
      case Bytecodes::_dup2_x2        : // fall through
      case Bytecodes::_swap           : stack_op(code); break;
      case Bytecodes::_iadd           : arithmetic_op(intType   , code); break;
      case Bytecodes::_ladd           : arithmetic_op(longType  , code); break;
      case Bytecodes::_fadd           : arithmetic_op(floatType , code); break;
      case Bytecodes::_dadd           : arithmetic_op(doubleType, code); break;
      case Bytecodes::_isub           : arithmetic_op(intType   , code); break;
      case Bytecodes::_lsub           : arithmetic_op(longType  , code); break;
      case Bytecodes::_fsub           : arithmetic_op(floatType , code); break;
      case Bytecodes::_dsub           : arithmetic_op(doubleType, code); break;
      case Bytecodes::_imul           : arithmetic_op(intType   , code); break;
      case Bytecodes::_lmul           : arithmetic_op(longType  , code); break;
      case Bytecodes::_fmul           : arithmetic_op(floatType , code); break;
      case Bytecodes::_dmul           : arithmetic_op(doubleType, code); break;
      case Bytecodes::_idiv           : arithmetic_op(intType   , code, copy_state_for_exception()); break;
      case Bytecodes::_ldiv           : arithmetic_op(longType  , code, copy_state_for_exception()); break;
      case Bytecodes::_fdiv           : arithmetic_op(floatType , code); break;
      case Bytecodes::_ddiv           : arithmetic_op(doubleType, code); break;
      case Bytecodes::_irem           : arithmetic_op(intType   , code, copy_state_for_exception()); break;
      case Bytecodes::_lrem           : arithmetic_op(longType  , code, copy_state_for_exception()); break;
      case Bytecodes::_frem           : arithmetic_op(floatType , code); break;
      case Bytecodes::_drem           : arithmetic_op(doubleType, code); break;
      case Bytecodes::_ineg           : negate_op(intType   ); break;
      case Bytecodes::_lneg           : negate_op(longType  ); break;
      case Bytecodes::_fneg           : negate_op(floatType ); break;
      case Bytecodes::_dneg           : negate_op(doubleType); break;
      case Bytecodes::_ishl           : shift_op(intType , code); break;
      case Bytecodes::_lshl           : shift_op(longType, code); break;
      case Bytecodes::_ishr           : shift_op(intType , code); break;
      case Bytecodes::_lshr           : shift_op(longType, code); break;
      case Bytecodes::_iushr          : shift_op(intType , code); break;
      case Bytecodes::_lushr          : shift_op(longType, code); break;
      case Bytecodes::_iand           : logic_op(intType , code); break;
      case Bytecodes::_land           : logic_op(longType, code); break;
      case Bytecodes::_ior            : logic_op(intType , code); break;
      case Bytecodes::_lor            : logic_op(longType, code); break;
      case Bytecodes::_ixor           : logic_op(intType , code); break;
      case Bytecodes::_lxor           : logic_op(longType, code); break;
      case Bytecodes::_iinc           : increment(); break;
      case Bytecodes::_i2l            : convert(code, T_INT   , T_LONG  ); break;
      case Bytecodes::_i2f            : convert(code, T_INT   , T_FLOAT ); break;
      case Bytecodes::_i2d            : convert(code, T_INT   , T_DOUBLE); break;
      case Bytecodes::_l2i            : convert(code, T_LONG  , T_INT   ); break;
      case Bytecodes::_l2f            : convert(code, T_LONG  , T_FLOAT ); break;
      case Bytecodes::_l2d            : convert(code, T_LONG  , T_DOUBLE); break;
      case Bytecodes::_f2i            : convert(code, T_FLOAT , T_INT   ); break;
      case Bytecodes::_f2l            : convert(code, T_FLOAT , T_LONG  ); break;
      case Bytecodes::_f2d            : convert(code, T_FLOAT , T_DOUBLE); break;
      case Bytecodes::_d2i            : convert(code, T_DOUBLE, T_INT   ); break;
      case Bytecodes::_d2l            : convert(code, T_DOUBLE, T_LONG  ); break;
      case Bytecodes::_d2f            : convert(code, T_DOUBLE, T_FLOAT ); break;
      case Bytecodes::_i2b            : convert(code, T_INT   , T_BYTE  ); break;
      case Bytecodes::_i2c            : convert(code, T_INT   , T_CHAR  ); break;
      case Bytecodes::_i2s            : convert(code, T_INT   , T_SHORT ); break;
      case Bytecodes::_lcmp           : compare_op(longType  , code); break;
      case Bytecodes::_fcmpl          : compare_op(floatType , code); break;
      case Bytecodes::_fcmpg          : compare_op(floatType , code); break;
      case Bytecodes::_dcmpl          : compare_op(doubleType, code); break;
      case Bytecodes::_dcmpg          : compare_op(doubleType, code); break;
      case Bytecodes::_ifeq           : if_zero(intType   , If::eql); break;
      case Bytecodes::_ifne           : if_zero(intType   , If::neq); break;
      case Bytecodes::_iflt           : if_zero(intType   , If::lss); break;
      case Bytecodes::_ifge           : if_zero(intType   , If::geq); break;
      case Bytecodes::_ifgt           : if_zero(intType   , If::gtr); break;
      case Bytecodes::_ifle           : if_zero(intType   , If::leq); break;
      case Bytecodes::_if_icmpeq      : if_same(intType   , If::eql); break;
      case Bytecodes::_if_icmpne      : if_same(intType   , If::neq); break;
      case Bytecodes::_if_icmplt      : if_same(intType   , If::lss); break;
      case Bytecodes::_if_icmpge      : if_same(intType   , If::geq); break;
      case Bytecodes::_if_icmpgt      : if_same(intType   , If::gtr); break;
      case Bytecodes::_if_icmple      : if_same(intType   , If::leq); break;
      case Bytecodes::_if_acmpeq      : if_same(objectType, If::eql); break;
      case Bytecodes::_if_acmpne      : if_same(objectType, If::neq); break;
      case Bytecodes::_goto           : _goto(s.cur_bci(), s.get_dest()); break;
      case Bytecodes::_jsr            : jsr(s.get_dest()); break;
      case Bytecodes::_ret            : ret(s.get_index()); break;
      case Bytecodes::_tableswitch    : table_switch(); break;
      case Bytecodes::_lookupswitch   : lookup_switch(); break;
      case Bytecodes::_ireturn        : method_return(ipop(), ignore_return); break;
      case Bytecodes::_lreturn        : method_return(lpop(), ignore_return); break;
      case Bytecodes::_freturn        : method_return(fpop(), ignore_return); break;
      case Bytecodes::_dreturn        : method_return(dpop(), ignore_return); break;
      case Bytecodes::_areturn        : method_return(apop(), ignore_return); break;
      case Bytecodes::_return         : method_return(nullptr, ignore_return); break;
      case Bytecodes::_getstatic      : // fall through
      case Bytecodes::_putstatic      : // fall through
      case Bytecodes::_getfield       : // fall through
      case Bytecodes::_putfield       : access_field(code); break;
      case Bytecodes::_invokevirtual  : // fall through
      case Bytecodes::_invokespecial  : // fall through
      case Bytecodes::_invokestatic   : // fall through
      case Bytecodes::_invokedynamic  : // fall through
      case Bytecodes::_invokeinterface: invoke(code); break;
      case Bytecodes::_new            : new_instance(s.get_index_u2()); break;
      case Bytecodes::_newarray       : new_type_array(); break;
      case Bytecodes::_anewarray      : new_object_array(); break;
      case Bytecodes::_arraylength    : { ValueStack* state_before = copy_state_for_exception(); ipush(append(new ArrayLength(apop(), state_before))); break; }
      case Bytecodes::_athrow         : throw_op(s.cur_bci()); break;
      case Bytecodes::_checkcast      : check_cast(s.get_index_u2()); break;
      case Bytecodes::_instanceof     : instance_of(s.get_index_u2()); break;
      case Bytecodes::_monitorenter   : monitorenter(apop(), s.cur_bci()); break;
      case Bytecodes::_monitorexit    : monitorexit (apop(), s.cur_bci()); break;
      case Bytecodes::_wide           : ShouldNotReachHere(); break;
      case Bytecodes::_multianewarray : new_multi_array(s.cur_bcp()[3]); break;
      case Bytecodes::_ifnull         : if_null(objectType, If::eql); break;
      case Bytecodes::_ifnonnull      : if_null(objectType, If::neq); break;
      case Bytecodes::_goto_w         : _goto(s.cur_bci(), s.get_far_dest()); break;
      case Bytecodes::_jsr_w          : jsr(s.get_far_dest()); break;
      case Bytecodes::_breakpoint     : BAILOUT_("concurrent setting of breakpoint", nullptr);
      default                         : ShouldNotReachHere(); break;
    }

    if (log != nullptr)
      log->clear_context(); // skip marker if nothing was printed

    // save current bci to setup Goto at the end
    prev_bci = s.cur_bci();

  }
  CHECK_BAILOUT_(nullptr);
  // stop processing of this block (see try_inline_full)
  if (_skip_block) {
    _skip_block = false;
    assert(_last && _last->as_BlockEnd(), "");
    return _last->as_BlockEnd();
  }
  // if there are any, check if last instruction is a BlockEnd instruction
  BlockEnd* end = last()->as_BlockEnd();
  if (end == nullptr) {
    // all blocks must end with a BlockEnd instruction => add a Goto
    end = new Goto(block_at(s.cur_bci()), false);
    append(end);
  }
  assert(end == last()->as_BlockEnd(), "inconsistency");

  assert(end->state() != nullptr, "state must already be present");
  assert(end->as_Return() == nullptr || end->as_Throw() == nullptr || end->state()->stack_size() == 0, "stack not needed for return and throw");

  // connect to begin & set state
  // NOTE that inlining may have changed the block we are parsing
  block()->set_end(end);
  // propagate state
  for (int i = end->number_of_sux() - 1; i >= 0; i--) {
    BlockBegin* sux = end->sux_at(i);
    assert(sux->is_predecessor(block()), "predecessor missing");
    // be careful, bailout if bytecodes are strange
    if (!sux->try_merge(end->state(), compilation()->has_irreducible_loops())) BAILOUT_("block join failed", nullptr);
    scope_data()->add_to_work_list(end->sux_at(i));
  }

  scope_data()->set_stream(nullptr);

  // done
  return end;
}


void GraphBuilder::iterate_all_blocks(bool start_in_current_block_for_inlining) {
  do {
    if (start_in_current_block_for_inlining && !bailed_out()) {
      iterate_bytecodes_for_block(0);
      start_in_current_block_for_inlining = false;
    } else {
      BlockBegin* b;
      while ((b = scope_data()->remove_from_work_list()) != nullptr) {
        if (!b->is_set(BlockBegin::was_visited_flag)) {
          if (b->is_set(BlockBegin::osr_entry_flag)) {
            // we're about to parse the osr entry block, so make sure
            // we setup the OSR edge leading into this block so that
            // Phis get setup correctly.
            setup_osr_entry_block();
            // this is no longer the osr entry block, so clear it.
            b->clear(BlockBegin::osr_entry_flag);
          }
          b->set(BlockBegin::was_visited_flag);
          connect_to_end(b);
        }
      }
    }
  } while (!bailed_out() && !scope_data()->is_work_list_empty());
}


bool GraphBuilder::_can_trap      [Bytecodes::number_of_java_codes];

void GraphBuilder::initialize() {
  // the following bytecodes are assumed to potentially
  // throw exceptions in compiled code - note that e.g.
  // monitorexit & the return bytecodes do not throw
  // exceptions since monitor pairing proved that they
  // succeed (if monitor pairing succeeded)
  Bytecodes::Code can_trap_list[] =
    { Bytecodes::_ldc
    , Bytecodes::_ldc_w
    , Bytecodes::_ldc2_w
    , Bytecodes::_iaload
    , Bytecodes::_laload
    , Bytecodes::_faload
    , Bytecodes::_daload
    , Bytecodes::_aaload
    , Bytecodes::_baload
    , Bytecodes::_caload
    , Bytecodes::_saload
    , Bytecodes::_iastore
    , Bytecodes::_lastore
    , Bytecodes::_fastore
    , Bytecodes::_dastore
    , Bytecodes::_aastore
    , Bytecodes::_bastore
    , Bytecodes::_castore
    , Bytecodes::_sastore
    , Bytecodes::_idiv
    , Bytecodes::_ldiv
    , Bytecodes::_irem
    , Bytecodes::_lrem
    , Bytecodes::_getstatic
    , Bytecodes::_putstatic
    , Bytecodes::_getfield
    , Bytecodes::_putfield
    , Bytecodes::_invokevirtual
    , Bytecodes::_invokespecial
    , Bytecodes::_invokestatic
    , Bytecodes::_invokedynamic
    , Bytecodes::_invokeinterface
    , Bytecodes::_new
    , Bytecodes::_newarray
    , Bytecodes::_anewarray
    , Bytecodes::_arraylength
    , Bytecodes::_athrow
    , Bytecodes::_checkcast
    , Bytecodes::_instanceof
    , Bytecodes::_monitorenter
    , Bytecodes::_multianewarray
    };

  // inititialize trap tables
  for (int i = 0; i < Bytecodes::number_of_java_codes; i++) {
    _can_trap[i] = false;
  }
  // set standard trap info
  for (uint j = 0; j < ARRAY_SIZE(can_trap_list); j++) {
    _can_trap[can_trap_list[j]] = true;
  }
}


BlockBegin* GraphBuilder::header_block(BlockBegin* entry, BlockBegin::Flag f, ValueStack* state) {
  assert(entry->is_set(f), "entry/flag mismatch");
  // create header block
  BlockBegin* h = new BlockBegin(entry->bci());
  h->set_depth_first_number(0);

  Value l = h;
  BlockEnd* g = new Goto(entry, false);
  l->set_next(g, entry->bci());
  h->set_end(g);
  h->set(f);
  // setup header block end state
  ValueStack* s = state->copy(ValueStack::StateAfter, entry->bci()); // can use copy since stack is empty (=> no phis)
  assert(s->stack_is_empty(), "must have empty stack at entry point");
  g->set_state(s);
  return h;
}



BlockBegin* GraphBuilder::setup_start_block(int osr_bci, BlockBegin* std_entry, BlockBegin* osr_entry, ValueStack* state) {
  BlockBegin* start = new BlockBegin(0);

  // This code eliminates the empty start block at the beginning of
  // each method.  Previously, each method started with the
  // start-block created below, and this block was followed by the
  // header block that was always empty.  This header block is only
  // necessary if std_entry is also a backward branch target because
  // then phi functions may be necessary in the header block.  It's
  // also necessary when profiling so that there's a single block that
  // can increment the counters.
  // In addition, with range check elimination, we may need a valid block
  // that dominates all the rest to insert range predicates.
  BlockBegin* new_header_block;
  if (std_entry->number_of_preds() > 0 || is_profiling() || RangeCheckElimination) {
    new_header_block = header_block(std_entry, BlockBegin::std_entry_flag, state);
  } else {
    new_header_block = std_entry;
  }

  // setup start block (root for the IR graph)
  Base* base =
    new Base(
      new_header_block,
      osr_entry
    );
  start->set_next(base, 0);
  start->set_end(base);
  // create & setup state for start block
  start->set_state(state->copy(ValueStack::StateAfter, std_entry->bci()));
  base->set_state(state->copy(ValueStack::StateAfter, std_entry->bci()));

  if (base->std_entry()->state() == nullptr) {
    // setup states for header blocks
    base->std_entry()->merge(state, compilation()->has_irreducible_loops());
  }

  assert(base->std_entry()->state() != nullptr, "");
  return start;
}


void GraphBuilder::setup_osr_entry_block() {
  assert(compilation()->is_osr_compile(), "only for osrs");

  int osr_bci = compilation()->osr_bci();
  ciBytecodeStream s(method());
  s.reset_to_bci(osr_bci);
  s.next();
  scope_data()->set_stream(&s);

  // create a new block to be the osr setup code
  _osr_entry = new BlockBegin(osr_bci);
  _osr_entry->set(BlockBegin::osr_entry_flag);
  _osr_entry->set_depth_first_number(0);
  BlockBegin* target = bci2block()->at(osr_bci);
  assert(target != nullptr && target->is_set(BlockBegin::osr_entry_flag), "must be there");
  // the osr entry has no values for locals
  ValueStack* state = target->state()->copy();
  _osr_entry->set_state(state);

  kill_all();
  _block = _osr_entry;
  _state = _osr_entry->state()->copy();
  assert(_state->bci() == osr_bci, "mismatch");
  _last  = _osr_entry;
  Value e = append(new OsrEntry());
  e->set_needs_null_check(false);

  // OSR buffer is
  //
  // locals[nlocals-1..0]
  // monitors[number_of_locks-1..0]
  //
  // locals is a direct copy of the interpreter frame so in the osr buffer
  // so first slot in the local array is the last local from the interpreter
  // and last slot is local[0] (receiver) from the interpreter
  //
  // Similarly with locks. The first lock slot in the osr buffer is the nth lock
  // from the interpreter frame, the nth lock slot in the osr buffer is 0th lock
  // in the interpreter frame (the method lock if a sync method)

  // Initialize monitors in the compiled activation.

  int index;
  Value local;

  // find all the locals that the interpreter thinks contain live oops
  const ResourceBitMap live_oops = method()->live_local_oops_at_bci(osr_bci);

  // compute the offset into the locals so that we can treat the buffer
  // as if the locals were still in the interpreter frame
  int locals_offset = BytesPerWord * (method()->max_locals() - 1);
  for_each_local_value(state, index, local) {
    int offset = locals_offset - (index + local->type()->size() - 1) * BytesPerWord;
    Value get;
    if (local->type()->is_object_kind() && !live_oops.at(index)) {
      // The interpreter thinks this local is dead but the compiler
      // doesn't so pretend that the interpreter passed in null.
      get = append(new Constant(objectNull));
    } else {
      Value off_val = append(new Constant(new IntConstant(offset)));
      get = append(new UnsafeGet(as_BasicType(local->type()), e,
                                 off_val,
                                 false/*is_volatile*/,
                                 true/*is_raw*/));
    }
    _state->store_local(index, get);
  }

  // the storage for the OSR buffer is freed manually in the LIRGenerator.

  assert(state->caller_state() == nullptr, "should be top scope");
  state->clear_locals();
  Goto* g = new Goto(target, false);
  append(g);
  _osr_entry->set_end(g);
  target->merge(_osr_entry->end()->state(), compilation()->has_irreducible_loops());

  scope_data()->set_stream(nullptr);
}


ValueStack* GraphBuilder::state_at_entry() {
  ValueStack* state = new ValueStack(scope(), nullptr);

  // Set up locals for receiver
  int idx = 0;
  if (!method()->is_static()) {
    // we should always see the receiver
    state->store_local(idx, new Local(method()->holder(), objectType, idx, true));
    idx = 1;
  }

  // Set up locals for incoming arguments
  ciSignature* sig = method()->signature();
  for (int i = 0; i < sig->count(); i++) {
    ciType* type = sig->type_at(i);
    BasicType basic_type = type->basic_type();
    // don't allow T_ARRAY to propagate into locals types
    if (is_reference_type(basic_type)) basic_type = T_OBJECT;
    ValueType* vt = as_ValueType(basic_type);
    state->store_local(idx, new Local(type, vt, idx, false));
    idx += type->size();
  }

  // lock synchronized method
  if (method()->is_synchronized()) {
    state->lock(nullptr);
  }

  return state;
}


GraphBuilder::GraphBuilder(Compilation* compilation, IRScope* scope)
  : _scope_data(nullptr)
  , _compilation(compilation)
  , _memory(new MemoryBuffer())
  , _inline_bailout_msg(nullptr)
  , _instruction_count(0)
  , _osr_entry(nullptr)
{
  int osr_bci = compilation->osr_bci();

  // determine entry points and bci2block mapping
  BlockListBuilder blm(compilation, scope, osr_bci);
  CHECK_BAILOUT();

  BlockList* bci2block = blm.bci2block();
  BlockBegin* start_block = bci2block->at(0);

  push_root_scope(scope, bci2block, start_block);

  // setup state for std entry
  _initial_state = state_at_entry();
  start_block->merge(_initial_state, compilation->has_irreducible_loops());

  // End nulls still exist here

  // complete graph
  _vmap        = new ValueMap();
  switch (scope->method()->intrinsic_id()) {
  case vmIntrinsics::_dabs          : // fall through
  case vmIntrinsics::_dsqrt         : // fall through
  case vmIntrinsics::_dsqrt_strict  : // fall through
  case vmIntrinsics::_dsin          : // fall through
  case vmIntrinsics::_dcos          : // fall through
  case vmIntrinsics::_dtan          : // fall through
  case vmIntrinsics::_dtanh         : // fall through
  case vmIntrinsics::_dcbrt         : // fall through
  case vmIntrinsics::_dlog          : // fall through
  case vmIntrinsics::_dlog10        : // fall through
  case vmIntrinsics::_dexp          : // fall through
  case vmIntrinsics::_dpow          : // fall through
    {
      // Compiles where the root method is an intrinsic need a special
      // compilation environment because the bytecodes for the method
      // shouldn't be parsed during the compilation, only the special
      // Intrinsic node should be emitted.  If this isn't done the
      // code for the inlined version will be different than the root
      // compiled version which could lead to monotonicity problems on
      // intel.
      if (CheckIntrinsics && !scope->method()->intrinsic_candidate()) {
        BAILOUT("failed to inline intrinsic, method not annotated");
      }

      // Set up a stream so that appending instructions works properly.
      ciBytecodeStream s(scope->method());
      s.reset_to_bci(0);
      scope_data()->set_stream(&s);
      s.next();

      // setup the initial block state
      _block = start_block;
      _state = start_block->state()->copy_for_parsing();
      _last  = start_block;
      load_local(doubleType, 0);
      if (scope->method()->intrinsic_id() == vmIntrinsics::_dpow) {
        load_local(doubleType, 2);
      }

      // Emit the intrinsic node.
      bool result = try_inline_intrinsics(scope->method());
      if (!result) BAILOUT("failed to inline intrinsic");
      method_return(dpop());

      // connect the begin and end blocks and we're all done.
      BlockEnd* end = last()->as_BlockEnd();
      block()->set_end(end);
      break;
    }

  case vmIntrinsics::_Reference_get:
    {
      {
        // With java.lang.ref.reference.get() we must go through the
        // intrinsic - when G1 is enabled - even when get() is the root
        // method of the compile so that, if necessary, the value in
        // the referent field of the reference object gets recorded by
        // the pre-barrier code.
        // Specifically, if G1 is enabled, the value in the referent
        // field is recorded by the G1 SATB pre barrier. This will
        // result in the referent being marked live and the reference
        // object removed from the list of discovered references during
        // reference processing.
        if (CheckIntrinsics && !scope->method()->intrinsic_candidate()) {
          BAILOUT("failed to inline intrinsic, method not annotated");
        }

        // Also we need intrinsic to prevent commoning reads from this field
        // across safepoint since GC can change its value.

        // Set up a stream so that appending instructions works properly.
        ciBytecodeStream s(scope->method());
        s.reset_to_bci(0);
        scope_data()->set_stream(&s);
        s.next();

        // setup the initial block state
        _block = start_block;
        _state = start_block->state()->copy_for_parsing();
        _last  = start_block;
        load_local(objectType, 0);

        // Emit the intrinsic node.
        bool result = try_inline_intrinsics(scope->method());
        if (!result) BAILOUT("failed to inline intrinsic");
        method_return(apop());

        // connect the begin and end blocks and we're all done.
        BlockEnd* end = last()->as_BlockEnd();
        block()->set_end(end);
        break;
      }
      // Otherwise, fall thru
    }

  default:
    scope_data()->add_to_work_list(start_block);
    iterate_all_blocks();
    break;
  }
  CHECK_BAILOUT();

# ifdef ASSERT
  // For all blocks reachable from start_block: _end must be non-null
  {
    BlockList processed;
    BlockList to_go;
    to_go.append(start_block);
    while(to_go.length() > 0) {
      BlockBegin* current = to_go.pop();
      assert(current != nullptr, "Should not happen.");
      assert(current->end() != nullptr, "All blocks reachable from start_block should have end() != nullptr.");
      processed.append(current);
      for(int i = 0; i < current->number_of_sux(); i++) {
        BlockBegin* s = current->sux_at(i);
        if (!processed.contains(s)) {
          to_go.append(s);
        }
      }
    }
  }
#endif // ASSERT

  _start = setup_start_block(osr_bci, start_block, _osr_entry, _initial_state);

  eliminate_redundant_phis(_start);

  NOT_PRODUCT(if (PrintValueNumbering && Verbose) print_stats());
  // for osr compile, bailout if some requirements are not fulfilled
  if (osr_bci != -1) {
    BlockBegin* osr_block = blm.bci2block()->at(osr_bci);
    if (!osr_block->is_set(BlockBegin::was_visited_flag)) {
      BAILOUT("osr entry must have been visited for osr compile");
    }

    // check if osr entry point has empty stack - we cannot handle non-empty stacks at osr entry points
    if (!osr_block->state()->stack_is_empty()) {
      BAILOUT("stack not empty at OSR entry point");
    }
  }
#ifndef PRODUCT
  if (PrintCompilation && Verbose) tty->print_cr("Created %d Instructions", _instruction_count);
#endif
}


ValueStack* GraphBuilder::copy_state_before() {
  return copy_state_before_with_bci(bci());
}

ValueStack* GraphBuilder::copy_state_exhandling() {
  return copy_state_exhandling_with_bci(bci());
}

ValueStack* GraphBuilder::copy_state_for_exception() {
  return copy_state_for_exception_with_bci(bci());
}

ValueStack* GraphBuilder::copy_state_before_with_bci(int bci) {
  return state()->copy(ValueStack::StateBefore, bci);
}

ValueStack* GraphBuilder::copy_state_exhandling_with_bci(int bci) {
  if (!has_handler()) return nullptr;
  return state()->copy(ValueStack::StateBefore, bci);
}

ValueStack* GraphBuilder::copy_state_for_exception_with_bci(int bci) {
  ValueStack* s = copy_state_exhandling_with_bci(bci);
  if (s == nullptr) {
    // no handler, no need to retain locals
    ValueStack::Kind exc_kind = ValueStack::empty_exception_kind();
    s = state()->copy(exc_kind, bci);
  }
  return s;
}

int GraphBuilder::recursive_inline_level(ciMethod* cur_callee) const {
  int recur_level = 0;
  for (IRScope* s = scope(); s != nullptr; s = s->caller()) {
    if (s->method() == cur_callee) {
      ++recur_level;
    }
  }
  return recur_level;
}

static void set_flags_for_inlined_callee(Compilation* compilation, ciMethod* callee) {
  if (callee->has_reserved_stack_access()) {
    compilation->set_has_reserved_stack_access(true);
  }
  if (callee->is_synchronized() || callee->has_monitor_bytecodes()) {
    compilation->set_has_monitors(true);
  }
  if (callee->is_scoped()) {
    compilation->set_has_scoped_access(true);
  }
}

bool GraphBuilder::try_inline(ciMethod* callee, bool holder_known, bool ignore_return, Bytecodes::Code bc, Value receiver) {
  const char* msg = nullptr;

  // clear out any existing inline bailout condition
  clear_inline_bailout();

  // exclude methods we don't want to inline
  msg = should_not_inline(callee);
  if (msg != nullptr) {
    print_inlining(callee, msg, /*success*/ false);
    return false;
  }

  // method handle invokes
  if (callee->is_method_handle_intrinsic()) {
    if (try_method_handle_inline(callee, ignore_return)) {
      set_flags_for_inlined_callee(compilation(), callee);
      return true;
    }
    return false;
  }

  // handle intrinsics
  if (callee->intrinsic_id() != vmIntrinsics::_none &&
      callee->check_intrinsic_candidate()) {
    if (try_inline_intrinsics(callee, ignore_return)) {
      print_inlining(callee, "intrinsic");
      set_flags_for_inlined_callee(compilation(), callee);
      return true;
    }
    // try normal inlining
  }

  // certain methods cannot be parsed at all
  msg = check_can_parse(callee);
  if (msg != nullptr) {
    print_inlining(callee, msg, /*success*/ false);
    return false;
  }

  // If bytecode not set use the current one.
  if (bc == Bytecodes::_illegal) {
    bc = code();
  }
  if (try_inline_full(callee, holder_known, ignore_return, bc, receiver)) {
    set_flags_for_inlined_callee(compilation(), callee);
    return true;
  }

  // Entire compilation could fail during try_inline_full call.
  // In that case printing inlining decision info is useless.
  if (!bailed_out())
    print_inlining(callee, _inline_bailout_msg, /*success*/ false);

  return false;
}


const char* GraphBuilder::check_can_parse(ciMethod* callee) const {
  // Certain methods cannot be parsed at all:
  if ( callee->is_native())            return "native method";
  if ( callee->is_abstract())          return "abstract method";
  if (!callee->can_be_parsed())        return "cannot be parsed";
  return nullptr;
}

// negative filter: should callee NOT be inlined?  returns null, ok to inline, or rejection msg
const char* GraphBuilder::should_not_inline(ciMethod* callee) const {
  if ( compilation()->directive()->should_not_inline(callee)) return "disallowed by CompileCommand";
  if ( callee->dont_inline())          return "don't inline by annotation";
  return nullptr;
}

void GraphBuilder::build_graph_for_intrinsic(ciMethod* callee, bool ignore_return) {
  vmIntrinsics::ID id = callee->intrinsic_id();
  assert(id != vmIntrinsics::_none, "must be a VM intrinsic");

  // Some intrinsics need special IR nodes.
  switch(id) {
  case vmIntrinsics::_getReference           : append_unsafe_get(callee, T_OBJECT,  false); return;
  case vmIntrinsics::_getBoolean             : append_unsafe_get(callee, T_BOOLEAN, false); return;
  case vmIntrinsics::_getByte                : append_unsafe_get(callee, T_BYTE,    false); return;
  case vmIntrinsics::_getShort               : append_unsafe_get(callee, T_SHORT,   false); return;
  case vmIntrinsics::_getChar                : append_unsafe_get(callee, T_CHAR,    false); return;
  case vmIntrinsics::_getInt                 : append_unsafe_get(callee, T_INT,     false); return;
  case vmIntrinsics::_getLong                : append_unsafe_get(callee, T_LONG,    false); return;
  case vmIntrinsics::_getFloat               : append_unsafe_get(callee, T_FLOAT,   false); return;
  case vmIntrinsics::_getDouble              : append_unsafe_get(callee, T_DOUBLE,  false); return;
  case vmIntrinsics::_putReference           : append_unsafe_put(callee, T_OBJECT,  false); return;
  case vmIntrinsics::_putBoolean             : append_unsafe_put(callee, T_BOOLEAN, false); return;
  case vmIntrinsics::_putByte                : append_unsafe_put(callee, T_BYTE,    false); return;
  case vmIntrinsics::_putShort               : append_unsafe_put(callee, T_SHORT,   false); return;
  case vmIntrinsics::_putChar                : append_unsafe_put(callee, T_CHAR,    false); return;
  case vmIntrinsics::_putInt                 : append_unsafe_put(callee, T_INT,     false); return;
  case vmIntrinsics::_putLong                : append_unsafe_put(callee, T_LONG,    false); return;
  case vmIntrinsics::_putFloat               : append_unsafe_put(callee, T_FLOAT,   false); return;
  case vmIntrinsics::_putDouble              : append_unsafe_put(callee, T_DOUBLE,  false); return;
  case vmIntrinsics::_getShortUnaligned      : append_unsafe_get(callee, T_SHORT,   false); return;
  case vmIntrinsics::_getCharUnaligned       : append_unsafe_get(callee, T_CHAR,    false); return;
  case vmIntrinsics::_getIntUnaligned        : append_unsafe_get(callee, T_INT,     false); return;
  case vmIntrinsics::_getLongUnaligned       : append_unsafe_get(callee, T_LONG,    false); return;
  case vmIntrinsics::_putShortUnaligned      : append_unsafe_put(callee, T_SHORT,   false); return;
  case vmIntrinsics::_putCharUnaligned       : append_unsafe_put(callee, T_CHAR,    false); return;
  case vmIntrinsics::_putIntUnaligned        : append_unsafe_put(callee, T_INT,     false); return;
  case vmIntrinsics::_putLongUnaligned       : append_unsafe_put(callee, T_LONG,    false); return;
  case vmIntrinsics::_getReferenceVolatile   : append_unsafe_get(callee, T_OBJECT,  true); return;
  case vmIntrinsics::_getBooleanVolatile     : append_unsafe_get(callee, T_BOOLEAN, true); return;
  case vmIntrinsics::_getByteVolatile        : append_unsafe_get(callee, T_BYTE,    true); return;
  case vmIntrinsics::_getShortVolatile       : append_unsafe_get(callee, T_SHORT,   true); return;
  case vmIntrinsics::_getCharVolatile        : append_unsafe_get(callee, T_CHAR,    true); return;
  case vmIntrinsics::_getIntVolatile         : append_unsafe_get(callee, T_INT,     true); return;
  case vmIntrinsics::_getLongVolatile        : append_unsafe_get(callee, T_LONG,    true); return;
  case vmIntrinsics::_getFloatVolatile       : append_unsafe_get(callee, T_FLOAT,   true); return;
  case vmIntrinsics::_getDoubleVolatile      : append_unsafe_get(callee, T_DOUBLE,  true); return;
  case vmIntrinsics::_putReferenceVolatile   : append_unsafe_put(callee, T_OBJECT,  true); return;
  case vmIntrinsics::_putBooleanVolatile     : append_unsafe_put(callee, T_BOOLEAN, true); return;
  case vmIntrinsics::_putByteVolatile        : append_unsafe_put(callee, T_BYTE,    true); return;
  case vmIntrinsics::_putShortVolatile       : append_unsafe_put(callee, T_SHORT,   true); return;
  case vmIntrinsics::_putCharVolatile        : append_unsafe_put(callee, T_CHAR,    true); return;
  case vmIntrinsics::_putIntVolatile         : append_unsafe_put(callee, T_INT,     true); return;
  case vmIntrinsics::_putLongVolatile        : append_unsafe_put(callee, T_LONG,    true); return;
  case vmIntrinsics::_putFloatVolatile       : append_unsafe_put(callee, T_FLOAT,   true); return;
  case vmIntrinsics::_putDoubleVolatile      : append_unsafe_put(callee, T_DOUBLE,  true); return;
  case vmIntrinsics::_compareAndSetLong:
  case vmIntrinsics::_compareAndSetInt:
  case vmIntrinsics::_compareAndSetReference : append_unsafe_CAS(callee); return;
  case vmIntrinsics::_getAndAddInt:
  case vmIntrinsics::_getAndAddLong          : append_unsafe_get_and_set(callee, true); return;
  case vmIntrinsics::_getAndSetInt           :
  case vmIntrinsics::_getAndSetLong          :
  case vmIntrinsics::_getAndSetReference     : append_unsafe_get_and_set(callee, false); return;
  case vmIntrinsics::_getCharStringU         : append_char_access(callee, false); return;
  case vmIntrinsics::_putCharStringU         : append_char_access(callee, true); return;
  case vmIntrinsics::_clone                  : append_alloc_array_copy(callee); return;
  default:
    break;
  }
  if (_inline_bailout_msg != nullptr) {
    return;
  }

  // create intrinsic node
  const bool has_receiver = !callee->is_static();
  ValueType* result_type = as_ValueType(callee->return_type());
  ValueStack* state_before = copy_state_for_exception();

  Values* args = state()->pop_arguments(callee->arg_size());

  if (is_profiling()) {
    // Don't profile in the special case where the root method
    // is the intrinsic
    if (callee != method()) {
      // Note that we'd collect profile data in this method if we wanted it.
      compilation()->set_would_profile(true);
      if (profile_calls()) {
        Value recv = nullptr;
        if (has_receiver) {
          recv = args->at(0);
          null_check(recv);
        }
        profile_call(callee, recv, nullptr, collect_args_for_profiling(args, callee, true), true);
      }
    }
  }

  Intrinsic* result = new Intrinsic(result_type, callee->intrinsic_id(),
                                    args, has_receiver, state_before,
                                    vmIntrinsics::preserves_state(id),
                                    vmIntrinsics::can_trap(id));
  // append instruction & push result
  Value value = append_split(result);
  if (result_type != voidType && !ignore_return) {
    push(result_type, value);
  }

  if (callee != method() && profile_return() && result_type->is_object_kind()) {
    profile_return_type(result, callee);
  }
}

bool GraphBuilder::try_inline_intrinsics(ciMethod* callee, bool ignore_return) {
  // For calling is_intrinsic_available we need to transition to
  // the '_thread_in_vm' state because is_intrinsic_available()
  // accesses critical VM-internal data.
  bool is_available = false;
  {
    VM_ENTRY_MARK;
    methodHandle mh(THREAD, callee->get_Method());
    is_available = _compilation->compiler()->is_intrinsic_available(mh, _compilation->directive());
  }

  if (!is_available) {
    if (!InlineNatives) {
      // Return false and also set message that the inlining of
      // intrinsics has been disabled in general.
      INLINE_BAILOUT("intrinsic method inlining disabled");
    } else {
      return false;
    }
  }
  build_graph_for_intrinsic(callee, ignore_return);
  if (_inline_bailout_msg != nullptr) {
    return false;
  }
  return true;
}


bool GraphBuilder::try_inline_jsr(int jsr_dest_bci) {
  // Introduce a new callee continuation point - all Ret instructions
  // will be replaced with Gotos to this point.
  if (next_bci() >= method()->code_size()) {
    return false;
  }
  BlockBegin* cont = block_at(next_bci());
  assert(cont != nullptr, "continuation must exist (BlockListBuilder starts a new block after a jsr");

  // Note: can not assign state to continuation yet, as we have to
  // pick up the state from the Ret instructions.

  // Push callee scope
  push_scope_for_jsr(cont, jsr_dest_bci);

  // Temporarily set up bytecode stream so we can append instructions
  // (only using the bci of this stream)
  scope_data()->set_stream(scope_data()->parent()->stream());

  BlockBegin* jsr_start_block = block_at(jsr_dest_bci);
  assert(jsr_start_block != nullptr, "jsr start block must exist");
  assert(!jsr_start_block->is_set(BlockBegin::was_visited_flag), "should not have visited jsr yet");
  Goto* goto_sub = new Goto(jsr_start_block, false);
  // Must copy state to avoid wrong sharing when parsing bytecodes
  assert(jsr_start_block->state() == nullptr, "should have fresh jsr starting block");
  jsr_start_block->set_state(copy_state_before_with_bci(jsr_dest_bci));
  append(goto_sub);
  _block->set_end(goto_sub);
  _last = _block = jsr_start_block;

  // Clear out bytecode stream
  scope_data()->set_stream(nullptr);

  scope_data()->add_to_work_list(jsr_start_block);

  // Ready to resume parsing in subroutine
  iterate_all_blocks();

  // If we bailed out during parsing, return immediately (this is bad news)
  CHECK_BAILOUT_(false);

  // Detect whether the continuation can actually be reached. If not,
  // it has not had state set by the join() operations in
  // iterate_bytecodes_for_block()/ret() and we should not touch the
  // iteration state. The calling activation of
  // iterate_bytecodes_for_block will then complete normally.
  if (cont->state() != nullptr) {
    if (!cont->is_set(BlockBegin::was_visited_flag)) {
      // add continuation to work list instead of parsing it immediately
      scope_data()->parent()->add_to_work_list(cont);
    }
  }

  assert(jsr_continuation() == cont, "continuation must not have changed");
  assert(!jsr_continuation()->is_set(BlockBegin::was_visited_flag) ||
         jsr_continuation()->is_set(BlockBegin::parser_loop_header_flag),
         "continuation can only be visited in case of backward branches");
  assert(_last && _last->as_BlockEnd(), "block must have end");

  // continuation is in work list, so end iteration of current block
  _skip_block = true;
  pop_scope_for_jsr();

  return true;
}


// Inline the entry of a synchronized method as a monitor enter and
// register the exception handler which releases the monitor if an
// exception is thrown within the callee. Note that the monitor enter
// cannot throw an exception itself, because the receiver is
// guaranteed to be non-null by the explicit null check at the
// beginning of inlining.
void GraphBuilder::inline_sync_entry(Value lock, BlockBegin* sync_handler) {
  assert(lock != nullptr && sync_handler != nullptr, "lock or handler missing");

  monitorenter(lock, SynchronizationEntryBCI);
  assert(_last->as_MonitorEnter() != nullptr, "monitor enter expected");
  _last->set_needs_null_check(false);

  sync_handler->set(BlockBegin::exception_entry_flag);
  sync_handler->set(BlockBegin::is_on_work_list_flag);

  ciExceptionHandler* desc = new ciExceptionHandler(method()->holder(), 0, method()->code_size(), -1, 0);
  XHandler* h = new XHandler(desc);
  h->set_entry_block(sync_handler);
  scope_data()->xhandlers()->append(h);
  scope_data()->set_has_handler();
}


// If an exception is thrown and not handled within an inlined
// synchronized method, the monitor must be released before the
// exception is rethrown in the outer scope. Generate the appropriate
// instructions here.
void GraphBuilder::fill_sync_handler(Value lock, BlockBegin* sync_handler, bool default_handler) {
  BlockBegin* orig_block = _block;
  ValueStack* orig_state = _state;
  Instruction* orig_last = _last;
  _last = _block = sync_handler;
  _state = sync_handler->state()->copy();

  assert(sync_handler != nullptr, "handler missing");
  assert(!sync_handler->is_set(BlockBegin::was_visited_flag), "is visited here");

  assert(lock != nullptr || default_handler, "lock or handler missing");

  XHandler* h = scope_data()->xhandlers()->remove_last();
  assert(h->entry_block() == sync_handler, "corrupt list of handlers");

  block()->set(BlockBegin::was_visited_flag);
  Value exception = append_with_bci(new ExceptionObject(), SynchronizationEntryBCI);
  assert(exception->is_pinned(), "must be");

  int bci = SynchronizationEntryBCI;
  if (compilation()->env()->dtrace_method_probes()) {
    // Report exit from inline methods.  We don't have a stream here
    // so pass an explicit bci of SynchronizationEntryBCI.
    Values* args = new Values(1);
    args->push(append_with_bci(new Constant(new MethodConstant(method())), bci));
    append_with_bci(new RuntimeCall(voidType, "dtrace_method_exit", CAST_FROM_FN_PTR(address, SharedRuntime::dtrace_method_exit), args), bci);
  }

  if (lock) {
    assert(state()->locks_size() > 0 && state()->lock_at(state()->locks_size() - 1) == lock, "lock is missing");
    if (!lock->is_linked()) {
      lock = append_with_bci(lock, bci);
    }

    // exit the monitor in the context of the synchronized method
    monitorexit(lock, bci);

    // exit the context of the synchronized method
    if (!default_handler) {
      pop_scope();
      bci = _state->caller_state()->bci();
      _state = _state->caller_state()->copy_for_parsing();
    }
  }

  // perform the throw as if at the call site
  apush(exception);
  throw_op(bci);

  BlockEnd* end = last()->as_BlockEnd();
  block()->set_end(end);

  _block = orig_block;
  _state = orig_state;
  _last = orig_last;
}


bool GraphBuilder::try_inline_full(ciMethod* callee, bool holder_known, bool ignore_return, Bytecodes::Code bc, Value receiver) {
  assert(!callee->is_native(), "callee must not be native");
  if (CompilationPolicy::should_not_inline(compilation()->env(), callee)) {
    INLINE_BAILOUT("inlining prohibited by policy");
  }
  // first perform tests of things it's not possible to inline
  if (callee->has_exception_handlers() &&
      !InlineMethodsWithExceptionHandlers) INLINE_BAILOUT("callee has exception handlers");
  if (callee->is_synchronized() &&
      !InlineSynchronizedMethods         ) INLINE_BAILOUT("callee is synchronized");
  if (!callee->holder()->is_linked())      INLINE_BAILOUT("callee's klass not linked yet");
  if (bc == Bytecodes::_invokestatic &&
      !callee->holder()->is_initialized()) INLINE_BAILOUT("callee's klass not initialized yet");
  if (!callee->has_balanced_monitors())    INLINE_BAILOUT("callee's monitors do not match");

  // Proper inlining of methods with jsrs requires a little more work.
  if (callee->has_jsrs()                 ) INLINE_BAILOUT("jsrs not handled properly by inliner yet");

  if (is_profiling() && !callee->ensure_method_data()) {
    INLINE_BAILOUT("mdo allocation failed");
  }

  const bool is_invokedynamic = (bc == Bytecodes::_invokedynamic);
  const bool has_receiver = (bc != Bytecodes::_invokestatic && !is_invokedynamic);

  const int args_base = state()->stack_size() - callee->arg_size();
  assert(args_base >= 0, "stack underflow during inlining");

  Value recv = nullptr;
  if (has_receiver) {
    assert(!callee->is_static(), "callee must not be static");
    assert(callee->arg_size() > 0, "must have at least a receiver");

    recv = state()->stack_at(args_base);
    if (recv->is_null_obj()) {
      INLINE_BAILOUT("receiver is always null");
    }
  }

  // now perform tests that are based on flag settings
  bool inlinee_by_directive = compilation()->directive()->should_inline(callee);
  if (callee->force_inline() || inlinee_by_directive) {
    if (inline_level() > MaxForceInlineLevel                      ) INLINE_BAILOUT("MaxForceInlineLevel");
    if (recursive_inline_level(callee) > C1MaxRecursiveInlineLevel) INLINE_BAILOUT("recursive inlining too deep");

    const char* msg = "";
    if (callee->force_inline())  msg = "force inline by annotation";
    if (inlinee_by_directive)    msg = "force inline by CompileCommand";
    print_inlining(callee, msg);
  } else {
    // use heuristic controls on inlining
    if (inline_level() > C1MaxInlineLevel                       ) INLINE_BAILOUT("inlining too deep");
    int callee_recursive_level = recursive_inline_level(callee);
    if (callee_recursive_level > C1MaxRecursiveInlineLevel      ) INLINE_BAILOUT("recursive inlining too deep");
    if (callee->code_size_for_inlining() > max_inline_size()    ) INLINE_BAILOUT("callee is too large");
    // Additional condition to limit stack usage for non-recursive calls.
    if ((callee_recursive_level == 0) &&
        (callee->max_stack() + callee->max_locals() - callee->size_of_parameters() > C1InlineStackLimit)) {
      INLINE_BAILOUT("callee uses too much stack");
    }

    // don't inline throwable methods unless the inlining tree is rooted in a throwable class
    if (callee->name() == ciSymbols::object_initializer_name() &&
        callee->holder()->is_subclass_of(ciEnv::current()->Throwable_klass())) {
      // Throwable constructor call
      IRScope* top = scope();
      while (top->caller() != nullptr) {
        top = top->caller();
      }
      if (!top->method()->holder()->is_subclass_of(ciEnv::current()->Throwable_klass())) {
        INLINE_BAILOUT("don't inline Throwable constructors");
      }
    }

    if (compilation()->env()->num_inlined_bytecodes() > DesiredMethodLimit) {
      INLINE_BAILOUT("total inlining greater than DesiredMethodLimit");
    }
    // printing
    print_inlining(callee, "inline", /*success*/ true);
  }

  assert(bc != Bytecodes::_invokestatic || callee->holder()->is_initialized(), "required");

  // NOTE: Bailouts from this point on, which occur at the
  // GraphBuilder level, do not cause bailout just of the inlining but
  // in fact of the entire compilation.

  BlockBegin* orig_block = block();

  // Insert null check if necessary
  if (has_receiver) {
    // note: null check must happen even if first instruction of callee does
    //       an implicit null check since the callee is in a different scope
    //       and we must make sure exception handling does the right thing
    null_check(recv);
  }

  if (is_profiling()) {
    // Note that we'd collect profile data in this method if we wanted it.
    // this may be redundant here...
    compilation()->set_would_profile(true);

    if (profile_calls()) {
      int start = 0;
      Values* obj_args = args_list_for_profiling(callee, start, has_receiver);
      if (obj_args != nullptr) {
        int s = obj_args->capacity();
        // if called through method handle invoke, some arguments may have been popped
        for (int i = args_base+start, j = 0; j < obj_args->capacity() && i < state()->stack_size(); ) {
          Value v = state()->stack_at_inc(i);
          if (v->type()->is_object_kind()) {
            obj_args->push(v);
            j++;
          }
        }
        check_args_for_profiling(obj_args, s);
      }
      profile_call(callee, recv, holder_known ? callee->holder() : nullptr, obj_args, true);
    }
  }

  // Introduce a new callee continuation point - if the callee has
  // more than one return instruction or the return does not allow
  // fall-through of control flow, all return instructions of the
  // callee will need to be replaced by Goto's pointing to this
  // continuation point.
  BlockBegin* cont = block_at(next_bci());
  bool continuation_existed = true;
  if (cont == nullptr) {
    cont = new BlockBegin(next_bci());
    // low number so that continuation gets parsed as early as possible
    cont->set_depth_first_number(0);
    if (PrintInitialBlockList) {
      tty->print_cr("CFG: created block %d (bci %d) as continuation for inline at bci %d",
                    cont->block_id(), cont->bci(), bci());
    }
    continuation_existed = false;
  }
  // Record number of predecessors of continuation block before
  // inlining, to detect if inlined method has edges to its
  // continuation after inlining.
  int continuation_preds = cont->number_of_preds();

  // Push callee scope
  push_scope(callee, cont);

  // the BlockListBuilder for the callee could have bailed out
  if (bailed_out())
      return false;

  // Temporarily set up bytecode stream so we can append instructions
  // (only using the bci of this stream)
  scope_data()->set_stream(scope_data()->parent()->stream());

  // Pass parameters into callee state: add assignments
  // note: this will also ensure that all arguments are computed before being passed
  ValueStack* callee_state = state();
  ValueStack* caller_state = state()->caller_state();
  for (int i = args_base; i < caller_state->stack_size(); ) {
    const int arg_no = i - args_base;
    Value arg = caller_state->stack_at_inc(i);
    store_local(callee_state, arg, arg_no);
  }

  // Remove args from stack.
  // Note that we preserve locals state in case we can use it later
  // (see use of pop_scope() below)
  caller_state->truncate_stack(args_base);
  assert(callee_state->stack_size() == 0, "callee stack must be empty");

  Value lock = nullptr;
  BlockBegin* sync_handler = nullptr;

  // Inline the locking of the receiver if the callee is synchronized
  if (callee->is_synchronized()) {
    lock = callee->is_static() ? append(new Constant(new InstanceConstant(callee->holder()->java_mirror())))
                               : state()->local_at(0);
    sync_handler = new BlockBegin(SynchronizationEntryBCI);
    inline_sync_entry(lock, sync_handler);
  }

  if (compilation()->env()->dtrace_method_probes()) {
    Values* args = new Values(1);
    args->push(append(new Constant(new MethodConstant(method()))));
    append(new RuntimeCall(voidType, "dtrace_method_entry", CAST_FROM_FN_PTR(address, SharedRuntime::dtrace_method_entry), args));
  }

  if (profile_inlined_calls()) {
    profile_invocation(callee, copy_state_before_with_bci(SynchronizationEntryBCI));
  }

  BlockBegin* callee_start_block = block_at(0);
  if (callee_start_block != nullptr) {
    assert(callee_start_block->is_set(BlockBegin::parser_loop_header_flag), "must be loop header");
    Goto* goto_callee = new Goto(callee_start_block, false);
    // The state for this goto is in the scope of the callee, so use
    // the entry bci for the callee instead of the call site bci.
    append_with_bci(goto_callee, 0);
    _block->set_end(goto_callee);
    callee_start_block->merge(callee_state, compilation()->has_irreducible_loops());

    _last = _block = callee_start_block;

    scope_data()->add_to_work_list(callee_start_block);
  }

  // Clear out bytecode stream
  scope_data()->set_stream(nullptr);
  scope_data()->set_ignore_return(ignore_return);

  CompileLog* log = compilation()->log();
  if (log != nullptr) log->head("parse method='%d'", log->identify(callee));

  // Ready to resume parsing in callee (either in the same block we
  // were in before or in the callee's start block)
  iterate_all_blocks(callee_start_block == nullptr);

  if (log != nullptr) log->done("parse");

  // If we bailed out during parsing, return immediately (this is bad news)
  if (bailed_out())
      return false;

  // iterate_all_blocks theoretically traverses in random order; in
  // practice, we have only traversed the continuation if we are
  // inlining into a subroutine
  assert(continuation_existed ||
         !continuation()->is_set(BlockBegin::was_visited_flag),
         "continuation should not have been parsed yet if we created it");

  // At this point we are almost ready to return and resume parsing of
  // the caller back in the GraphBuilder. The only thing we want to do
  // first is an optimization: during parsing of the callee we
  // generated at least one Goto to the continuation block. If we
  // generated exactly one, and if the inlined method spanned exactly
  // one block (and we didn't have to Goto its entry), then we snip
  // off the Goto to the continuation, allowing control to fall
  // through back into the caller block and effectively performing
  // block merging. This allows load elimination and CSE to take place
  // across multiple callee scopes if they are relatively simple, and
  // is currently essential to making inlining profitable.
  if (num_returns() == 1
      && block() == orig_block
      && block() == inline_cleanup_block()) {
    _last  = inline_cleanup_return_prev();
    _state = inline_cleanup_state();
  } else if (continuation_preds == cont->number_of_preds()) {
    // Inlining caused that the instructions after the invoke in the
    // caller are not reachable any more. So skip filling this block
    // with instructions!
    assert(cont == continuation(), "");
    assert(_last && _last->as_BlockEnd(), "");
    _skip_block = true;
  } else {
    // Resume parsing in continuation block unless it was already parsed.
    // Note that if we don't change _last here, iteration in
    // iterate_bytecodes_for_block will stop when we return.
    if (!continuation()->is_set(BlockBegin::was_visited_flag)) {
      // add continuation to work list instead of parsing it immediately
      assert(_last && _last->as_BlockEnd(), "");
      scope_data()->parent()->add_to_work_list(continuation());
      _skip_block = true;
    }
  }

  // Fill the exception handler for synchronized methods with instructions
  if (callee->is_synchronized() && sync_handler->state() != nullptr) {
    fill_sync_handler(lock, sync_handler);
  } else {
    pop_scope();
  }

  compilation()->notice_inlined_method(callee);

  return true;
}


bool GraphBuilder::try_method_handle_inline(ciMethod* callee, bool ignore_return) {
  ValueStack* state_before = copy_state_before();
  vmIntrinsics::ID iid = callee->intrinsic_id();
  switch (iid) {
  case vmIntrinsics::_invokeBasic:
    {
      // get MethodHandle receiver
      const int args_base = state()->stack_size() - callee->arg_size();
      ValueType* type = state()->stack_at(args_base)->type();
      if (type->is_constant()) {
        ciObject* mh = type->as_ObjectType()->constant_value();
        if (mh->is_method_handle()) {
          ciMethod* target = mh->as_method_handle()->get_vmtarget();

          // We don't do CHA here so only inline static and statically bindable methods.
          if (target->is_static() || target->can_be_statically_bound()) {
            if (ciMethod::is_consistent_info(callee, target)) {
              Bytecodes::Code bc = target->is_static() ? Bytecodes::_invokestatic : Bytecodes::_invokevirtual;
              ignore_return = ignore_return || (callee->return_type()->is_void() && !target->return_type()->is_void());
              if (try_inline(target, /*holder_known*/ !callee->is_static(), ignore_return, bc)) {
                return true;
              }
            } else {
              print_inlining(target, "signatures mismatch", /*success*/ false);
            }
          } else {
            assert(false, "no inlining through MH::invokeBasic"); // missing optimization opportunity due to suboptimal LF shape
            print_inlining(target, "not static or statically bindable", /*success*/ false);
          }
        } else {
          assert(mh->is_null_object(), "not a null");
          print_inlining(callee, "receiver is always null", /*success*/ false);
        }
      } else {
        print_inlining(callee, "receiver not constant", /*success*/ false);
      }
    }
    break;

  case vmIntrinsics::_linkToVirtual:
  case vmIntrinsics::_linkToStatic:
  case vmIntrinsics::_linkToSpecial:
  case vmIntrinsics::_linkToInterface:
    {
      // pop MemberName argument
      const int args_base = state()->stack_size() - callee->arg_size();
      ValueType* type = apop()->type();
      if (type->is_constant()) {
        ciMethod* target = type->as_ObjectType()->constant_value()->as_member_name()->get_vmtarget();
        ignore_return = ignore_return || (callee->return_type()->is_void() && !target->return_type()->is_void());
        // If the target is another method handle invoke, try to recursively get
        // a better target.
        if (target->is_method_handle_intrinsic()) {
          if (try_method_handle_inline(target, ignore_return)) {
            return true;
          }
        } else if (!ciMethod::is_consistent_info(callee, target)) {
          print_inlining(target, "signatures mismatch", /*success*/ false);
        } else {
          ciSignature* signature = target->signature();
          const int receiver_skip = target->is_static() ? 0 : 1;
          // Cast receiver to its type.
          if (!target->is_static()) {
            ciKlass* tk = signature->accessing_klass();
            Value obj = state()->stack_at(args_base);
            if (obj->exact_type() == nullptr &&
                obj->declared_type() != tk && tk != compilation()->env()->Object_klass()) {
              TypeCast* c = new TypeCast(tk, obj, state_before);
              append(c);
              state()->stack_at_put(args_base, c);
            }
          }
          // Cast reference arguments to its type.
          for (int i = 0, j = 0; i < signature->count(); i++) {
            ciType* t = signature->type_at(i);
            if (t->is_klass()) {
              ciKlass* tk = t->as_klass();
              Value obj = state()->stack_at(args_base + receiver_skip + j);
              if (obj->exact_type() == nullptr &&
                  obj->declared_type() != tk && tk != compilation()->env()->Object_klass()) {
                TypeCast* c = new TypeCast(t, obj, state_before);
                append(c);
                state()->stack_at_put(args_base + receiver_skip + j, c);
              }
            }
            j += t->size();  // long and double take two slots
          }
          // We don't do CHA here so only inline static and statically bindable methods.
          if (target->is_static() || target->can_be_statically_bound()) {
            Bytecodes::Code bc = target->is_static() ? Bytecodes::_invokestatic : Bytecodes::_invokevirtual;
            if (try_inline(target, /*holder_known*/ !callee->is_static(), ignore_return, bc)) {
              return true;
            }
          } else {
            print_inlining(target, "not static or statically bindable", /*success*/ false);
          }
        }
      } else {
        print_inlining(callee, "MemberName not constant", /*success*/ false);
      }
    }
    break;

  case vmIntrinsics::_linkToNative:
    print_inlining(callee, "native call", /*success*/ false);
    break;

  default:
    fatal("unexpected intrinsic %d: %s", vmIntrinsics::as_int(iid), vmIntrinsics::name_at(iid));
    break;
  }
  set_state(state_before->copy_for_parsing());
  return false;
}


void GraphBuilder::inline_bailout(const char* msg) {
  assert(msg != nullptr, "inline bailout msg must exist");
  _inline_bailout_msg = msg;
}


void GraphBuilder::clear_inline_bailout() {
  _inline_bailout_msg = nullptr;
}


void GraphBuilder::push_root_scope(IRScope* scope, BlockList* bci2block, BlockBegin* start) {
  ScopeData* data = new ScopeData(nullptr);
  data->set_scope(scope);
  data->set_bci2block(bci2block);
  _scope_data = data;
  _block = start;
}


void GraphBuilder::push_scope(ciMethod* callee, BlockBegin* continuation) {
  IRScope* callee_scope = new IRScope(compilation(), scope(), bci(), callee, -1, false);
  scope()->add_callee(callee_scope);

  BlockListBuilder blb(compilation(), callee_scope, -1);
  CHECK_BAILOUT();

  if (!blb.bci2block()->at(0)->is_set(BlockBegin::parser_loop_header_flag)) {
    // this scope can be inlined directly into the caller so remove
    // the block at bci 0.
    blb.bci2block()->at_put(0, nullptr);
  }

  set_state(new ValueStack(callee_scope, state()->copy(ValueStack::CallerState, bci())));

  ScopeData* data = new ScopeData(scope_data());
  data->set_scope(callee_scope);
  data->set_bci2block(blb.bci2block());
  data->set_continuation(continuation);
  _scope_data = data;
}


void GraphBuilder::push_scope_for_jsr(BlockBegin* jsr_continuation, int jsr_dest_bci) {
  ScopeData* data = new ScopeData(scope_data());
  data->set_parsing_jsr();
  data->set_jsr_entry_bci(jsr_dest_bci);
  data->set_jsr_return_address_local(-1);
  // Must clone bci2block list as we will be mutating it in order to
  // properly clone all blocks in jsr region as well as exception
  // handlers containing rets
  BlockList* new_bci2block = new BlockList(bci2block()->length());
  new_bci2block->appendAll(bci2block());
  data->set_bci2block(new_bci2block);
  data->set_scope(scope());
  data->setup_jsr_xhandlers();
  data->set_continuation(continuation());
  data->set_jsr_continuation(jsr_continuation);
  _scope_data = data;
}


void GraphBuilder::pop_scope() {
  int number_of_locks = scope()->number_of_locks();
  _scope_data = scope_data()->parent();
  // accumulate minimum number of monitor slots to be reserved
  scope()->set_min_number_of_locks(number_of_locks);
}


void GraphBuilder::pop_scope_for_jsr() {
  _scope_data = scope_data()->parent();
}

void GraphBuilder::append_unsafe_get(ciMethod* callee, BasicType t, bool is_volatile) {
  Values* args = state()->pop_arguments(callee->arg_size());
  null_check(args->at(0));
  Instruction* offset = args->at(2);
#ifndef _LP64
  offset = append(new Convert(Bytecodes::_l2i, offset, as_ValueType(T_INT)));
#endif
  Instruction* op = append(new UnsafeGet(t, args->at(1), offset, is_volatile));
  push(op->type(), op);
  compilation()->set_has_unsafe_access(true);
}


void GraphBuilder::append_unsafe_put(ciMethod* callee, BasicType t, bool is_volatile) {
  Values* args = state()->pop_arguments(callee->arg_size());
  null_check(args->at(0));
  Instruction* offset = args->at(2);
#ifndef _LP64
  offset = append(new Convert(Bytecodes::_l2i, offset, as_ValueType(T_INT)));
#endif
  Value val = args->at(3);
  if (t == T_BOOLEAN) {
    Value mask = append(new Constant(new IntConstant(1)));
    val = append(new LogicOp(Bytecodes::_iand, val, mask));
  }
  Instruction* op = append(new UnsafePut(t, args->at(1), offset, val, is_volatile));
  compilation()->set_has_unsafe_access(true);
  kill_all();
}

void GraphBuilder::append_unsafe_CAS(ciMethod* callee) {
  ValueStack* state_before = copy_state_for_exception();
  ValueType* result_type = as_ValueType(callee->return_type());
  assert(result_type->is_int(), "int result");
  Values* args = state()->pop_arguments(callee->arg_size());

  // Pop off some args to specially handle, then push back
  Value newval = args->pop();
  Value cmpval = args->pop();
  Value offset = args->pop();
  Value src = args->pop();
  Value unsafe_obj = args->pop();

  // Separately handle the unsafe arg. It is not needed for code
  // generation, but must be null checked
  null_check(unsafe_obj);

#ifndef _LP64
  offset = append(new Convert(Bytecodes::_l2i, offset, as_ValueType(T_INT)));
#endif

  args->push(src);
  args->push(offset);
  args->push(cmpval);
  args->push(newval);

  // An unsafe CAS can alias with other field accesses, but we don't
  // know which ones so mark the state as no preserved.  This will
  // cause CSE to invalidate memory across it.
  bool preserves_state = false;
  Intrinsic* result = new Intrinsic(result_type, callee->intrinsic_id(), args, false, state_before, preserves_state);
  append_split(result);
  push(result_type, result);
  compilation()->set_has_unsafe_access(true);
}

void GraphBuilder::append_char_access(ciMethod* callee, bool is_store) {
  // This intrinsic accesses byte[] array as char[] array. Computing the offsets
  // correctly requires matched array shapes.
  assert (arrayOopDesc::base_offset_in_bytes(T_CHAR) == arrayOopDesc::base_offset_in_bytes(T_BYTE),
          "sanity: byte[] and char[] bases agree");
  assert (type2aelembytes(T_CHAR) == type2aelembytes(T_BYTE)*2,
          "sanity: byte[] and char[] scales agree");

  ValueStack* state_before = copy_state_indexed_access();
  compilation()->set_has_access_indexed(true);
  Values* args = state()->pop_arguments(callee->arg_size());
  Value array = args->at(0);
  Value index = args->at(1);
  if (is_store) {
    Value value = args->at(2);
    Instruction* store = append(new StoreIndexed(array, index, nullptr, T_CHAR, value, state_before, false, true));
    store->set_flag(Instruction::NeedsRangeCheckFlag, false);
    _memory->store_value(value);
  } else {
    Instruction* load = append(new LoadIndexed(array, index, nullptr, T_CHAR, state_before, true));
    load->set_flag(Instruction::NeedsRangeCheckFlag, false);
    push(load->type(), load);
  }
}

void GraphBuilder::append_alloc_array_copy(ciMethod* callee) {
  const int args_base = state()->stack_size() - callee->arg_size();
  ciType* receiver_type = state()->stack_at(args_base)->exact_type();
  if (receiver_type == nullptr) {
    inline_bailout("must have a receiver");
    return;
  }
  if (!receiver_type->is_type_array_klass()) {
    inline_bailout("clone array not primitive");
    return;
  }

  ValueStack* state_before = copy_state_before();
  state_before->set_force_reexecute();
  Value src = apop();
  BasicType basic_type = src->exact_type()->as_array_klass()->element_type()->basic_type();
  Value length = append(new ArrayLength(src, state_before));
  Value new_array = append_split(new NewTypeArray(length, basic_type, state_before, false));

  ValueType* result_type = as_ValueType(callee->return_type());
  vmIntrinsics::ID id = vmIntrinsics::_arraycopy;
  Values* args = new Values(5);
  args->push(src);
  args->push(append(new Constant(new IntConstant(0))));
  args->push(new_array);
  args->push(append(new Constant(new IntConstant(0))));
  args->push(length);
  const bool has_receiver = true;
  Intrinsic* array_copy = new Intrinsic(result_type, id,
                                    args, has_receiver, state_before,
                                    vmIntrinsics::preserves_state(id),
                                    vmIntrinsics::can_trap(id));
  array_copy->set_flag(Instruction::OmitChecksFlag, true);
  append_split(array_copy);
  apush(new_array);
  append(new MemBar(lir_membar_storestore));
}

void GraphBuilder::print_inlining(ciMethod* callee, const char* msg, bool success) {
  CompileLog* log = compilation()->log();
  if (log != nullptr) {
    assert(msg != nullptr, "inlining msg should not be null!");
    if (success) {
      log->inline_success(msg);
    } else {
      log->inline_fail(msg);
    }
  }
  EventCompilerInlining event;
  if (event.should_commit()) {
    CompilerEvent::InlineEvent::post(event, compilation()->env()->task()->compile_id(), method()->get_Method(), callee, success, msg, bci());
  }

  CompileTask::print_inlining_ul(callee, scope()->level(), bci(), inlining_result_of(success), msg);

  if (!compilation()->directive()->PrintInliningOption) {
    return;
  }
  CompileTask::print_inlining_tty(callee, scope()->level(), bci(), inlining_result_of(success), msg);
  if (success && CIPrintMethodCodes) {
    callee->print_codes();
  }
}

void GraphBuilder::append_unsafe_get_and_set(ciMethod* callee, bool is_add) {
  Values* args = state()->pop_arguments(callee->arg_size());
  BasicType t = callee->return_type()->basic_type();
  null_check(args->at(0));
  Instruction* offset = args->at(2);
#ifndef _LP64
  offset = append(new Convert(Bytecodes::_l2i, offset, as_ValueType(T_INT)));
#endif
  Instruction* op = append(new UnsafeGetAndSet(t, args->at(1), offset, args->at(3), is_add));
  compilation()->set_has_unsafe_access(true);
  kill_all();
  push(op->type(), op);
}

#ifndef PRODUCT
void GraphBuilder::print_stats() {
  if (UseLocalValueNumbering) {
    vmap()->print();
  }
}
#endif // PRODUCT

void GraphBuilder::profile_call(ciMethod* callee, Value recv, ciKlass* known_holder, Values* obj_args, bool inlined) {
  assert(known_holder == nullptr || (known_holder->is_instance_klass() &&
                                  (!known_holder->is_interface() ||
                                   ((ciInstanceKlass*)known_holder)->has_nonstatic_concrete_methods())), "should be non-static concrete method");
  if (known_holder != nullptr) {
    if (known_holder->exact_klass() == nullptr) {
      known_holder = compilation()->cha_exact_type(known_holder);
    }
  }

  append(new ProfileCall(method(), bci(), callee, recv, known_holder, obj_args, inlined));
}

void GraphBuilder::profile_return_type(Value ret, ciMethod* callee, ciMethod* m, int invoke_bci) {
  assert((m == nullptr) == (invoke_bci < 0), "invalid method and invalid bci together");
  if (m == nullptr) {
    m = method();
  }
  if (invoke_bci < 0) {
    invoke_bci = bci();
  }
  ciMethodData* md = m->method_data_or_null();
  ciProfileData* data = md->bci_to_data(invoke_bci);
  if (data != nullptr && (data->is_CallTypeData() || data->is_VirtualCallTypeData())) {
    bool has_return = data->is_CallTypeData() ? ((ciCallTypeData*)data)->has_return() : ((ciVirtualCallTypeData*)data)->has_return();
    if (has_return) {
      append(new ProfileReturnType(m , invoke_bci, callee, ret));
    }
  }
}

void GraphBuilder::profile_invocation(ciMethod* callee, ValueStack* state) {
  append(new ProfileInvoke(callee, state));
}
