RFR: 8273317: crash in cmovP_cmpP_zero_zeroNode::bottom_type()

SUN Guoyun github.com+40024232+sunny868 at openjdk.java.net
Wed Sep 29 09:53:34 UTC 2021


On Sat, 4 Sep 2021 02:58:56 GMT, SUN Guoyun <github.com+40024232+sunny868 at openjdk.org> wrote:

> Hi all,
> 
> When I implement a new instruct in adfile for match CMoveP with Cmp node,like this:
> 
> match(Set dst (CMoveP (Binary cop (CmpP op1 zero)) (Binary dst zero)));
> 
> this means right child of CmpP is immediate zero and right child of CmovP also is immediate zero, then an exception will occur:
> 
> <pre><code class="shell">
> #
> # A fatal error has been detected by the Java Runtime Environment:
> #
> # SIGSEGV (0xb) at pc=0x000000fff410fcc4, pid=11130, tid=11146
> #
> # JRE version: OpenJDK Runtime Environment (17.0) (build 17-internal+0-jenkins-slave-20210821140615-jdk-ls-a526852e137)
> # Java VM: OpenJDK 64-Bit Server VM (17-internal+0-jenkins-slave-20210821140615-jdk-ls-a526852e137, compiled mode, compressed oops, compressed class ptrs, g1 gc, linux-loongarch64)
> # Problematic frame:
> # V [libjvm.so+0x21fcc4] cmovP_cmpP_zero_zeroNode::bottom_type() const+0x44
> #
> # No core dump will be written. Core dumps have been disabled. To enable core dumping, try "ulimit -c unlimited" before starting Java again
> #
> # If you would like to submit a bug report, please visit:
> # https://bugreport.java.com/bugreport/crash.jsp
> #
> </code></pre>
> 
> In this case, cmovP_ cmpP_ zero_ zeroNode only has three input nodes, so an exception is triggered. This is a patch to fix this problem. Please help review it 
> 
> Thanks,
> Sun Guoyun

the C code generated by adlc with and without this changes:
<pre><code class="cpp">
class cmovP_cmpP_zero_zeroNode : public MachNode { 
private:
  MachOper *_opnd_array[6];
public:
  MachOper *opnd_array(uint operand_index) const {
    assert(operand_index < _num_opnds, "invalid _opnd_array index");
    return _opnd_array[operand_index];
  }
  void      set_opnd_array(uint operand_index, MachOper *operand) {
    assert(operand_index < _num_opnds, "invalid _opnd_array index");
    _opnd_array[operand_index] = operand;
  }
  virtual uint           rule() const { return cmovP_cmpP_zero_zero_rule; }
private:
  virtual const RegMask &out_RegMask() const;
  virtual void           emit(CodeBuffer &cbuf, PhaseRegAlloc *ra_) const;
  virtual int            ideal_Opcode() const { return Op_CMoveP; }
  virtual uint           two_adr() const  { return oper_input_base() + opnd_array(1)->num_edges() + opnd_array(2)->num_edges() + opnd_array(3)->num_edges(); }
  virtual int            reloc() const;
public:
  cmovP_cmpP_zero_zeroNode() {  _num_opnds = 6; _opnds = _opnd_array; }
  virtual uint           size_of() const { return sizeof(cmovP_cmpP_zero_zeroNode); }
  virtual MachNode      *Expand(State *state, Node_List &proj_list, Node* mem);
  static  const Pipeline *pipeline_class();
  virtual const Pipeline *pipeline() const;
  const Type            *bottom_type() const { const Type *t = in(oper_input_base()+2)->bottom_type(); return (req() <= oper_input_base()+3) ? t : t->meet(in(oper_input_base()+3)->bottom_type()); } // CMoveP
#ifndef PRODUCT
  virtual void           format(PhaseRegAlloc *ra, outputStream *st) const;
  virtual const char    *Name() const { return "cmovP_cmpP_zero_zero";}
#endif
};
</code></pre>
The cmovP_cmpP_zero_zeroNode only has three input nodes, so the value of cmovP_cmpP_zero_zeroNode->req() is 3, In function of bottom_type(), value of oper_input_base() is 1,
so in(0) in(1) in(2) is ok, but in(1+2) will not a valid address. in(3)->bottom_type() will occur SIGSEGV.


Then the C code with this changes:

<pre><code class="cpp">
class cmovP_cmpP_zero_regNode : public MachNode { 
private:
  MachOper *_opnd_array[6];
public:
  MachOper *opnd_array(uint operand_index) const {
    assert(operand_index < _num_opnds, "invalid _opnd_array index");
    return _opnd_array[operand_index];
  }
  void      set_opnd_array(uint operand_index, MachOper *operand) {
    assert(operand_index < _num_opnds, "invalid _opnd_array index");
    _opnd_array[operand_index] = operand;
  }
  virtual uint           rule() const { return cmovP_cmpP_zero_reg_rule; }
private:
  virtual const RegMask &out_RegMask() const;
  virtual void           emit(CodeBuffer &cbuf, PhaseRegAlloc *ra_) const;
  virtual int            ideal_Opcode() const { return Op_CMoveP; }
  virtual uint           two_adr() const  { return oper_input_base() + opnd_array(1)->num_edges() + opnd_array(2)->num_edges() + opnd_array(3)->num_edges(); }
  virtual int            reloc() const;
public:
  cmovP_cmpP_zero_regNode() {  _num_opnds = 6; _opnds = _opnd_array; }
  virtual uint           size_of() const { return sizeof(cmovP_cmpP_zero_regNode); }
  static  const Pipeline *pipeline_class();
  virtual const Pipeline *pipeline() const;
  const Type            *bottom_type() const { if (req() == 3) return in(2)->bottom_type();
	const Type *t = in(oper_input_base()+2)->bottom_type(); return (req() <= oper_input_base()+3) ? t : t->meet(in(oper_input_base()+3)->bottom_type()); } // CMoveP
#ifndef PRODUCT
  virtual void           format(PhaseRegAlloc *ra, outputStream *st) const;
  virtual const char    *Name() const { return "cmovP_cmpP_zero_reg";}
#endif
};

</code></pre>

when req() equal 3,then bottom_type of last input node in(2) will be return. 

By the way,under x86 aarch64 s390 ppc architectures, CMove node and Cmp nodes do not incorporate a match rule, so similar exceptions will not be triggered.

-------------

PR: https://git.openjdk.java.net/jdk/pull/5369


More information about the hotspot-compiler-dev mailing list