< prev index next >

src/hotspot/share/c1/c1_Instruction.hpp

Print this page
*** 72,10 ***
--- 72,11 ---
  class     NewInstance;
  class     NewArray;
  class       NewTypeArray;
  class       NewObjectArray;
  class       NewMultiArray;
+ class     Deoptimize;
  class     TypeCheck;
  class       CheckCast;
  class       InstanceOf;
  class     AccessMonitor;
  class       MonitorEnter;

*** 96,10 ***
--- 97,11 ---
  class     UnsafeGet;
  class     UnsafePut;
  class     UnsafeGetAndSet;
  class   ProfileCall;
  class   ProfileReturnType;
+ class   ProfileACmpTypes;
  class   ProfileInvoke;
  class   RuntimeCall;
  class   MemBar;
  class   RangeCheckPredicate;
  #ifdef ASSERT

*** 191,10 ***
--- 193,11 ---
    virtual void do_UnsafeGet      (UnsafeGet*       x) = 0;
    virtual void do_UnsafePut      (UnsafePut*       x) = 0;
    virtual void do_UnsafeGetAndSet(UnsafeGetAndSet* x) = 0;
    virtual void do_ProfileCall    (ProfileCall*     x) = 0;
    virtual void do_ProfileReturnType (ProfileReturnType*  x) = 0;
+   virtual void do_ProfileACmpTypes(ProfileACmpTypes*  x) = 0;
    virtual void do_ProfileInvoke  (ProfileInvoke*   x) = 0;
    virtual void do_RuntimeCall    (RuntimeCall*     x) = 0;
    virtual void do_MemBar         (MemBar*          x) = 0;
    virtual void do_RangeCheckPredicate(RangeCheckPredicate* x) = 0;
  #ifdef ASSERT

*** 207,13 ***
  //
  // Note: This hash functions affect the performance
  //       of ValueMap - make changes carefully!
  
  #define HASH1(x1            )                    ((intx)(x1))
! #define HASH2(x1, x2        )                    ((HASH1(x1        ) << 7) ^ HASH1(x2))
! #define HASH3(x1, x2, x3    )                    ((HASH2(x1, x2    ) << 7) ^ HASH1(x3))
! #define HASH4(x1, x2, x3, x4)                    ((HASH3(x1, x2, x3) << 7) ^ HASH1(x4))
  
  
  // The following macros are used to implement instruction-specific hashing.
  // By default, each instruction implements hash() and is_equal(Value), used
  // for value numbering/common subexpression elimination. The default imple-
--- 210,14 ---
  //
  // Note: This hash functions affect the performance
  //       of ValueMap - make changes carefully!
  
  #define HASH1(x1            )                    ((intx)(x1))
! #define HASH2(x1, x2        )                    ((HASH1(x1            ) << 7) ^ HASH1(x2))
! #define HASH3(x1, x2, x3    )                    ((HASH2(x1, x2        ) << 7) ^ HASH1(x3))
! #define HASH4(x1, x2, x3, x4)                    ((HASH3(x1, x2, x3    ) << 7) ^ HASH1(x4))
+ #define HASH5(x1, x2, x3, x4, x5)                ((HASH4(x1, x2, x3, x4) << 7) ^ HASH1(x5))
  
  
  // The following macros are used to implement instruction-specific hashing.
  // By default, each instruction implements hash() and is_equal(Value), used
  // for value numbering/common subexpression elimination. The default imple-

*** 268,10 ***
--- 272,25 ---
      if (f2 != _v->f2) return false;                   \
      if (f3 != _v->f3) return false;                   \
      return true;                                      \
    }                                                   \
  
+ #define HASHING4(class_name, enabled, f1, f2, f3, f4) \
+   virtual intx hash() const {                         \
+     return (enabled) ? HASH5(name(), f1, f2, f3, f4) : 0; \
+   }                                                   \
+   virtual bool is_equal(Value v) const {              \
+     if (!(enabled)  ) return false;                   \
+     class_name* _v = v->as_##class_name();            \
+     if (_v == nullptr  ) return false;                   \
+     if (f1 != _v->f1) return false;                   \
+     if (f2 != _v->f2) return false;                   \
+     if (f3 != _v->f3) return false;                   \
+     if (f4 != _v->f4) return false;                   \
+     return true;                                      \
+   }                                                   \
+ 
  
  // The mother of all instructions...
  
  class Instruction: public CompilationResourceObj {
   private:

*** 290,10 ***
--- 309,11 ---
    ValueStack*  _state_before;                    // Copy of state with input operands still on stack (or null)
    ValueStack*  _exception_state;                 // Copy of state for exception handling
    XHandlers*   _exception_handlers;              // Flat list of exception handlers covering this instruction
  
    friend class UseCountComputer;
+   friend class GraphBuilder;
  
    void update_exception_state(ValueStack* state);
  
   protected:
    BlockBegin*  _block;                           // Block that contains this instruction

*** 342,10 ***
--- 362,11 ---
  
    static const int no_bci = -99;
  
    enum InstructionFlag {
      NeedsNullCheckFlag = 0,
+     NeverNullFlag,          // For "Q" signatures
      CanTrapFlag,
      DirectCompareFlag,
      IsEliminatedFlag,
      IsSafepointFlag,
      IsStaticFlag,

*** 436,20 ***
--- 457,23 ---
    Instruction* subst()                           { return _subst == nullptr ? this : _subst->subst(); }
    LIR_Opr operand() const                        { return _operand; }
  
    void set_needs_null_check(bool f)              { set_flag(NeedsNullCheckFlag, f); }
    bool needs_null_check() const                  { return check_flag(NeedsNullCheckFlag); }
+   void set_null_free(bool f)                     { set_flag(NeverNullFlag, f); }
+   bool is_null_free() const                      { return check_flag(NeverNullFlag); }
    bool is_linked() const                         { return check_flag(IsLinkedInBlockFlag); }
    bool can_be_linked()                           { return as_Local() == nullptr && as_Phi() == nullptr; }
  
    bool is_null_obj()                             { return as_Constant() != nullptr && type()->as_ObjectType()->constant_value()->is_null_object(); }
  
    bool has_uses() const                          { return use_count() > 0; }
    ValueStack* state_before() const               { return _state_before; }
    ValueStack* exception_state() const            { return _exception_state; }
    virtual bool needs_exception_state() const     { return true; }
    XHandlers* exception_handlers() const          { return _exception_handlers; }
+   ciKlass* as_loaded_klass_or_null() const;
  
    // manipulation
    void pin(PinReason reason)                     { _pin_state |= reason; }
    void pin()                                     { _pin_state |= PinUnknown; }
    // DANGEROUS: only used by EliminateStores

*** 490,10 ***
--- 514,14 ---
      set_next(i);
      i->set_next(n);
      return _next;
    }
  
+   bool is_loaded_flat_array() const;
+   bool maybe_flat_array();
+   bool maybe_null_free_array();
+ 
    Instruction *insert_after_same_bci(Instruction *i) {
  #ifndef PRODUCT
      i->set_printable_bci(printable_bci());
  #endif
      return insert_after(i);

*** 689,16 ***
    int      _java_index;                          // the local index within the method to which the local belongs
    bool     _is_receiver;                         // if local variable holds the receiver: "this" for non-static methods
    ciType*  _declared_type;
   public:
    // creation
!   Local(ciType* declared, ValueType* type, int index, bool receiver)
      : Instruction(type)
      , _java_index(index)
      , _is_receiver(receiver)
      , _declared_type(declared)
    {
      NOT_PRODUCT(set_printable_bci(-1));
    }
  
    // accessors
    int java_index() const                         { return _java_index; }
--- 717,17 ---
    int      _java_index;                          // the local index within the method to which the local belongs
    bool     _is_receiver;                         // if local variable holds the receiver: "this" for non-static methods
    ciType*  _declared_type;
   public:
    // creation
!   Local(ciType* declared, ValueType* type, int index, bool receiver, bool null_free)
      : Instruction(type)
      , _java_index(index)
      , _is_receiver(receiver)
      , _declared_type(declared)
    {
+     set_null_free(null_free);
      NOT_PRODUCT(set_printable_bci(-1));
    }
  
    // accessors
    int java_index() const                         { return _java_index; }

*** 816,13 ***
  
  LEAF(LoadField, AccessField)
   public:
    // creation
    LoadField(Value obj, int offset, ciField* field, bool is_static,
!             ValueStack* state_before, bool needs_patching)
    : AccessField(obj, offset, field, is_static, state_before, needs_patching)
!   {}
  
    ciType* declared_type() const;
  
    // generic; cannot be eliminated if needs patching or if volatile.
    HASHING3(LoadField, !needs_patching() && !field()->is_volatile(), obj()->subst(), offset(), declared_type())
--- 845,16 ---
  
  LEAF(LoadField, AccessField)
   public:
    // creation
    LoadField(Value obj, int offset, ciField* field, bool is_static,
!             ValueStack* state_before, bool needs_patching,
+             ciInlineKlass* inline_klass = nullptr, Value default_value = nullptr )
    : AccessField(obj, offset, field, is_static, state_before, needs_patching)
!   {
+     set_null_free(field->is_null_free());
+   }
  
    ciType* declared_type() const;
  
    // generic; cannot be eliminated if needs patching or if volatile.
    HASHING3(LoadField, !needs_patching() && !field()->is_volatile(), obj()->subst(), offset(), declared_type())

*** 830,26 ***
  
  
  LEAF(StoreField, AccessField)
   private:
    Value _value;
  
   public:
    // creation
    StoreField(Value obj, int offset, ciField* field, Value value, bool is_static,
!              ValueStack* state_before, bool needs_patching)
-   : AccessField(obj, offset, field, is_static, state_before, needs_patching)
-   , _value(value)
-   {
-     set_flag(NeedsWriteBarrierFlag, as_ValueType(field_type())->is_object());
-     ASSERT_VALUES
-     pin();
-   }
  
    // accessors
    Value value() const                            { return _value; }
    bool needs_write_barrier() const               { return check_flag(NeedsWriteBarrierFlag); }
  
    // generic
    virtual void input_values_do(ValueVisitor* f)   { AccessField::input_values_do(f); f->visit(&_value); }
  };
  
--- 862,22 ---
  
  
  LEAF(StoreField, AccessField)
   private:
    Value _value;
+   ciField* _enclosing_field;   // enclosing field (the flat one) for nested fields
  
   public:
    // creation
    StoreField(Value obj, int offset, ciField* field, Value value, bool is_static,
!              ValueStack* state_before, bool needs_patching);
  
    // accessors
    Value value() const                            { return _value; }
    bool needs_write_barrier() const               { return check_flag(NeedsWriteBarrierFlag); }
+   ciField* enclosing_field() const               { return _enclosing_field; }
+   void set_enclosing_field(ciField* field)       { _enclosing_field = field; }
  
    // generic
    virtual void input_values_do(ValueVisitor* f)   { AccessField::input_values_do(f); f->visit(&_value); }
  };
  

*** 903,19 ***
--- 931,22 ---
   private:
    Value     _index;
    Value     _length;
    BasicType _elt_type;
    bool      _mismatched;
+   ciMethod* _profiled_method;
+   int       _profiled_bci;
  
   public:
    // creation
    AccessIndexed(Value array, Value index, Value length, BasicType elt_type, ValueStack* state_before, bool mismatched)
    : AccessArray(as_ValueType(elt_type), array, state_before)
    , _index(index)
    , _length(length)
    , _elt_type(elt_type)
    , _mismatched(mismatched)
+   , _profiled_method(nullptr), _profiled_bci(0)
    {
      set_flag(Instruction::NeedsRangeCheckFlag, true);
      ASSERT_VALUES
    }
  

*** 927,24 ***
  
    void clear_length()                            { _length = nullptr; }
    // perform elimination of range checks involving constants
    bool compute_needs_range_check();
  
    // generic
    virtual void input_values_do(ValueVisitor* f)   { AccessArray::input_values_do(f); f->visit(&_index); if (_length != nullptr) f->visit(&_length); }
  };
  
  
  LEAF(LoadIndexed, AccessIndexed)
   private:
    NullCheck*  _explicit_null_check;              // For explicit null check elimination
  
   public:
    // creation
    LoadIndexed(Value array, Value index, Value length, BasicType elt_type, ValueStack* state_before, bool mismatched = false)
    : AccessIndexed(array, index, length, elt_type, state_before, mismatched)
!   , _explicit_null_check(nullptr) {}
  
    // accessors
    NullCheck* explicit_null_check() const         { return _explicit_null_check; }
  
    // setters
--- 958,36 ---
  
    void clear_length()                            { _length = nullptr; }
    // perform elimination of range checks involving constants
    bool compute_needs_range_check();
  
+   // Helpers for MethodData* profiling
+   void set_should_profile(bool value)                { set_flag(ProfileMDOFlag, value); }
+   void set_profiled_method(ciMethod* method)         { _profiled_method = method;   }
+   void set_profiled_bci(int bci)                     { _profiled_bci = bci;         }
+   bool      should_profile() const                   { return check_flag(ProfileMDOFlag); }
+   ciMethod* profiled_method() const                  { return _profiled_method;     }
+   int       profiled_bci() const                     { return _profiled_bci;        }
+ 
+ 
    // generic
    virtual void input_values_do(ValueVisitor* f)   { AccessArray::input_values_do(f); f->visit(&_index); if (_length != nullptr) f->visit(&_length); }
  };
  
+ class DelayedLoadIndexed;
  
  LEAF(LoadIndexed, AccessIndexed)
   private:
    NullCheck*  _explicit_null_check;              // For explicit null check elimination
+   NewInstance* _vt;
+   DelayedLoadIndexed* _delayed;
  
   public:
    // creation
    LoadIndexed(Value array, Value index, Value length, BasicType elt_type, ValueStack* state_before, bool mismatched = false)
    : AccessIndexed(array, index, length, elt_type, state_before, mismatched)
!   , _explicit_null_check(nullptr), _vt(nullptr), _delayed(nullptr) {}
  
    // accessors
    NullCheck* explicit_null_check() const         { return _explicit_null_check; }
  
    // setters

*** 952,48 ***
    void set_explicit_null_check(NullCheck* check) { _explicit_null_check = check; }
  
    ciType* exact_type() const;
    ciType* declared_type() const;
  
    // generic;
!   HASHING3(LoadIndexed, true, elt_type(), array()->subst(), index()->subst())
  };
  
  
  LEAF(StoreIndexed, AccessIndexed)
   private:
    Value       _value;
  
-   ciMethod* _profiled_method;
-   int       _profiled_bci;
    bool      _check_boolean;
  
   public:
    // creation
    StoreIndexed(Value array, Value index, Value length, BasicType elt_type, Value value, ValueStack* state_before,
!                bool check_boolean, bool mismatched = false)
-   : AccessIndexed(array, index, length, elt_type, state_before, mismatched)
-   , _value(value), _profiled_method(nullptr), _profiled_bci(0), _check_boolean(check_boolean)
-   {
-     set_flag(NeedsWriteBarrierFlag, (as_ValueType(elt_type)->is_object()));
-     set_flag(NeedsStoreCheckFlag, (as_ValueType(elt_type)->is_object()));
-     ASSERT_VALUES
-     pin();
-   }
  
    // accessors
    Value value() const                            { return _value; }
    bool needs_write_barrier() const               { return check_flag(NeedsWriteBarrierFlag); }
    bool needs_store_check() const                 { return check_flag(NeedsStoreCheckFlag); }
    bool check_boolean() const                     { return _check_boolean; }
!   // Helpers for MethodData* profiling
!   void set_should_profile(bool value)                { set_flag(ProfileMDOFlag, value); }
!   void set_profiled_method(ciMethod* method)         { _profiled_method = method;   }
-   void set_profiled_bci(int bci)                     { _profiled_bci = bci;         }
-   bool      should_profile() const                   { return check_flag(ProfileMDOFlag); }
-   ciMethod* profiled_method() const                  { return _profiled_method;     }
-   int       profiled_bci() const                     { return _profiled_bci;        }
    // generic
    virtual void input_values_do(ValueVisitor* f)   { AccessIndexed::input_values_do(f); f->visit(&_value); }
  };
  
  
--- 995,63 ---
    void set_explicit_null_check(NullCheck* check) { _explicit_null_check = check; }
  
    ciType* exact_type() const;
    ciType* declared_type() const;
  
+   NewInstance* vt() const { return _vt; }
+   void set_vt(NewInstance* vt) { _vt = vt; }
+ 
+   DelayedLoadIndexed* delayed() const { return _delayed; }
+   void set_delayed(DelayedLoadIndexed* delayed) { _delayed = delayed; }
+ 
    // generic;
!   HASHING4(LoadIndexed, delayed() == nullptr && !should_profile(), elt_type(), array()->subst(), index()->subst(), vt())
  };
  
+ class DelayedLoadIndexed : public CompilationResourceObj {
+ private:
+   LoadIndexed* _load_instr;
+   ValueStack* _state_before;
+   ciField* _field;
+   int _offset;
+  public:
+   DelayedLoadIndexed(LoadIndexed* load, ValueStack* state_before)
+   : _load_instr(load)
+   , _state_before(state_before)
+   , _field(nullptr)
+   , _offset(0) { }
+ 
+   void update(ciField* field, int offset) {
+     _field = field;
+     _offset += offset;
+   }
+ 
+   LoadIndexed* load_instr() const { return _load_instr; }
+   ValueStack* state_before() const { return _state_before; }
+   ciField* field() const { return _field; }
+   int offset() const { return _offset; }
+ };
  
  LEAF(StoreIndexed, AccessIndexed)
   private:
    Value       _value;
  
    bool      _check_boolean;
  
   public:
    // creation
    StoreIndexed(Value array, Value index, Value length, BasicType elt_type, Value value, ValueStack* state_before,
!                bool check_boolean, bool mismatched = false);
  
    // accessors
    Value value() const                            { return _value; }
    bool needs_write_barrier() const               { return check_flag(NeedsWriteBarrierFlag); }
    bool needs_store_check() const                 { return check_flag(NeedsStoreCheckFlag); }
    bool check_boolean() const                     { return _check_boolean; }
! 
!   // Flattened array support
!   bool is_exact_flat_array_store() const;
    // generic
    virtual void input_values_do(ValueVisitor* f)   { AccessIndexed::input_values_do(f); f->visit(&_value); }
  };
  
  

*** 1100,29 ***
  
  LEAF(IfOp, Op2)
   private:
    Value _tval;
    Value _fval;
  
   public:
    // creation
!   IfOp(Value x, Condition cond, Value y, Value tval, Value fval)
    : Op2(tval->type()->meet(fval->type()), (Bytecodes::Code)cond, x, y)
    , _tval(tval)
    , _fval(fval)
    {
      ASSERT_VALUES
      assert(tval->type()->tag() == fval->type()->tag(), "types must match");
    }
  
    // accessors
    virtual bool is_commutative() const;
    Bytecodes::Code op() const                     { ShouldNotCallThis(); return Bytecodes::_illegal; }
    Condition cond() const                         { return (Condition)Op2::op(); }
    Value tval() const                             { return _tval; }
    Value fval() const                             { return _fval; }
! 
    // generic
    virtual void input_values_do(ValueVisitor* f)   { Op2::input_values_do(f); f->visit(&_tval); f->visit(&_fval); }
  };
  
  
--- 1158,32 ---
  
  LEAF(IfOp, Op2)
   private:
    Value _tval;
    Value _fval;
+   bool _substitutability_check;
  
   public:
    // creation
!   IfOp(Value x, Condition cond, Value y, Value tval, Value fval, ValueStack* state_before, bool substitutability_check)
    : Op2(tval->type()->meet(fval->type()), (Bytecodes::Code)cond, x, y)
    , _tval(tval)
    , _fval(fval)
+   , _substitutability_check(substitutability_check)
    {
      ASSERT_VALUES
      assert(tval->type()->tag() == fval->type()->tag(), "types must match");
+     set_state_before(state_before);
    }
  
    // accessors
    virtual bool is_commutative() const;
    Bytecodes::Code op() const                     { ShouldNotCallThis(); return Bytecodes::_illegal; }
    Condition cond() const                         { return (Condition)Op2::op(); }
    Value tval() const                             { return _tval; }
    Value fval() const                             { return _fval; }
!   bool substitutability_check() const             { return _substitutability_check; }
    // generic
    virtual void input_values_do(ValueVisitor* f)   { Op2::input_values_do(f); f->visit(&_tval); f->visit(&_fval); }
  };
  
  

*** 1275,31 ***
  
  LEAF(NewInstance, StateSplit)
   private:
    ciInstanceKlass* _klass;
    bool _is_unresolved;
  
   public:
    // creation
!   NewInstance(ciInstanceKlass* klass, ValueStack* state_before, bool is_unresolved)
    : StateSplit(instanceType, state_before)
!   , _klass(klass), _is_unresolved(is_unresolved)
    {}
  
    // accessors
    ciInstanceKlass* klass() const                 { return _klass; }
    bool is_unresolved() const                     { return _is_unresolved; }
  
    virtual bool needs_exception_state() const     { return false; }
  
    // generic
    virtual bool can_trap() const                  { return true; }
    ciType* exact_type() const;
    ciType* declared_type() const;
  };
  
- 
  BASE(NewArray, StateSplit)
   private:
    Value       _length;
  
   public:
--- 1336,32 ---
  
  LEAF(NewInstance, StateSplit)
   private:
    ciInstanceKlass* _klass;
    bool _is_unresolved;
+   bool _needs_state_before;
  
   public:
    // creation
!   NewInstance(ciInstanceKlass* klass, ValueStack* state_before, bool is_unresolved, bool needs_state_before)
    : StateSplit(instanceType, state_before)
!   , _klass(klass), _is_unresolved(is_unresolved), _needs_state_before(needs_state_before)
    {}
  
    // accessors
    ciInstanceKlass* klass() const                 { return _klass; }
    bool is_unresolved() const                     { return _is_unresolved; }
+   bool needs_state_before() const                { return _needs_state_before; }
  
    virtual bool needs_exception_state() const     { return false; }
  
    // generic
    virtual bool can_trap() const                  { return true; }
    ciType* exact_type() const;
    ciType* declared_type() const;
  };
  
  BASE(NewArray, StateSplit)
   private:
    Value       _length;
  
   public:

*** 1349,11 ***
   private:
    ciKlass* _klass;
  
   public:
    // creation
!   NewObjectArray(ciKlass* klass, Value length, ValueStack* state_before) : NewArray(length, state_before), _klass(klass) {}
  
    // accessors
    ciKlass* klass() const                         { return _klass; }
    ciType* exact_type() const;
  };
--- 1411,12 ---
   private:
    ciKlass* _klass;
  
   public:
    // creation
!   NewObjectArray(ciKlass* klass, Value length, ValueStack* state_before)
+   : NewArray(length, state_before), _klass(klass) { }
  
    // accessors
    ciKlass* klass() const                         { return _klass; }
    ciType* exact_type() const;
  };

*** 1384,10 ***
--- 1447,12 ---
      // get updated, and the value must not be traversed twice. Was bug
      // - kbr 4/10/2001
      StateSplit::input_values_do(f);
      for (int i = 0; i < _dims->length(); i++) f->visit(_dims->adr_at(i));
    }
+ 
+   ciType* exact_type() const;
  };
  
  
  BASE(TypeCheck, StateSplit)
   private:

*** 1431,11 ***
  
  LEAF(CheckCast, TypeCheck)
   public:
    // creation
    CheckCast(ciKlass* klass, Value obj, ValueStack* state_before)
!   : TypeCheck(klass, obj, objectType, state_before) {}
  
    void set_incompatible_class_change_check() {
      set_flag(ThrowIncompatibleClassChangeErrorFlag, true);
    }
    bool is_incompatible_class_change_check() const {
--- 1496,11 ---
  
  LEAF(CheckCast, TypeCheck)
   public:
    // creation
    CheckCast(ciKlass* klass, Value obj, ValueStack* state_before)
!   : TypeCheck(klass, obj, objectType, state_before) { }
  
    void set_incompatible_class_change_check() {
      set_flag(ThrowIncompatibleClassChangeErrorFlag, true);
    }
    bool is_incompatible_class_change_check() const {

*** 1489,18 ***
    virtual void input_values_do(ValueVisitor* f)   { StateSplit::input_values_do(f); f->visit(&_obj); }
  };
  
  
  LEAF(MonitorEnter, AccessMonitor)
   public:
    // creation
!   MonitorEnter(Value obj, int monitor_no, ValueStack* state_before)
    : AccessMonitor(obj, monitor_no, state_before)
    {
      ASSERT_VALUES
    }
  
    // generic
    virtual bool can_trap() const                  { return true; }
  };
  
  
--- 1554,23 ---
    virtual void input_values_do(ValueVisitor* f)   { StateSplit::input_values_do(f); f->visit(&_obj); }
  };
  
  
  LEAF(MonitorEnter, AccessMonitor)
+   bool _maybe_inlinetype;
   public:
    // creation
!   MonitorEnter(Value obj, int monitor_no, ValueStack* state_before, bool maybe_inlinetype)
    : AccessMonitor(obj, monitor_no, state_before)
+   , _maybe_inlinetype(maybe_inlinetype)
    {
      ASSERT_VALUES
    }
  
+   // accessors
+   bool maybe_inlinetype() const                   { return _maybe_inlinetype; }
+ 
    // generic
    virtual bool can_trap() const                  { return true; }
  };
  
  

*** 1956,21 ***
    Value       _y;
    ciMethod*   _profiled_method;
    int         _profiled_bci; // Canonicalizer may alter bci of If node
    bool        _swapped;      // Is the order reversed with respect to the original If in the
                               // bytecode stream?
   public:
    // creation
    // unordered_is_true is valid for float/double compares only
!   If(Value x, Condition cond, bool unordered_is_true, Value y, BlockBegin* tsux, BlockBegin* fsux, ValueStack* state_before, bool is_safepoint)
      : BlockEnd(illegalType, state_before, is_safepoint)
    , _x(x)
    , _cond(cond)
    , _y(y)
    , _profiled_method(nullptr)
    , _profiled_bci(0)
    , _swapped(false)
    {
      ASSERT_VALUES
      set_flag(UnorderedIsTrueFlag, unordered_is_true);
      assert(x->type()->tag() == y->type()->tag(), "types must match");
      BlockList* s = new BlockList(2);
--- 2026,23 ---
    Value       _y;
    ciMethod*   _profiled_method;
    int         _profiled_bci; // Canonicalizer may alter bci of If node
    bool        _swapped;      // Is the order reversed with respect to the original If in the
                               // bytecode stream?
+   bool        _substitutability_check;
   public:
    // creation
    // unordered_is_true is valid for float/double compares only
!   If(Value x, Condition cond, bool unordered_is_true, Value y, BlockBegin* tsux, BlockBegin* fsux, ValueStack* state_before, bool is_safepoint, bool substitutability_check=false)
      : BlockEnd(illegalType, state_before, is_safepoint)
    , _x(x)
    , _cond(cond)
    , _y(y)
    , _profiled_method(nullptr)
    , _profiled_bci(0)
    , _swapped(false)
+   , _substitutability_check(substitutability_check)
    {
      ASSERT_VALUES
      set_flag(UnorderedIsTrueFlag, unordered_is_true);
      assert(x->type()->tag() == y->type()->tag(), "types must match");
      BlockList* s = new BlockList(2);

*** 2001,10 ***
--- 2073,11 ---
  
    void set_should_profile(bool value)             { set_flag(ProfileMDOFlag, value); }
    void set_profiled_method(ciMethod* method)      { _profiled_method = method; }
    void set_profiled_bci(int bci)                  { _profiled_bci = bci;       }
    void set_swapped(bool value)                    { _swapped = value;         }
+   bool substitutability_check() const              { return _substitutability_check; }
    // generic
    virtual void input_values_do(ValueVisitor* f)   { BlockEnd::input_values_do(f); f->visit(&_x); f->visit(&_y); }
  };
  
  

*** 2335,11 ***
      , _callee(callee)
      , _bci_of_invoke(bci)
      , _ret(ret)
    {
      set_needs_null_check(true);
!     // The ProfileType has side-effects and must occur precisely where located
      pin();
    }
  
    ciMethod* method()             const { return _method; }
    ciMethod* callee()             const { return _callee; }
--- 2408,11 ---
      , _callee(callee)
      , _bci_of_invoke(bci)
      , _ret(ret)
    {
      set_needs_null_check(true);
!     // The ProfileReturnType has side-effects and must occur precisely where located
      pin();
    }
  
    ciMethod* method()             const { return _method; }
    ciMethod* callee()             const { return _callee; }

*** 2351,10 ***
--- 2424,52 ---
        f->visit(&_ret);
      }
    }
  };
  
+ LEAF(ProfileACmpTypes, Instruction)
+  private:
+   ciMethod*        _method;
+   int              _bci;
+   Value            _left;
+   Value            _right;
+   bool             _left_maybe_null;
+   bool             _right_maybe_null;
+ 
+  public:
+   ProfileACmpTypes(ciMethod* method, int bci, Value left, Value right)
+     : Instruction(voidType)
+     , _method(method)
+     , _bci(bci)
+     , _left(left)
+     , _right(right)
+   {
+     // The ProfileACmp has side-effects and must occur precisely where located
+     pin();
+     _left_maybe_null = true;
+     _right_maybe_null = true;
+   }
+ 
+   ciMethod* method()             const { return _method; }
+   int bci()                      const { return _bci; }
+   Value left()                   const { return _left; }
+   Value right()                  const { return _right; }
+   bool left_maybe_null()         const { return _left_maybe_null; }
+   bool right_maybe_null()        const { return _right_maybe_null; }
+   void set_left_maybe_null(bool v)     { _left_maybe_null = v; }
+   void set_right_maybe_null(bool v)    { _right_maybe_null = v; }
+ 
+   virtual void input_values_do(ValueVisitor* f)   {
+     if (_left != nullptr) {
+       f->visit(&_left);
+     }
+     if (_right != nullptr) {
+       f->visit(&_right);
+     }
+   }
+ };
+ 
  // Call some C runtime function that doesn't safepoint,
  // optionally passing the current thread as the first argument.
  LEAF(RuntimeCall, Instruction)
   private:
    const char* _entry_name;
< prev index next >