Anforderungen  |   Konzepte  |   Entwurf  |   Entwicklung  |   Qualitätssicherung  |   Lebenszyklus  |   Steuerung
 
 
 
 


Quellcode-Bibliothek

© Kompilation durch diese Firma

[Weder Korrektheit noch Funktionsfähigkeit der Software werden zugesichert.]

Datei: stylesheet.css   Sprache: C

/*
 * Copyright (c) 2000, 2022, 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.
 *
 */


#ifndef SHARE_C1_C1_LIR_HPP
#define SHARE_C1_C1_LIR_HPP

#include "c1/c1_Defs.hpp"
#include "c1/c1_ValueType.hpp"
#include "oops/method.hpp"
#include "utilities/globalDefinitions.hpp"

class BlockBegin;
class BlockList;
class LIR_Assembler;
class CodeEmitInfo;
class CodeStub;
class CodeStubList;
class C1SafepointPollStub;
class ArrayCopyStub;
class LIR_Op;
class ciType;
class ValueType;
class LIR_OpVisitState;
class FpuStackSim;

//---------------------------------------------------------------------
//                 LIR Operands
//    LIR_OprPtr
//      LIR_Const
//      LIR_Address
//---------------------------------------------------------------------
class LIR_OprPtr;
class LIR_Const;
class LIR_Address;
class LIR_OprVisitor;
class LIR_Opr;

typedef int          RegNr;

typedef GrowableArray<LIR_Opr> LIR_OprList;
typedef GrowableArray<LIR_Op*> LIR_OpArray;
typedef GrowableArray<LIR_Op*> LIR_OpList;

// define LIR_OprPtr early so LIR_Opr can refer to it
class LIR_OprPtr: public CompilationResourceObj {
 public:
  bool is_oop_pointer() const                    { return (type() == T_OBJECT); }
  bool is_float_kind() const                     { BasicType t = type(); return (t == T_FLOAT) || (t == T_DOUBLE); }

  virtual LIR_Const*  as_constant()              { return NULL; }
  virtual LIR_Address* as_address()              { return NULL; }
  virtual BasicType type() const                 = 0;
  virtual void print_value_on(outputStream* out) const = 0;
};



// LIR constants
class LIR_Const: public LIR_OprPtr {
 private:
  JavaValue _value;

  void type_check(BasicType t) const   { assert(type() == t, "type check"); }
  void type_check(BasicType t1, BasicType t2) const   { assert(type() == t1 || type() == t2, "type check"); }
  void type_check(BasicType t1, BasicType t2, BasicType t3) const   { assert(type() == t1 || type() == t2 || type() == t3, "type check"); }

 public:
  LIR_Const(jint i, bool is_address=false)       { _value.set_type(is_address?T_ADDRESS:T_INT); _value.set_jint(i); }
  LIR_Const(jlong l)                             { _value.set_type(T_LONG);    _value.set_jlong(l); }
  LIR_Const(jfloat f)                            { _value.set_type(T_FLOAT);   _value.set_jfloat(f); }
  LIR_Const(jdouble d)                           { _value.set_type(T_DOUBLE);  _value.set_jdouble(d); }
  LIR_Const(jobject o)                           { _value.set_type(T_OBJECT);  _value.set_jobject(o); }
  LIR_Const(void* p) {
#ifdef _LP64
    assert(sizeof(jlong) >= sizeof(p), "too small");;
    _value.set_type(T_LONG);    _value.set_jlong((jlong)p);
#else
    assert(sizeof(jint) >= sizeof(p), "too small");;
    _value.set_type(T_INT);     _value.set_jint((jint)p);
#endif
  }
  LIR_Const(Metadata* m) {
    _value.set_type(T_METADATA);
#ifdef _LP64
    _value.set_jlong((jlong)m);
#else
    _value.set_jint((jint)m);
#endif // _LP64
  }

  virtual BasicType type()       const { return _value.get_type(); }
  virtual LIR_Const* as_constant()     { return this; }

  jint      as_jint()    const         { type_check(T_INT, T_ADDRESS); return _value.get_jint(); }
  jlong     as_jlong()   const         { type_check(T_LONG  ); return _value.get_jlong(); }
  jfloat    as_jfloat()  const         { type_check(T_FLOAT ); return _value.get_jfloat(); }
  jdouble   as_jdouble() const         { type_check(T_DOUBLE); return _value.get_jdouble(); }
  jobject   as_jobject() const         { type_check(T_OBJECT); return _value.get_jobject(); }
  jint      as_jint_lo() const         { type_check(T_LONG  ); return low(_value.get_jlong()); }
  jint      as_jint_hi() const         { type_check(T_LONG  ); return high(_value.get_jlong()); }

#ifdef _LP64
  address   as_pointer() const         { type_check(T_LONG  ); return (address)_value.get_jlong(); }
  Metadata* as_metadata() const        { type_check(T_METADATA); return (Metadata*)_value.get_jlong(); }
#else
  address   as_pointer() const         { type_check(T_INT   ); return (address)_value.get_jint(); }
  Metadata* as_metadata() const        { type_check(T_METADATA); return (Metadata*)_value.get_jint(); }
#endif


  jint      as_jint_bits() const       { type_check(T_FLOAT, T_INT, T_ADDRESS); return _value.get_jint(); }
  jint      as_jint_lo_bits() const    {
    if (type() == T_DOUBLE) {
      return low(jlong_cast(_value.get_jdouble()));
    } else {
      return as_jint_lo();
    }
  }
  jint      as_jint_hi_bits() const    {
    if (type() == T_DOUBLE) {
      return high(jlong_cast(_value.get_jdouble()));
    } else {
      return as_jint_hi();
    }
  }
  jlong      as_jlong_bits() const    {
    if (type() == T_DOUBLE) {
      return jlong_cast(_value.get_jdouble());
    } else {
      return as_jlong();
    }
  }

  virtual void print_value_on(outputStream* out) const PRODUCT_RETURN;


  bool is_zero_float() {
    jfloat f = as_jfloat();
    jfloat ok = 0.0f;
    return jint_cast(f) == jint_cast(ok);
  }

  bool is_one_float() {
    jfloat f = as_jfloat();
    return !g_isnan(f) && g_isfinite(f) && f == 1.0;
  }

  bool is_zero_double() {
    jdouble d = as_jdouble();
    jdouble ok = 0.0;
    return jlong_cast(d) == jlong_cast(ok);
  }

  bool is_one_double() {
    jdouble d = as_jdouble();
    return !g_isnan(d) && g_isfinite(d) && d == 1.0;
  }
};


//---------------------LIR Operand descriptor------------------------------------
//
// The class LIR_Opr represents a LIR instruction operand;
// it can be a register (ALU/FPU), stack location or a constant;
// Constants and addresses are represented as resource area allocated
// structures (see above), and pointers are stored in the _value field (cast to
// an intptr_t).
// Registers and stack locations are represented inline as integers.
// (see value function).

// Previously, this class was derived from CompilationResourceObj.
// However, deriving from any of the "Obj" types in allocation.hpp seems
// detrimental, since in some build modes it would add a vtable to this class,
// which make it no longer be a 1-word trivially-copyable wrapper object,
// which is the entire point of it.

class LIR_Opr {
 public:
  // value structure:
  //          data        other-non-data opr-type opr-kind
  // +-------------------+--------------+-------+-----+
  // [max...............................|6 5 4 3|2 1 0]
  //                                                 ^
  //                                           is_pointer bit
  //
  // lowest bit cleared, means it is a structure pointer
  // we need 4 bits to represent types

 private:
  friend class LIR_OprFact;

  intptr_t _value;
  // Conversion
  intptr_t value() const                         { return _value; }

  bool check_value_mask(intptr_t mask, intptr_t masked_value) const {
    return (value() & mask) == masked_value;
  }

  enum OprKind {
      pointer_value      = 0
    , stack_value        = 1
    , cpu_register       = 3
    , fpu_register       = 5
    , illegal_value      = 7
  };

  enum OprBits {
      pointer_bits   = 1
    , kind_bits      = 3
    , type_bits      = 4
    , size_bits      = 2
    , destroys_bits  = 1
    , virtual_bits   = 1
    , is_xmm_bits    = 1
    , last_use_bits  = 1
    , is_fpu_stack_offset_bits = 1        // used in assertion checking on x86 for FPU stack slot allocation
    , non_data_bits  = kind_bits + type_bits + size_bits + destroys_bits + virtual_bits
                       + is_xmm_bits + last_use_bits + is_fpu_stack_offset_bits
    , data_bits      = BitsPerInt - non_data_bits
    , reg_bits       = data_bits / 2      // for two registers in one value encoding
  };

  enum OprShift : uintptr_t {
      kind_shift     = 0
    , type_shift     = kind_shift     + kind_bits
    , size_shift     = type_shift     + type_bits
    , destroys_shift = size_shift     + size_bits
    , last_use_shift = destroys_shift + destroys_bits
    , is_fpu_stack_offset_shift = last_use_shift + last_use_bits
    , virtual_shift  = is_fpu_stack_offset_shift + is_fpu_stack_offset_bits
    , is_xmm_shift   = virtual_shift + virtual_bits
    , data_shift     = is_xmm_shift + is_xmm_bits
    , reg1_shift = data_shift
    , reg2_shift = data_shift + reg_bits

  };

  enum OprSize {
      single_size = 0 << size_shift
    , double_size = 1 << size_shift
  };

  enum OprMask {
      kind_mask      = right_n_bits(kind_bits)
    , type_mask      = right_n_bits(type_bits) << type_shift
    , size_mask      = right_n_bits(size_bits) << size_shift
    , last_use_mask  = right_n_bits(last_use_bits) << last_use_shift
    , is_fpu_stack_offset_mask = right_n_bits(is_fpu_stack_offset_bits) << is_fpu_stack_offset_shift
    , virtual_mask   = right_n_bits(virtual_bits) << virtual_shift
    , is_xmm_mask    = right_n_bits(is_xmm_bits) << is_xmm_shift
    , pointer_mask   = right_n_bits(pointer_bits)
    , lower_reg_mask = right_n_bits(reg_bits)
    , no_type_mask   = (int)(~(type_mask | last_use_mask | is_fpu_stack_offset_mask))
  };

  uint32_t data() const                          { return (uint32_t)value() >> data_shift; }
  int lo_reg_half() const                        { return data() & lower_reg_mask; }
  int hi_reg_half() const                        { return (data() >> reg_bits) & lower_reg_mask; }
  OprKind kind_field() const                     { return (OprKind)(value() & kind_mask); }
  OprSize size_field() const                     { return (OprSize)(value() & size_mask); }

  static char type_char(BasicType t);

 public:
  LIR_Opr() : _value(0) {}
  LIR_Opr(intptr_t val) : _value(val) {}
  LIR_Opr(LIR_OprPtr *val) : _value(reinterpret_cast<intptr_t>(val)) {}
  bool operator==(const LIR_Opr &other) const { return _value == other._value; }
  bool operator!=(const LIR_Opr &other) const { return _value != other._value; }
  explicit operator bool() const { return _value != 0; }

  // UGLY HACK: make this value object look like a pointer (to itself). This
  // operator overload should be removed, and all callers updated from
  // `opr->fn()` to `opr.fn()`.
  const LIR_Opr* operator->() const { return this; }
  LIR_Opr* operator->() { return this; }

  enum {
    vreg_base = ConcreteRegisterImpl::number_of_registers,
    data_max = (1 << data_bits) - 1,      // max unsigned value for data bit field
    vreg_limit =  10000,                  // choose a reasonable limit,
    vreg_max = MIN2(vreg_limit, data_max) // and make sure if fits in the bit field
  };

  static inline LIR_Opr illegalOpr();
  static inline LIR_Opr nullOpr();

  enum OprType {
      unknown_type  = 0 << type_shift    // means: not set (catch uninitialized types)
    , int_type      = 1 << type_shift
    , long_type     = 2 << type_shift
    , object_type   = 3 << type_shift
    , address_type  = 4 << type_shift
    , float_type    = 5 << type_shift
    , double_type   = 6 << type_shift
    , metadata_type = 7 << type_shift
  };
  friend OprType as_OprType(BasicType t);
  friend BasicType as_BasicType(OprType t);

  OprType type_field_valid() const               { assert(is_register() || is_stack(), "should not be called otherwise"); return (OprType)(value() & type_mask); }
  OprType type_field() const                     { return is_illegal() ? unknown_type : (OprType)(value() & type_mask); }

  static OprSize size_for(BasicType t) {
    switch (t) {
      case T_LONG:
      case T_DOUBLE:
        return double_size;
        break;

      case T_FLOAT:
      case T_BOOLEAN:
      case T_CHAR:
      case T_BYTE:
      case T_SHORT:
      case T_INT:
      case T_ADDRESS:
      case T_OBJECT:
      case T_ARRAY:
      case T_METADATA:
        return single_size;
        break;

      default:
        ShouldNotReachHere();
        return single_size;
      }
  }


  void validate_type() const PRODUCT_RETURN;

  BasicType type() const {
    if (is_pointer()) {
      return pointer()->type();
    }
    return as_BasicType(type_field());
  }


  ValueType* value_type() const                  { return as_ValueType(type()); }

  char type_char() const                         { return type_char((is_pointer()) ? pointer()->type() : type()); }

  bool is_equal(LIR_Opr opr) const         { return *this == opr; }
  // checks whether types are same
  bool is_same_type(LIR_Opr opr) const     {
    assert(type_field() != unknown_type &&
           opr->type_field() != unknown_type, "shouldn't see unknown_type");
    return type_field() == opr->type_field();
  }
  bool is_same_register(LIR_Opr opr) {
    return (is_register() && opr->is_register() &&
            kind_field() == opr->kind_field() &&
            (value() & no_type_mask) == (opr->value() & no_type_mask));
  }

  bool is_pointer() const      { return check_value_mask(pointer_mask, pointer_value); }
  bool is_illegal() const      { return kind_field() == illegal_value; }
  bool is_valid() const        { return kind_field() != illegal_value; }

  bool is_register() const     { return is_cpu_register() || is_fpu_register(); }
  bool is_virtual() const      { return is_virtual_cpu()  || is_virtual_fpu();  }

  bool is_constant() const     { return is_pointer() && pointer()->as_constant() != NULL; }
  bool is_address() const      { return is_pointer() && pointer()->as_address() != NULL; }

  bool is_float_kind() const   { return is_pointer() ? pointer()->is_float_kind() : (kind_field() == fpu_register); }
  bool is_oop() const;

  // semantic for fpu- and xmm-registers:
  // * is_float and is_double return true for xmm_registers
  //   (so is_single_fpu and is_single_xmm are true)
  // * So you must always check for is_???_xmm prior to is_???_fpu to
  //   distinguish between fpu- and xmm-registers

  bool is_stack() const        { validate_type(); return check_value_mask(kind_mask,                stack_value);                 }
  bool is_single_stack() const { validate_type(); return check_value_mask(kind_mask | size_mask,    stack_value  | single_size);  }
  bool is_double_stack() const { validate_type(); return check_value_mask(kind_mask | size_mask,    stack_value  | double_size);  }

  bool is_cpu_register() const { validate_type(); return check_value_mask(kind_mask,                cpu_register);                }
  bool is_virtual_cpu() const  { validate_type(); return check_value_mask(kind_mask | virtual_mask, cpu_register | virtual_mask); }
  bool is_fixed_cpu() const    { validate_type(); return check_value_mask(kind_mask | virtual_mask, cpu_register);                }
  bool is_single_cpu() const   { validate_type(); return check_value_mask(kind_mask | size_mask,    cpu_register | single_size);  }
  bool is_double_cpu() const   { validate_type(); return check_value_mask(kind_mask | size_mask,    cpu_register | double_size);  }

  bool is_fpu_register() const { validate_type(); return check_value_mask(kind_mask,                fpu_register);                }
  bool is_virtual_fpu() const  { validate_type(); return check_value_mask(kind_mask | virtual_mask, fpu_register | virtual_mask); }
  bool is_fixed_fpu() const    { validate_type(); return check_value_mask(kind_mask | virtual_mask, fpu_register);                }
  bool is_single_fpu() const   { validate_type(); return check_value_mask(kind_mask | size_mask,    fpu_register | single_size);  }
  bool is_double_fpu() const   { validate_type(); return check_value_mask(kind_mask | size_mask,    fpu_register | double_size);  }

  bool is_xmm_register() const { validate_type(); return check_value_mask(kind_mask | is_xmm_mask,             fpu_register | is_xmm_mask); }
  bool is_single_xmm() const   { validate_type(); return check_value_mask(kind_mask | size_mask | is_xmm_mask, fpu_register | single_size | is_xmm_mask); }
  bool is_double_xmm() const   { validate_type(); return check_value_mask(kind_mask | size_mask | is_xmm_mask, fpu_register | double_size | is_xmm_mask); }

  // fast accessor functions for special bits that do not work for pointers
  // (in this functions, the check for is_pointer() is omitted)
  bool is_single_word() const      { assert(is_register() || is_stack(), "type check"); return check_value_mask(size_mask, single_size); }
  bool is_double_word() const      { assert(is_register() || is_stack(), "type check"); return check_value_mask(size_mask, double_size); }
  bool is_virtual_register() const { assert(is_register(),               "type check"); return check_value_mask(virtual_mask, virtual_mask); }
  bool is_oop_register() const     { assert(is_register() || is_stack(), "type check"); return type_field_valid() == object_type; }
  BasicType type_register() const  { assert(is_register() || is_stack(), "type check"); return as_BasicType(type_field_valid());  }

  bool is_last_use() const         { assert(is_register(), "only works for registers"); return (value() & last_use_mask) != 0; }
  bool is_fpu_stack_offset() const { assert(is_register(), "only works for registers"); return (value() & is_fpu_stack_offset_mask) != 0; }
  LIR_Opr make_last_use()          { assert(is_register(), "only works for registers"); return (LIR_Opr)(value() | last_use_mask); }
  LIR_Opr make_fpu_stack_offset()  { assert(is_register(), "only works for registers"); return (LIR_Opr)(value() | is_fpu_stack_offset_mask); }


  int single_stack_ix() const  { assert(is_single_stack() && !is_virtual(), "type check"); return (int)data(); }
  int double_stack_ix() const  { assert(is_double_stack() && !is_virtual(), "type check"); return (int)data(); }
  RegNr cpu_regnr() const      { assert(is_single_cpu()   && !is_virtual(), "type check"); return (RegNr)data(); }
  RegNr cpu_regnrLo() const    { assert(is_double_cpu()   && !is_virtual(), "type check"); return (RegNr)lo_reg_half(); }
  RegNr cpu_regnrHi() const    { assert(is_double_cpu()   && !is_virtual(), "type check"); return (RegNr)hi_reg_half(); }
  RegNr fpu_regnr() const      { assert(is_single_fpu()   && !is_virtual(), "type check"); return (RegNr)data(); }
  RegNr fpu_regnrLo() const    { assert(is_double_fpu()   && !is_virtual(), "type check"); return (RegNr)lo_reg_half(); }
  RegNr fpu_regnrHi() const    { assert(is_double_fpu()   && !is_virtual(), "type check"); return (RegNr)hi_reg_half(); }
  RegNr xmm_regnr() const      { assert(is_single_xmm()   && !is_virtual(), "type check"); return (RegNr)data(); }
  RegNr xmm_regnrLo() const    { assert(is_double_xmm()   && !is_virtual(), "type check"); return (RegNr)lo_reg_half(); }
  RegNr xmm_regnrHi() const    { assert(is_double_xmm()   && !is_virtual(), "type check"); return (RegNr)hi_reg_half(); }
  int   vreg_number() const    { assert(is_virtual(),                       "type check"); return (RegNr)data(); }

  LIR_OprPtr* pointer() const { assert(_value != 0 && is_pointer(), "nullness and type check"); return (LIR_OprPtr*)_value; }
  LIR_Const* as_constant_ptr() const             { return pointer()->as_constant(); }
  LIR_Address* as_address_ptr() const            { return pointer()->as_address(); }

  Register as_register()    const;
  Register as_register_lo() const;
  Register as_register_hi() const;

  Register as_pointer_register() {
#ifdef _LP64
    if (is_double_cpu()) {
      assert(as_register_lo() == as_register_hi(), "should be a single register");
      return as_register_lo();
    }
#endif
    return as_register();
  }

  FloatRegister as_float_reg   () const;
  FloatRegister as_double_reg  () const;
#ifdef X86
  XMMRegister as_xmm_float_reg () const;
  XMMRegister as_xmm_double_reg() const;
  // for compatibility with RInfo
  int fpu() const { return lo_reg_half(); }
#endif

  jint      as_jint()    const { return as_constant_ptr()->as_jint(); }
  jlong     as_jlong()   const { return as_constant_ptr()->as_jlong(); }
  jfloat    as_jfloat()  const { return as_constant_ptr()->as_jfloat(); }
  jdouble   as_jdouble() const { return as_constant_ptr()->as_jdouble(); }
  jobject   as_jobject() const { return as_constant_ptr()->as_jobject(); }

  void print() const PRODUCT_RETURN;
  void print(outputStream* out) const PRODUCT_RETURN;
};

inline LIR_Opr::OprType as_OprType(BasicType type) {
  switch (type) {
  case T_INT:      return LIR_Opr::int_type;
  case T_LONG:     return LIR_Opr::long_type;
  case T_FLOAT:    return LIR_Opr::float_type;
  case T_DOUBLE:   return LIR_Opr::double_type;
  case T_OBJECT:
  case T_ARRAY:    return LIR_Opr::object_type;
  case T_ADDRESS:  return LIR_Opr::address_type;
  case T_METADATA: return LIR_Opr::metadata_type;
  case T_ILLEGAL:  // fall through
  default: ShouldNotReachHere(); return LIR_Opr::unknown_type;
  }
}

inline BasicType as_BasicType(LIR_Opr::OprType t) {
  switch (t) {
  case LIR_Opr::int_type:     return T_INT;
  case LIR_Opr::long_type:    return T_LONG;
  case LIR_Opr::float_type:   return T_FLOAT;
  case LIR_Opr::double_type:  return T_DOUBLE;
  case LIR_Opr::object_type:  return T_OBJECT;
  case LIR_Opr::address_type: return T_ADDRESS;
  case LIR_Opr::metadata_type:return T_METADATA;
  case LIR_Opr::unknown_type: // fall through
  default: ShouldNotReachHere();  return T_ILLEGAL;
  }
}


// LIR_Address
class LIR_Address: public LIR_OprPtr {
 friend class LIR_OpVisitState;

 public:
  // NOTE: currently these must be the log2 of the scale factor (and
  // must also be equivalent to the ScaleFactor enum in
  // assembler_i486.hpp)
  enum Scale {
    times_1  =  0,
    times_2  =  1,
    times_4  =  2,
    times_8  =  3
  };

 private:
  LIR_Opr   _base;
  LIR_Opr   _index;
  Scale     _scale;
  intx      _disp;
  BasicType _type;

 public:
  LIR_Address(LIR_Opr base, LIR_Opr index, BasicType type):
       _base(base)
     , _index(index)
     , _scale(times_1)
     , _disp(0)
     , _type(type) { verify(); }

  LIR_Address(LIR_Opr base, intx disp, BasicType type):
       _base(base)
     , _index(LIR_Opr::illegalOpr())
     , _scale(times_1)
     , _disp(disp)
     , _type(type) { verify(); }

  LIR_Address(LIR_Opr base, BasicType type):
       _base(base)
     , _index(LIR_Opr::illegalOpr())
     , _scale(times_1)
     , _disp(0)
     , _type(type) { verify(); }

  LIR_Address(LIR_Opr base, LIR_Opr index, intx disp, BasicType type):
       _base(base)
     , _index(index)
     , _scale(times_1)
     , _disp(disp)
     , _type(type) { verify(); }

  LIR_Address(LIR_Opr base, LIR_Opr index, Scale scale, intx disp, BasicType type):
       _base(base)
     , _index(index)
     , _scale(scale)
     , _disp(disp)
     , _type(type) { verify(); }

  LIR_Opr base()  const                          { return _base;  }
  LIR_Opr index() const                          { return _index; }
  Scale   scale() const                          { return _scale; }
  intx    disp()  const                          { return _disp;  }

  bool equals(LIR_Address* other) const          { return base() == other->base() && index() == other->index() && disp() == other->disp() && scale() == other->scale(); }

  virtual LIR_Address* as_address()              { return this;   }
  virtual BasicType type() const                 { return _type; }
  virtual void print_value_on(outputStream* out) const PRODUCT_RETURN;

  void verify() const PRODUCT_RETURN;

  static Scale scale(BasicType type);
};


// operand factory
class LIR_OprFact: public AllStatic {
 public:

  static LIR_Opr illegalOpr;
  static LIR_Opr nullOpr;

  static LIR_Opr single_cpu(int reg) {
    return (LIR_Opr)(intptr_t)((reg  << LIR_Opr::reg1_shift) |
                               LIR_Opr::int_type             |
                               LIR_Opr::cpu_register         |
                               LIR_Opr::single_size);
  }
  static LIR_Opr single_cpu_oop(int reg) {
    return (LIR_Opr)(intptr_t)((reg  << LIR_Opr::reg1_shift) |
                               LIR_Opr::object_type          |
                               LIR_Opr::cpu_register         |
                               LIR_Opr::single_size);
  }
  static LIR_Opr single_cpu_address(int reg) {
    return (LIR_Opr)(intptr_t)((reg  << LIR_Opr::reg1_shift) |
                               LIR_Opr::address_type         |
                               LIR_Opr::cpu_register         |
                               LIR_Opr::single_size);
  }
  static LIR_Opr single_cpu_metadata(int reg) {
    return (LIR_Opr)(intptr_t)((reg  << LIR_Opr::reg1_shift) |
                               LIR_Opr::metadata_type        |
                               LIR_Opr::cpu_register         |
                               LIR_Opr::single_size);
  }
  static LIR_Opr double_cpu(int reg1, int reg2) {
    LP64_ONLY(assert(reg1 == reg2, "must be identical"));
    return (LIR_Opr)(intptr_t)((reg1 << LIR_Opr::reg1_shift) |
                               (reg2 << LIR_Opr::reg2_shift) |
                               LIR_Opr::long_type            |
                               LIR_Opr::cpu_register         |
                               LIR_Opr::double_size);
  }

  static LIR_Opr single_fpu(int reg) {
    return (LIR_Opr)(intptr_t)((reg  << LIR_Opr::reg1_shift) |
                               LIR_Opr::float_type           |
                               LIR_Opr::fpu_register         |
                               LIR_Opr::single_size);
  }

  // Platform dependent.
  static LIR_Opr double_fpu(int reg1, int reg2 = -1 /*fnoreg*/);

#ifdef ARM32
  static LIR_Opr single_softfp(int reg) {
    return (LIR_Opr)(intptr_t)((reg  << LIR_Opr::reg1_shift) |
                               LIR_Opr::float_type           |
                               LIR_Opr::cpu_register         |
                               LIR_Opr::single_size);
  }
  static LIR_Opr double_softfp(int reg1, int reg2) {
    return (LIR_Opr)(intptr_t)((reg1 << LIR_Opr::reg1_shift) |
                               (reg2 << LIR_Opr::reg2_shift) |
                               LIR_Opr::double_type          |
                               LIR_Opr::cpu_register         |
                               LIR_Opr::double_size);
  }
#endif // ARM32

#if defined(X86)
  static LIR_Opr single_xmm(int reg) {
    return (LIR_Opr)(intptr_t)((reg << LIR_Opr::reg1_shift) |
                               LIR_Opr::float_type          |
                               LIR_Opr::fpu_register        |
                               LIR_Opr::single_size         |
                               LIR_Opr::is_xmm_mask);
  }
  static LIR_Opr double_xmm(int reg) {
    return (LIR_Opr)(intptr_t)((reg << LIR_Opr::reg1_shift) |
                               (reg << LIR_Opr::reg2_shift) |
                               LIR_Opr::double_type         |
                               LIR_Opr::fpu_register        |
                               LIR_Opr::double_size         |
                               LIR_Opr::is_xmm_mask);
  }
#endif // X86

  static LIR_Opr virtual_register(int index, BasicType type) {
    if (index > LIR_Opr::vreg_max) {
      // Running out of virtual registers. Caller should bailout.
      return illegalOpr;
    }

    LIR_Opr res;
    switch (type) {
      case T_OBJECT: // fall through
      case T_ARRAY:
        res = (LIR_Opr)(intptr_t)((index << LIR_Opr::data_shift)  |
                                            LIR_Opr::object_type  |
                                            LIR_Opr::cpu_register |
                                            LIR_Opr::single_size  |
                                            LIR_Opr::virtual_mask);
        break;

      case T_METADATA:
        res = (LIR_Opr)(intptr_t)((index << LIR_Opr::data_shift)  |
                                            LIR_Opr::metadata_type|
                                            LIR_Opr::cpu_register |
                                            LIR_Opr::single_size  |
                                            LIR_Opr::virtual_mask);
        break;

      case T_INT:
        res = (LIR_Opr)(intptr_t)((index << LIR_Opr::data_shift) |
                                  LIR_Opr::int_type              |
                                  LIR_Opr::cpu_register          |
                                  LIR_Opr::single_size           |
                                  LIR_Opr::virtual_mask);
        break;

      case T_ADDRESS:
        res = (LIR_Opr)(intptr_t)((index << LIR_Opr::data_shift) |
                                  LIR_Opr::address_type          |
                                  LIR_Opr::cpu_register          |
                                  LIR_Opr::single_size           |
                                  LIR_Opr::virtual_mask);
        break;

      case T_LONG:
        res = (LIR_Opr)(intptr_t)((index << LIR_Opr::data_shift) |
                                  LIR_Opr::long_type             |
                                  LIR_Opr::cpu_register          |
                                  LIR_Opr::double_size           |
                                  LIR_Opr::virtual_mask);
        break;

#ifdef __SOFTFP__
      case T_FLOAT:
        res = (LIR_Opr)(intptr_t)((index << LIR_Opr::data_shift) |
                                  LIR_Opr::float_type  |
                                  LIR_Opr::cpu_register |
                                  LIR_Opr::single_size |
                                  LIR_Opr::virtual_mask);
        break;
      case T_DOUBLE:
        res = (LIR_Opr)(intptr_t)((index << LIR_Opr::data_shift) |
                                  LIR_Opr::double_type |
                                  LIR_Opr::cpu_register |
                                  LIR_Opr::double_size |
                                  LIR_Opr::virtual_mask);
        break;
#else // __SOFTFP__
      case T_FLOAT:
        res = (LIR_Opr)(intptr_t)((index << LIR_Opr::data_shift) |
                                  LIR_Opr::float_type           |
                                  LIR_Opr::fpu_register         |
                                  LIR_Opr::single_size          |
                                  LIR_Opr::virtual_mask);
        break;

      case
        T_DOUBLE: res = (LIR_Opr)(intptr_t)((index << LIR_Opr::data_shift) |
                                            LIR_Opr::double_type           |
                                            LIR_Opr::fpu_register          |
                                            LIR_Opr::double_size           |
                                            LIR_Opr::virtual_mask);
        break;
#endif // __SOFTFP__
      default:       ShouldNotReachHere(); res = illegalOpr;
    }

#ifdef ASSERT
    res->validate_type();
    assert(res->vreg_number() == index, "conversion check");
    assert(index >= LIR_Opr::vreg_base, "must start at vreg_base");

    // old-style calculation; check if old and new method are equal
    LIR_Opr::OprType t = as_OprType(type);
#ifdef __SOFTFP__
    LIR_Opr old_res = (LIR_Opr)(intptr_t)((index << LIR_Opr::data_shift) |
                               t |
                               LIR_Opr::cpu_register |
                               LIR_Opr::size_for(type) | LIR_Opr::virtual_mask);
#else // __SOFTFP__
    LIR_Opr old_res = (LIR_Opr)(intptr_t)((index << LIR_Opr::data_shift) | t |
                                          ((type == T_FLOAT || type == T_DOUBLE) ?  LIR_Opr::fpu_register : LIR_Opr::cpu_register) |
                               LIR_Opr::size_for(type) | LIR_Opr::virtual_mask);
    assert(res == old_res, "old and new method not equal");
#endif // __SOFTFP__
#endif // ASSERT

    return res;
  }

  // 'index' is computed by FrameMap::local_stack_pos(index); do not use other parameters as
  // the index is platform independent; a double stack using indices 2 and 3 has always
  // index 2.
  static LIR_Opr stack(int index, BasicType type) {
    LIR_Opr res;
    switch (type) {
      case T_OBJECT: // fall through
      case T_ARRAY:
        res = (LIR_Opr)(intptr_t)((index << LIR_Opr::data_shift) |
                                  LIR_Opr::object_type           |
                                  LIR_Opr::stack_value           |
                                  LIR_Opr::single_size);
        break;

      case T_METADATA:
        res = (LIR_Opr)(intptr_t)((index << LIR_Opr::data_shift) |
                                  LIR_Opr::metadata_type         |
                                  LIR_Opr::stack_value           |
                                  LIR_Opr::single_size);
        break;
      case T_INT:
        res = (LIR_Opr)(intptr_t)((index << LIR_Opr::data_shift) |
                                  LIR_Opr::int_type              |
                                  LIR_Opr::stack_value           |
                                  LIR_Opr::single_size);
        break;

      case T_ADDRESS:
        res = (LIR_Opr)(intptr_t)((index << LIR_Opr::data_shift) |
                                  LIR_Opr::address_type          |
                                  LIR_Opr::stack_value           |
                                  LIR_Opr::single_size);
        break;

      case T_LONG:
        res = (LIR_Opr)(intptr_t)((index << LIR_Opr::data_shift) |
                                  LIR_Opr::long_type             |
                                  LIR_Opr::stack_value           |
                                  LIR_Opr::double_size);
        break;

      case T_FLOAT:
        res = (LIR_Opr)(intptr_t)((index << LIR_Opr::data_shift) |
                                  LIR_Opr::float_type            |
                                  LIR_Opr::stack_value           |
                                  LIR_Opr::single_size);
        break;
      case T_DOUBLE:
        res = (LIR_Opr)(intptr_t)((index << LIR_Opr::data_shift) |
                                  LIR_Opr::double_type           |
                                  LIR_Opr::stack_value           |
                                  LIR_Opr::double_size);
        break;

      default:       ShouldNotReachHere(); res = illegalOpr;
    }

#ifdef ASSERT
    assert(index >= 0, "index must be positive");
    assert(index == (int)res->data(), "conversion check");

    LIR_Opr old_res = (LIR_Opr)(intptr_t)((index << LIR_Opr::data_shift) |
                                          LIR_Opr::stack_value           |
                                          as_OprType(type)                   |
                                          LIR_Opr::size_for(type));
    assert(res == old_res, "old and new method not equal");
#endif

    return res;
  }

  static LIR_Opr intConst(jint i)                { return (LIR_Opr)(new LIR_Const(i)); }
  static LIR_Opr longConst(jlong l)              { return (LIR_Opr)(new LIR_Const(l)); }
  static LIR_Opr floatConst(jfloat f)            { return (LIR_Opr)(new LIR_Const(f)); }
  static LIR_Opr doubleConst(jdouble d)          { return (LIR_Opr)(new LIR_Const(d)); }
  static LIR_Opr oopConst(jobject o)             { return (LIR_Opr)(new LIR_Const(o)); }
  static LIR_Opr address(LIR_Address* a)         { return (LIR_Opr)a; }
  static LIR_Opr intptrConst(void* p)            { return (LIR_Opr)(new LIR_Const(p)); }
  static LIR_Opr intptrConst(intptr_t v)         { return (LIR_Opr)(new LIR_Const((void*)v)); }
  static LIR_Opr illegal()                       { return (LIR_Opr)-1; }
  static LIR_Opr addressConst(jint i)            { return (LIR_Opr)(new LIR_Const(i, true)); }
  static LIR_Opr metadataConst(Metadata* m)      { return (LIR_Opr)(new LIR_Const(m)); }

  static LIR_Opr value_type(ValueType* type);
};


//-------------------------------------------------------------------------------
//                   LIR Instructions
//-------------------------------------------------------------------------------
//
// Note:
//  - every instruction has a result operand
//  - every instruction has an CodeEmitInfo operand (can be revisited later)
//  - every instruction has a LIR_OpCode operand
//  - LIR_OpN, means an instruction that has N input operands
//
// class hierarchy:
//
class  LIR_Op;
class    LIR_Op0;
class      LIR_OpLabel;
class    LIR_Op1;
class      LIR_OpBranch;
class      LIR_OpConvert;
class      LIR_OpAllocObj;
class      LIR_OpReturn;
class      LIR_OpRoundFP;
class    LIR_Op2;
class    LIR_OpDelay;
class    LIR_Op3;
class      LIR_OpAllocArray;
class    LIR_Op4;
class    LIR_OpCall;
class      LIR_OpJavaCall;
class      LIR_OpRTCall;
class    LIR_OpArrayCopy;
class    LIR_OpUpdateCRC32;
class    LIR_OpLock;
class    LIR_OpTypeCheck;
class    LIR_OpCompareAndSwap;
class    LIR_OpLoadKlass;
class    LIR_OpProfileCall;
class    LIR_OpProfileType;
#ifdef ASSERT
class    LIR_OpAssert;
#endif

// LIR operation codes
enum LIR_Code {
    lir_none
  , begin_op0
      , lir_label
      , lir_nop
      , lir_std_entry
      , lir_osr_entry
      , lir_fpop_raw
      , lir_breakpoint
      , lir_rtcall
      , lir_membar
      , lir_membar_acquire
      , lir_membar_release
      , lir_membar_loadload
      , lir_membar_storestore
      , lir_membar_loadstore
      , lir_membar_storeload
      , lir_get_thread
      , lir_on_spin_wait
  , end_op0
  , begin_op1
      , lir_fxch
      , lir_fld
      , lir_push
      , lir_pop
      , lir_null_check
      , lir_return
      , lir_leal
      , lir_move
      , lir_convert
      , lir_alloc_object
      , lir_monaddr
      , lir_roundfp
      , lir_safepoint
      , lir_unwind
      , lir_load_klass
  , end_op1
  , begin_op2
      , lir_branch
      , lir_cond_float_branch
      , lir_cmp
      , lir_cmp_l2i
      , lir_ucmp_fd2i
      , lir_cmp_fd2i
      , lir_add
      , lir_sub
      , lir_mul
      , lir_div
      , lir_rem
      , lir_sqrt
      , lir_abs
      , lir_neg
      , lir_tan
      , lir_log10
      , lir_logic_and
      , lir_logic_or
      , lir_logic_xor
      , lir_shl
      , lir_shr
      , lir_ushr
      , lir_alloc_array
      , lir_throw
      , lir_xadd
      , lir_xchg
  , end_op2
  , begin_op3
      , lir_idiv
      , lir_irem
      , lir_fmad
      , lir_fmaf
  , end_op3
  , begin_op4
      , lir_cmove
  , end_op4
  , begin_opJavaCall
      , lir_static_call
      , lir_optvirtual_call
      , lir_icvirtual_call
      , lir_dynamic_call
  , end_opJavaCall
  , begin_opArrayCopy
      , lir_arraycopy
  , end_opArrayCopy
  , begin_opUpdateCRC32
      , lir_updatecrc32
  , end_opUpdateCRC32
  , begin_opLock
    , lir_lock
    , lir_unlock
  , end_opLock
  , begin_delay_slot
    , lir_delay_slot
  , end_delay_slot
  , begin_opTypeCheck
    , lir_instanceof
    , lir_checkcast
    , lir_store_check
  , end_opTypeCheck
  , begin_opCompareAndSwap
    , lir_cas_long
    , lir_cas_obj
    , lir_cas_int
  , end_opCompareAndSwap
  , begin_opMDOProfile
    , lir_profile_call
    , lir_profile_type
  , end_opMDOProfile
  , begin_opAssert
    , lir_assert
  , end_opAssert
#ifdef INCLUDE_ZGC
  , begin_opZLoadBarrierTest
    , lir_zloadbarrier_test
  , end_opZLoadBarrierTest
#endif
};


enum LIR_Condition {
    lir_cond_equal
  , lir_cond_notEqual
  , lir_cond_less
  , lir_cond_lessEqual
  , lir_cond_greaterEqual
  , lir_cond_greater
  , lir_cond_belowEqual
  , lir_cond_aboveEqual
  , lir_cond_always
  , lir_cond_unknown = -1
};


enum LIR_PatchCode {
  lir_patch_none,
  lir_patch_low,
  lir_patch_high,
  lir_patch_normal
};


enum LIR_MoveKind {
  lir_move_normal,
  lir_move_volatile,
  lir_move_wide,
  lir_move_max_flag
};


// --------------------------------------------------
// LIR_Op
// --------------------------------------------------
class LIR_Op: public CompilationResourceObj {
 friend class LIR_OpVisitState;

#ifdef ASSERT
 private:
  const char *  _file;
  int           _line;
#endif

 protected:
  LIR_Opr       _result;
  unsigned short _code;
  unsigned short _flags;
  CodeEmitInfo* _info;
  int           _id;     // value id for register allocation
  int           _fpu_pop_count;
  Instruction*  _source; // for debugging

  static void print_condition(outputStream* out, LIR_Condition cond) PRODUCT_RETURN;

 protected:
  static bool is_in_range(LIR_Code test, LIR_Code start, LIR_Code end)  { return start < test && test < end; }

 public:
  LIR_Op()
    :
#ifdef ASSERT
      _file(NULL)
    , _line(0),
#endif
      _result(LIR_OprFact::illegalOpr)
    , _code(lir_none)
    , _flags(0)
    , _info(NULL)
    , _id(-1)
    , _fpu_pop_count(0)
    , _source(NULL) {}

  LIR_Op(LIR_Code code, LIR_Opr result, CodeEmitInfo* info)
    :
#ifdef ASSERT
      _file(NULL)
    , _line(0),
#endif
      _result(result)
    , _code(code)
    , _flags(0)
    , _info(info)
    , _id(-1)
    , _fpu_pop_count(0)
    , _source(NULL) {}

  CodeEmitInfo* info() const                  { return _info;   }
  LIR_Code code()      const                  { return (LIR_Code)_code;   }
  LIR_Opr result_opr() const                  { return _result; }
  void    set_result_opr(LIR_Opr opr)         { _result = opr;  }

#ifdef ASSERT
  void set_file_and_line(const char * file, int line) {
    _file = file;
    _line = line;
  }
#endif

  virtual const char * name() const PRODUCT_RETURN0;
  virtual void visit(LIR_OpVisitState* state);

  int id()             const                  { return _id;     }
  void set_id(int id)                         { _id = id; }

  // FPU stack simulation helpers -- only used on Intel
  void set_fpu_pop_count(int count)           { assert(count >= 0 && count <= 1, "currently only 0 and 1 are valid"); _fpu_pop_count = count; }
  int  fpu_pop_count() const                  { return _fpu_pop_count; }
  bool pop_fpu_stack()                        { return _fpu_pop_count > 0; }

  Instruction* source() const                 { return _source; }
  void set_source(Instruction* ins)           { _source = ins; }

  virtual void emit_code(LIR_Assembler* masm) = 0;
  virtual void print_instr(outputStream* out) const   = 0;
  virtual void print_on(outputStream* st) const PRODUCT_RETURN;

  virtual bool is_patching() { return false; }
  virtual LIR_OpCall* as_OpCall() { return NULL; }
  virtual LIR_OpJavaCall* as_OpJavaCall() { return NULL; }
  virtual LIR_OpLabel* as_OpLabel() { return NULL; }
  virtual LIR_OpDelay* as_OpDelay() { return NULL; }
  virtual LIR_OpLock* as_OpLock() { return NULL; }
  virtual LIR_OpAllocArray* as_OpAllocArray() { return NULL; }
  virtual LIR_OpAllocObj* as_OpAllocObj() { return NULL; }
  virtual LIR_OpRoundFP* as_OpRoundFP() { return NULL; }
  virtual LIR_OpBranch* as_OpBranch() { return NULL; }
  virtual LIR_OpReturn* as_OpReturn() { return NULL; }
  virtual LIR_OpRTCall* as_OpRTCall() { return NULL; }
  virtual LIR_OpConvert* as_OpConvert() { return NULL; }
  virtual LIR_Op0* as_Op0() { return NULL; }
  virtual LIR_Op1* as_Op1() { return NULL; }
  virtual LIR_Op2* as_Op2() { return NULL; }
  virtual LIR_Op3* as_Op3() { return NULL; }
  virtual LIR_Op4* as_Op4() { return NULL; }
  virtual LIR_OpArrayCopy* as_OpArrayCopy() { return NULL; }
  virtual LIR_OpUpdateCRC32* as_OpUpdateCRC32() { return NULL; }
  virtual LIR_OpTypeCheck* as_OpTypeCheck() { return NULL; }
  virtual LIR_OpCompareAndSwap* as_OpCompareAndSwap() { return NULL; }
  virtual LIR_OpLoadKlass* as_OpLoadKlass() { return NULL; }
  virtual LIR_OpProfileCall* as_OpProfileCall() { return NULL; }
  virtual LIR_OpProfileType* as_OpProfileType() { return NULL; }
#ifdef ASSERT
  virtual LIR_OpAssert* as_OpAssert() { return NULL; }
#endif

  virtual void verify() const {}
};

// for calls
class LIR_OpCall: public LIR_Op {
 friend class LIR_OpVisitState;

 protected:
  address      _addr;
  LIR_OprList* _arguments;
 protected:
  LIR_OpCall(LIR_Code code, address addr, LIR_Opr result,
             LIR_OprList* arguments, CodeEmitInfo* info = NULL)
    : LIR_Op(code, result, info)
    , _addr(addr)
    , _arguments(arguments) {}

 public:
  address addr() const                           { return _addr; }
  const LIR_OprList* arguments() const           { return _arguments; }
  virtual LIR_OpCall* as_OpCall()                { return this; }
};


// --------------------------------------------------
// LIR_OpJavaCall
// --------------------------------------------------
class LIR_OpJavaCall: public LIR_OpCall {
 friend class LIR_OpVisitState;

 private:
  ciMethod* _method;
  LIR_Opr   _receiver;
  LIR_Opr   _method_handle_invoke_SP_save_opr;  // Used in LIR_OpVisitState::visit to store the reference to FrameMap::method_handle_invoke_SP_save_opr.

 public:
  LIR_OpJavaCall(LIR_Code code, ciMethod* method,
                 LIR_Opr receiver, LIR_Opr result,
                 address addr, LIR_OprList* arguments,
                 CodeEmitInfo* info)
  : LIR_OpCall(code, addr, result, arguments, info)
  , _method(method)
  , _receiver(receiver)
  , _method_handle_invoke_SP_save_opr(LIR_OprFact::illegalOpr)
  { assert(is_in_range(code, begin_opJavaCall, end_opJavaCall), "code check"); }

  LIR_OpJavaCall(LIR_Code code, ciMethod* method,
                 LIR_Opr receiver, LIR_Opr result, intptr_t vtable_offset,
                 LIR_OprList* arguments, CodeEmitInfo* info)
  : LIR_OpCall(code, (address)vtable_offset, result, arguments, info)
  , _method(method)
  , _receiver(receiver)
  , _method_handle_invoke_SP_save_opr(LIR_OprFact::illegalOpr)
  { assert(is_in_range(code, begin_opJavaCall, end_opJavaCall), "code check"); }

  LIR_Opr receiver() const                       { return _receiver; }
  ciMethod* method() const                       { return _method;   }

  // JSR 292 support.
  bool is_invokedynamic() const                  { return code() == lir_dynamic_call; }
  bool is_method_handle_invoke() const {
    return method()->is_compiled_lambda_form() ||   // Java-generated lambda form
           method()->is_method_handle_intrinsic();  // JVM-generated MH intrinsic
  }

  virtual void emit_code(LIR_Assembler* masm);
  virtual LIR_OpJavaCall* as_OpJavaCall() { return this; }
  virtual void print_instr(outputStream* out) const PRODUCT_RETURN;
};

// --------------------------------------------------
// LIR_OpLabel
// --------------------------------------------------
// Location where a branch can continue
class LIR_OpLabel: public LIR_Op {
 friend class LIR_OpVisitState;

 private:
  Label* _label;
 public:
  LIR_OpLabel(Label* lbl)
   : LIR_Op(lir_label, LIR_OprFact::illegalOpr, NULL)
   , _label(lbl)                                 {}
  Label* label() const                           { return _label; }

  virtual void emit_code(LIR_Assembler* masm);
  virtual LIR_OpLabel* as_OpLabel() { return this; }
  virtual void print_instr(outputStream* out) const PRODUCT_RETURN;
};

// LIR_OpArrayCopy
class LIR_OpArrayCopy: public LIR_Op {
 friend class LIR_OpVisitState;

 private:
  ArrayCopyStub*  _stub;
  LIR_Opr   _src;
  LIR_Opr   _src_pos;
  LIR_Opr   _dst;
  LIR_Opr   _dst_pos;
  LIR_Opr   _length;
  LIR_Opr   _tmp;
  ciArrayKlass* _expected_type;
  int       _flags;

public:
  enum Flags {
    src_null_check         = 1 << 0,
    dst_null_check         = 1 << 1,
    src_pos_positive_check = 1 << 2,
    dst_pos_positive_check = 1 << 3,
    length_positive_check  = 1 << 4,
    src_range_check        = 1 << 5,
    dst_range_check        = 1 << 6,
    type_check             = 1 << 7,
    overlapping            = 1 << 8,
    unaligned              = 1 << 9,
    src_objarray           = 1 << 10,
    dst_objarray           = 1 << 11,
    all_flags              = (1 << 12) - 1
  };

  LIR_OpArrayCopy(LIR_Opr src, LIR_Opr src_pos, LIR_Opr dst, LIR_Opr dst_pos, LIR_Opr length, LIR_Opr tmp,
                  ciArrayKlass* expected_type, int flags, CodeEmitInfo* info);

  LIR_Opr src() const                            { return _src; }
  LIR_Opr src_pos() const                        { return _src_pos; }
  LIR_Opr dst() const                            { return _dst; }
  LIR_Opr dst_pos() const                        { return _dst_pos; }
  LIR_Opr length() const                         { return _length; }
  LIR_Opr tmp() const                            { return _tmp; }
  int flags() const                              { return _flags; }
  ciArrayKlass* expected_type() const            { return _expected_type; }
  ArrayCopyStub* stub() const                    { return _stub; }

  virtual void emit_code(LIR_Assembler* masm);
  virtual LIR_OpArrayCopy* as_OpArrayCopy() { return this; }
  void print_instr(outputStream* out) const PRODUCT_RETURN;
};

// LIR_OpUpdateCRC32
class LIR_OpUpdateCRC32: public LIR_Op {
  friend class LIR_OpVisitState;

private:
  LIR_Opr   _crc;
  LIR_Opr   _val;

public:

  LIR_OpUpdateCRC32(LIR_Opr crc, LIR_Opr val, LIR_Opr res);

  LIR_Opr crc() const                            { return _crc; }
  LIR_Opr val() const                            { return _val; }

  virtual void emit_code(LIR_Assembler* masm);
  virtual LIR_OpUpdateCRC32* as_OpUpdateCRC32()  { return this; }
  void print_instr(outputStream* out) const PRODUCT_RETURN;
};

// --------------------------------------------------
// LIR_Op0
// --------------------------------------------------
class LIR_Op0: public LIR_Op {
 friend class LIR_OpVisitState;

 public:
  LIR_Op0(LIR_Code code)
   : LIR_Op(code, LIR_OprFact::illegalOpr, NULL)  { assert(is_in_range(code, begin_op0, end_op0), "code check"); }
  LIR_Op0(LIR_Code code, LIR_Opr result, CodeEmitInfo* info = NULL)
   : LIR_Op(code, result, info)  { assert(is_in_range(code, begin_op0, end_op0), "code check"); }

  virtual void emit_code(LIR_Assembler* masm);
  virtual LIR_Op0* as_Op0() { return this; }
  virtual void print_instr(outputStream* out) const PRODUCT_RETURN;
};


// --------------------------------------------------
// LIR_Op1
// --------------------------------------------------

class LIR_Op1: public LIR_Op {
 friend class LIR_OpVisitState;

 protected:
  LIR_Opr         _opr;   // input operand
  BasicType       _type;  // Operand types
  LIR_PatchCode   _patch; // only required with patchin (NEEDS_CLEANUP: do we want a special instruction for patching?)

  static void print_patch_code(outputStream* out, LIR_PatchCode code);

  void set_kind(LIR_MoveKind kind) {
    assert(code() == lir_move, "must be");
    _flags = kind;
  }

 public:
  LIR_Op1(LIR_Code code, LIR_Opr opr, LIR_Opr result = LIR_OprFact::illegalOpr, BasicType type = T_ILLEGAL, LIR_PatchCode patch = lir_patch_none, CodeEmitInfo* info = NULL)
    : LIR_Op(code, result, info)
    , _opr(opr)
    , _type(type)
    , _patch(patch)                    { assert(is_in_range(code, begin_op1, end_op1), "code check"); }

  LIR_Op1(LIR_Code code, LIR_Opr opr, LIR_Opr result, BasicType type, LIR_PatchCode patch, CodeEmitInfo* info, LIR_MoveKind kind)
    : LIR_Op(code, result, info)
    , _opr(opr)
    , _type(type)
    , _patch(patch)                    {
    assert(code == lir_move, "must be");
    set_kind(kind);
  }

  LIR_Op1(LIR_Code code, LIR_Opr opr, CodeEmitInfo* info)
    : LIR_Op(code, LIR_OprFact::illegalOpr, info)
    , _opr(opr)
    , _type(T_ILLEGAL)
    , _patch(lir_patch_none)           { assert(is_in_range(code, begin_op1, end_op1), "code check"); }

  LIR_Opr in_opr()           const               { return _opr;   }
  LIR_PatchCode patch_code() const               { return _patch; }
  BasicType type()           const               { return _type;  }

  LIR_MoveKind move_kind() const {
    assert(code() == lir_move, "must be");
    return (LIR_MoveKind)_flags;
  }

  virtual bool is_patching() { return _patch != lir_patch_none; }
  virtual void emit_code(LIR_Assembler* masm);
  virtual LIR_Op1* as_Op1() { return this; }
  virtual const char * name() const PRODUCT_RETURN0;

  void set_in_opr(LIR_Opr opr) { _opr = opr; }

  virtual void print_instr(outputStream* out) const PRODUCT_RETURN;
  virtual void verify() const;
};


// for runtime calls
class LIR_OpRTCall: public LIR_OpCall {
 friend class LIR_OpVisitState;

 private:
  LIR_Opr _tmp;
 public:
  LIR_OpRTCall(address addr, LIR_Opr tmp,
               LIR_Opr result, LIR_OprList* arguments, CodeEmitInfo* info = NULL)
    : LIR_OpCall(lir_rtcall, addr, result, arguments, info)
    , _tmp(tmp) {}

  virtual void print_instr(outputStream* out) const PRODUCT_RETURN;
  virtual void emit_code(LIR_Assembler* masm);
  virtual LIR_OpRTCall* as_OpRTCall() { return this; }

  LIR_Opr tmp() const                            { return _tmp; }

  virtual void verify() const;
};



class LIR_OpReturn: public LIR_Op1 {
 friend class LIR_OpVisitState;

 private:
  C1SafepointPollStub* _stub;

 public:
  LIR_OpReturn(LIR_Opr opr);

  C1SafepointPollStub* stub() const { return _stub; }
  virtual LIR_OpReturn* as_OpReturn() { return this; }
};

class ConversionStub;

class LIR_OpConvert: public LIR_Op1 {
 friend class LIR_OpVisitState;

 private:
   Bytecodes::Code _bytecode;
   ConversionStub* _stub;

 public:
   LIR_OpConvert(Bytecodes::Code code, LIR_Opr opr, LIR_Opr result, ConversionStub* stub)
     : LIR_Op1(lir_convert, opr, result)
     , _bytecode(code)
     , _stub(stub)                               {}

  Bytecodes::Code bytecode() const               { return _bytecode; }
  ConversionStub* stub() const                   { return _stub; }

  virtual void emit_code(LIR_Assembler* masm);
  virtual LIR_OpConvert* as_OpConvert() { return this; }
  virtual void print_instr(outputStream* out) const PRODUCT_RETURN;

  static void print_bytecode(outputStream* out, Bytecodes::Code code) PRODUCT_RETURN;
};


// LIR_OpAllocObj
class LIR_OpAllocObj : public LIR_Op1 {
 friend class LIR_OpVisitState;

 private:
  LIR_Opr _tmp1;
  LIR_Opr _tmp2;
  LIR_Opr _tmp3;
  LIR_Opr _tmp4;
  int     _hdr_size;
  int     _obj_size;
  CodeStub* _stub;
  bool    _init_check;

 public:
  LIR_OpAllocObj(LIR_Opr klass, LIR_Opr result,
                 LIR_Opr t1, LIR_Opr t2, LIR_Opr t3, LIR_Opr t4,
                 int hdr_size, int obj_size, bool init_check, CodeStub* stub)
    : LIR_Op1(lir_alloc_object, klass, result)
    , _tmp1(t1)
    , _tmp2(t2)
    , _tmp3(t3)
    , _tmp4(t4)
    , _hdr_size(hdr_size)
    , _obj_size(obj_size)
    , _stub(stub)
    , _init_check(init_check)                    { }

  LIR_Opr klass()        const                   { return in_opr();     }
  LIR_Opr obj()          const                   { return result_opr(); }
  LIR_Opr tmp1()         const                   { return _tmp1;        }
  LIR_Opr tmp2()         const                   { return _tmp2;        }
  LIR_Opr tmp3()         const                   { return _tmp3;        }
  LIR_Opr tmp4()         const                   { return _tmp4;        }
  int     header_size()  const                   { return _hdr_size;    }
  int     object_size()  const                   { return _obj_size;    }
  bool    init_check()   const                   { return _init_check;  }
  CodeStub* stub()       const                   { return _stub;        }

  virtual void emit_code(LIR_Assembler* masm);
  virtual LIR_OpAllocObj * as_OpAllocObj () { return this; }
  virtual void print_instr(outputStream* out) const PRODUCT_RETURN;
};


// LIR_OpRoundFP
class LIR_OpRoundFP : public LIR_Op1 {
 friend class LIR_OpVisitState;

 private:
  LIR_Opr _tmp;

 public:
  LIR_OpRoundFP(LIR_Opr reg, LIR_Opr stack_loc_temp, LIR_Opr result)
    : LIR_Op1(lir_roundfp, reg, result)
    , _tmp(stack_loc_temp) {}

  LIR_Opr tmp() const                            { return _tmp; }
  virtual LIR_OpRoundFP* as_OpRoundFP()          { return this; }
  void print_instr(outputStream* out) const PRODUCT_RETURN;
};

// LIR_OpTypeCheck
class LIR_OpTypeCheck: public LIR_Op {
 friend class LIR_OpVisitState;

 private:
  LIR_Opr       _object;
  LIR_Opr       _array;
  ciKlass*      _klass;
  LIR_Opr       _tmp1;
  LIR_Opr       _tmp2;
  LIR_Opr       _tmp3;
  bool          _fast_check;
  CodeEmitInfo* _info_for_patch;
  CodeEmitInfo* _info_for_exception;
  CodeStub*     _stub;
  ciMethod*     _profiled_method;
  int           _profiled_bci;
  bool          _should_profile;

public:
  LIR_OpTypeCheck(LIR_Code code, LIR_Opr result, LIR_Opr object, ciKlass* klass,
                  LIR_Opr tmp1, LIR_Opr tmp2, LIR_Opr tmp3, bool fast_check,
                  CodeEmitInfo* info_for_exception, CodeEmitInfo* info_for_patch, CodeStub* stub);
  LIR_OpTypeCheck(LIR_Code code, LIR_Opr object, LIR_Opr array,
                  LIR_Opr tmp1, LIR_Opr tmp2, LIR_Opr tmp3, CodeEmitInfo* info_for_exception);

  LIR_Opr object() const                         { return _object;         }
  LIR_Opr array() const                          { assert(code() == lir_store_check, "not valid"); return _array;         }
  LIR_Opr tmp1() const                           { return _tmp1;           }
  LIR_Opr tmp2() const                           { return _tmp2;           }
  LIR_Opr tmp3() const                           { return _tmp3;           }
  ciKlass* klass() const                         { assert(code() == lir_instanceof || code() == lir_checkcast, "not valid"); return _klass;          }
  bool fast_check() const                        { assert(code() == lir_instanceof || code() == lir_checkcast, "not valid"); return _fast_check;     }
  CodeEmitInfo* info_for_patch() const           { return _info_for_patch;  }
  CodeEmitInfo* info_for_exception() const       { return _info_for_exception; }
  CodeStub* stub() const                         { return _stub;           }

  // MethodData* profiling
  void set_profiled_method(ciMethod *method)     { _profiled_method = method; }
  void set_profiled_bci(int bci)                 { _profiled_bci = bci;       }
  void set_should_profile(bool b)                { _should_profile = b;       }
  ciMethod* profiled_method() const              { return _profiled_method;   }
  int       profiled_bci() const                 { return _profiled_bci;      }
  bool      should_profile() const               { return _should_profile;    }

  virtual bool is_patching() { return _info_for_patch != NULL; }
  virtual void emit_code(LIR_Assembler* masm);
  virtual LIR_OpTypeCheck* as_OpTypeCheck() { return this; }
  void print_instr(outputStream* out) const PRODUCT_RETURN;
};

// LIR_Op2
class LIR_Op2: public LIR_Op {
 friend class LIR_OpVisitState;

  int  _fpu_stack_size; // for sin/cos implementation on Intel

 protected:
  LIR_Opr   _opr1;
  LIR_Opr   _opr2;
  BasicType _type;
  LIR_Opr   _tmp1;
  LIR_Opr   _tmp2;
  LIR_Opr   _tmp3;
  LIR_Opr   _tmp4;
  LIR_Opr   _tmp5;
  LIR_Condition _condition;

  void verify() const;

 public:
  LIR_Op2(LIR_Code code, LIR_Condition condition, LIR_Opr opr1, LIR_Opr opr2, CodeEmitInfo* info = NULL, BasicType type = T_ILLEGAL)
    : LIR_Op(code, LIR_OprFact::illegalOpr, info)
    , _fpu_stack_size(0)
    , _opr1(opr1)
    , _opr2(opr2)
    , _type(type)
    , _tmp1(LIR_OprFact::illegalOpr)
    , _tmp2(LIR_OprFact::illegalOpr)
    , _tmp3(LIR_OprFact::illegalOpr)
    , _tmp4(LIR_OprFact::illegalOpr)
    , _tmp5(LIR_OprFact::illegalOpr)
    , _condition(condition) {
    assert(code == lir_cmp || code == lir_branch || code == lir_cond_float_branch || code == lir_assert, "code check");
  }

  LIR_Op2(LIR_Code code, LIR_Condition condition, LIR_Opr opr1, LIR_Opr opr2, LIR_Opr result, BasicType type)
    : LIR_Op(code, result, NULL)
    , _fpu_stack_size(0)
    , _opr1(opr1)
    , _opr2(opr2)
    , _type(type)
    , _tmp1(LIR_OprFact::illegalOpr)
    , _tmp2(LIR_OprFact::illegalOpr)
    , _tmp3(LIR_OprFact::illegalOpr)
    , _tmp4(LIR_OprFact::illegalOpr)
    , _tmp5(LIR_OprFact::illegalOpr)
    , _condition(condition) {
    assert(code == lir_cmove, "code check");
    assert(type != T_ILLEGAL, "cmove should have type");
  }

  LIR_Op2(LIR_Code code, LIR_Opr opr1, LIR_Opr opr2, LIR_Opr result = LIR_OprFact::illegalOpr,
          CodeEmitInfo* info = NULL, BasicType type = T_ILLEGAL)
    : LIR_Op(code, result, info)
    , _fpu_stack_size(0)
    , _opr1(opr1)
    , _opr2(opr2)
    , _type(type)
    , _tmp1(LIR_OprFact::illegalOpr)
    , _tmp2(LIR_OprFact::illegalOpr)
    , _tmp3(LIR_OprFact::illegalOpr)
    , _tmp4(LIR_OprFact::illegalOpr)
    , _tmp5(LIR_OprFact::illegalOpr)
    , _condition(lir_cond_unknown) {
    assert(code != lir_cmp && code != lir_branch && code != lir_cond_float_branch && is_in_range(code, begin_op2, end_op2), "code check");
  }

  LIR_Op2(LIR_Code code, LIR_Opr opr1, LIR_Opr opr2, LIR_Opr result, LIR_Opr tmp1, LIR_Opr tmp2 = LIR_OprFact::illegalOpr,
          LIR_Opr tmp3 = LIR_OprFact::illegalOpr, LIR_Opr tmp4 = LIR_OprFact::illegalOpr, LIR_Opr tmp5 = LIR_OprFact::illegalOpr)
    : LIR_Op(code, result, NULL)
    , _fpu_stack_size(0)
    , _opr1(opr1)
    , _opr2(opr2)
    , _type(T_ILLEGAL)
    , _tmp1(tmp1)
    , _tmp2(tmp2)
    , _tmp3(tmp3)
    , _tmp4(tmp4)
    , _tmp5(tmp5)
    , _condition(lir_cond_unknown) {
    assert(code != lir_cmp && code != lir_branch && code != lir_cond_float_branch && is_in_range(code, begin_op2, end_op2), "code check");
  }

  LIR_Opr in_opr1() const                        { return _opr1; }
  LIR_Opr in_opr2() const                        { return _opr2; }
  BasicType type()  const                        { return _type; }
  LIR_Opr tmp1_opr() const                       { return _tmp1; }
  LIR_Opr tmp2_opr() const                       { return _tmp2; }
  LIR_Opr tmp3_opr() const                       { return _tmp3; }
  LIR_Opr tmp4_opr() const                       { return _tmp4; }
  LIR_Opr tmp5_opr() const                       { return _tmp5; }
  LIR_Condition condition() const  {
    assert(code() == lir_cmp || code() == lir_branch || code() == lir_cond_float_branch || code() == lir_assert, "only valid for branch and assert"); return _condition;
  }
  void set_condition(LIR_Condition condition) {
    assert(code() == lir_cmp || code() == lir_branch || code() == lir_cond_float_branch, "only valid for branch"); _condition = condition;
  }

  void set_fpu_stack_size(int size)              { _fpu_stack_size = size; }
  int  fpu_stack_size() const                    { return _fpu_stack_size; }

  void set_in_opr1(LIR_Opr opr)                  { _opr1 = opr; }
  void set_in_opr2(LIR_Opr opr)                  { _opr2 = opr; }

  virtual void emit_code(LIR_Assembler* masm);
  virtual LIR_Op2* as_Op2() { return this; }
  virtual void print_instr(outputStream* out) const PRODUCT_RETURN;
};

class LIR_OpBranch: public LIR_Op2 {
 friend class LIR_OpVisitState;

 private:
  Label*        _label;
  BlockBegin*   _block;  // if this is a branch to a block, this is the block
  BlockBegin*   _ublock; // if this is a float-branch, this is the unordered block
  CodeStub*     _stub;   // if this is a branch to a stub, this is the stub

 public:
  LIR_OpBranch(LIR_Condition cond, Label* lbl)
    : LIR_Op2(lir_branch, cond, LIR_OprFact::illegalOpr, LIR_OprFact::illegalOpr, (CodeEmitInfo*) NULL)
    , _label(lbl)
    , _block(NULL)
    , _ublock(NULL)
    , _stub(NULL) { }

  LIR_OpBranch(LIR_Condition cond, BlockBegin* block);
  LIR_OpBranch(LIR_Condition cond, CodeStub* stub);

  // for unordered comparisons
  LIR_OpBranch(LIR_Condition cond, BlockBegin* block, BlockBegin* ublock);

  LIR_Condition cond() const {
    return condition();
  }

  void set_cond(LIR_Condition cond) {
    set_condition(cond);
  }

  Label*        label()       const              { return _label;       }
  BlockBegin*   block()       const              { return _block;       }
  BlockBegin*   ublock()      const              { return _ublock;      }
  CodeStub*     stub()        const              { return _stub;        }

  void          change_block(BlockBegin* b);
  void          change_ublock(BlockBegin* b);
  void          negate_cond();

  virtual void emit_code(LIR_Assembler* masm);
  virtual LIR_OpBranch* as_OpBranch() { return this; }
  virtual void print_instr(outputStream* out) const PRODUCT_RETURN;
};

class LIR_OpAllocArray : public LIR_Op {
 friend class LIR_OpVisitState;

 private:
  LIR_Opr   _klass;
  LIR_Opr   _len;
  LIR_Opr   _tmp1;
  LIR_Opr   _tmp2;
  LIR_Opr   _tmp3;
  LIR_Opr   _tmp4;
  BasicType _type;
  CodeStub* _stub;

 public:
  LIR_OpAllocArray(LIR_Opr klass, LIR_Opr len, LIR_Opr result, LIR_Opr t1, LIR_Opr t2, LIR_Opr t3, LIR_Opr t4, BasicType type, CodeStub* stub)
    : LIR_Op(lir_alloc_array, result, NULL)
    , _klass(klass)
    , _len(len)
    , _tmp1(t1)
    , _tmp2(t2)
    , _tmp3(t3)
    , _tmp4(t4)
    , _type(type)
    , _stub(stub) {}

  LIR_Opr   klass()   const                      { return _klass;       }
  LIR_Opr   len()     const                      { return _len;         }
  LIR_Opr   obj()     const                      { return result_opr(); }
  LIR_Opr   tmp1()    const                      { return _tmp1;        }
  LIR_Opr   tmp2()    const                      { return _tmp2;        }
  LIR_Opr   tmp3()    const                      { return _tmp3;        }
--> --------------------

--> maximum size reached

--> --------------------

¤ Dauer der Verarbeitung: 0.68 Sekunden  (vorverarbeitet)  ¤





vermutete Sprache:
Sekunden
vermutete Sprache:
sprechenden Kalenders

in der Quellcodebibliothek suchen




Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.


Bemerkung:

Die farbliche Syntaxdarstellung ist noch experimentell.


Bot Zugriff



                                                                                                                                                                                                                                                                                                                                                                                                     


Neuigkeiten

     Aktuelles
     Motto des Tages

Software

     Produkte
     Quellcodebibliothek

Aktivitäten

     Artikel über Sicherheit
     Anleitung zur Aktivierung von SSL

Muße

     Gedichte
     Musik
     Bilder

Jenseits des Üblichen ....
    

Besucherstatistik

Besucherstatistik