openjdk-riscv / jdk11u

Read-only mirror of https://hg.openjdk.java.net/jdk-updates/jdk11u/
GNU General Public License v2.0
11 stars 14 forks source link

bad AD file 问题分析 #388

Closed DingliZhang closed 1 year ago

DingliZhang commented 2 years ago

C2调试的主issue https://github.com/openjdk-riscv/jdk11u/issues/342 比较长,目前的问题可能需要深入分析,因此新开一个issue进行记录。 目前的报错:

assert(false) failed: bad AD file

是由于在循环中没有使 svec->valid(x) 函数成立的index。

svec->valid(x)会在build目录下的ad_riscv32.hpp进行定义:

 // Access function for _valid bit vector
  bool valid(uint index) {
    return( STATE__VALID(index) != 0 );
  }

// STATE__VALID的定义
#define STATE__VALID(index)     (_valid[((uint)index) >> 5] &  (0x1 << (((uint)index) & 0x0001F)))

这里的 _valid 是类State的一个public数组,存储了 _LAST_MACH_OPER 个oprand的vaild值(0/1,用int以字节形式对vaild值进行保存,因此会以32个为一组):

// build/linux-riscv32-normal-custom-slowdebug/hotspot/variant-custom/support/adlc/ad_riscv32.hpp
class State : public ResourceObj {
public:
  ...
  unsigned int _valid[(_LAST_MACH_OPER/32)+1]; // Bit Map of valid Cost/Rule entrie
  ...
}

//_LAST_MACH_OPER 的定义
enum MachOperands {
  /*    0 */  UNIVERSE,
  /*    1 */  LABEL,
  ...  
  /*  147 */  _BINARY_IREGP_R11_IREGP_R13,
  // last internally defined operand
  _LAST_MACH_OPER
};

而_LAST_MACH_OPER是由riscv32.ad文件中对应的operand所生成的,所以接下来要看看 _valid数组是在哪里赋值的。

通过查看源代码,发现其与DFA相关。这里的src/hotspot/share/adlc/dfa.cpp为了生成 DFA,会遍历 ADLC 前端生成的理想操作码/匹配列表,以构建case语句(一系列 if 语句)的内容,来匹配ad文件中的理想操作码。

在类State中包含一个成员函数 DFA

// Assign a state to a node, definition of method produced by ADLC
  bool DFA( int opcode, const Node *ideal );

在 build/linux-riscv32-normal-custom-slowdebug/hotspot/variant-custom/support/adlc/dfa_riscv32.cpp 中会对opcode进行匹配,然后调用DFA_PRODUCTION__SET_VALID等宏,从而将类State中的 _valid 数组进行赋值:

#define DFA_PRODUCTION__SET_VALID(result, rule, cost)\
  DFA_PRODUCTION( (result), (rule), (cost) ); STATE__SET_VALID( (result) );

接下来需要结合当前的报错信息,分析State中opcode没有匹配上的原因。

DingliZhang commented 2 years ago

目前生成的报错信息:

--N: o10    Parm    === o3  [[o24 o124 o527 o525 o523 o440 o437 o435 o431 o531 o219 o219 o331 o284 o533 o529 o336 o199 o199 o195 o537 o62 o541 o541 o39 o39 o535 ]] Parm0: byte[int:>=0]:exact *
   IREGP  0  IREGP
   IREGPNOSP  0  IREGPNOSP
   IREGP_R10  0  IREGP_R10
   IREGP_R11  0  IREGP_R11
   IREGP_R12  0  IREGP_R12
   IREGP_R13  0  IREGP_R13
   IREGP_R14  0  IREGP_R14
   IREGP_R15  0  IREGP_R15
   IREGP_R16  0  IREGP_R16
   IREGP_R28  0  IREGP_R28
   JAVATHREAD_REGP  0  JAVATHREAD_REGP
   INDIRECT  0  INDIRECT
   INLINE_CACHE_REGP  0  INLINE_CACHE_REGP
   MEMORY  0  INDIRECT
   IREGNORP  0  IREGP
   IREGILNP  0  IREGP
   IREGILNPNOSP  0  IREGPNOSP

   --N: o200    Phi === o201 o213 o192  [[o192 o199 ]]  #int #tripcount
   IREGI  0  IREGI
   IREGINOSP  0  IREGINOSP
   IREGI_R10  0  IREGI_R10
   IREGI_R12  0  IREGI_R12
   IREGI_R13  0  IREGI_R13
   IREGI_R14  0  IREGI_R14
   IREGIHEAPBASE  0  IREGIHEAPBASE
   IREGIORL2I  0  IREGI
   IREGIORL  0  IREGI
   IREGILNP  0  IREGI
   IREGILNPNOSP  0  IREGINOSP

是由 svec->dump() 所生成的:

void State::dump() {
  tty->print("\n");
  dump(0);
}

void State::dump(int depth) {
  for( int j = 0; j < depth; j++ )
    tty->print("   ");
  tty->print("--N: ");
  _leaf->dump();
  uint i;
  for( i = 0; i < _LAST_MACH_OPER; i++ )
    // Check for valid entry
    if( valid(i) ) {
      for( int j = 0; j < depth; j++ )
        tty->print("   ");
        assert(_cost[i] != max_juint, "cost must be a valid value");
        assert(_rule[i] < _last_Mach_Node, "rule[i] must be valid rule");
        tty->print_cr("%s  %d  %s",
                      ruleName[i], _cost[i], ruleName[_rule[i]] );
      }
  tty->cr();

  for( i=0; i<2; i++ )
    if( _kids[i] )
      _kids[i]->dump(depth+1);
}

报错信息中的两个节点是由_kids[i]->dump(depth+1);生成的,也就是当前报错对应的state的两个孩子节点:

State *_kids[2];       // Children of state node in label tree

o10 Parm 表示参数,是理想图中常用的节点,可能代表I/O输入,内存输入,指针输入,返回值及函数的实参。 o200 Phi 是为SSA准备的节点,通常用于处理数据流的合并。

o10 Parm    === o3  [[o24 o124 o527 o525 o523 o440 o437 o435 o431 o531 o219 o219 o331 o284 o533 o529 o336 o199 o199 o195 o537 o62 o541 o541 o39 o39 o535 ]] Parm0: byte[int:>=0]:exact *

o200    Phi === o201 o213 o192  [[o192 o199 ]]  #int #tripcount

是由 _leaf->dump(); 所输出的,而 _leaf 是State类中一个Node类型的指针变量,代表了匹配树的理想节点。

参考:https://wiki.openjdk.java.net/display/HotSpot/C2+IR+Graph+and+Nodes

axiangyushanhaijing commented 2 years ago

image 对此处的index右移5位的目的不理解。

axiangyushanhaijing commented 2 years ago
// build/linux-riscv32-normal-custom-slowdebug/hotspot/variant-custom/support/adlc/ad_riscv32.hpp
class State : public ResourceObj {
public:
  ...
  unsigned int _valid[(_LAST_MACH_OPER/32)+1]; // Bit Map of valid Cost/Rule entrie
  ...
}

//_LAST_MACH_OPER 的定义
enum MachOperands {
  /*    0 */  UNIVERSE,
  /*    1 */  LABEL,
  ...  
  /*  147 */  _BINARY_IREGP_R11_IREGP_R13,
  // last internally defined operand
  _LAST_MACH_OPER
};

其中_LAST_MACH_OPER是一个枚举变量,在MachOperands 中出现多个关于IMMI_63的变量,与IMMI_63相关的变量在riscv32中应该需要删掉,这样最终的_LAST_MACH_OPER的值会改变,最终影响到 image 最后影响结果: assert(false) failed: bad AD file。 由于 jdk11u/build/linux-riscv32-normal-custom-release/hotspot/variant-custom/gensrc/adfiles/ad_riscv32.hpp文档的编译问题,初步修改调试没有明显变化,后续需要理清楚该文档跟riscv32.ad之间的关系。

尝试在riscv32.ad中删去关于IMMI_63的操作以及指令,但是没有影响。

DingliZhang commented 2 years ago

image 对此处的index右移5位的目的不理解。

这里的话从_valid的定义就能理解了:

unsigned int _valid[(_LAST_MACH_OPER/32)+1];

右移五位和/32的效果是一样的,都是将当前的index映射到数组中对应的字节(32位),而字节中的其中一个bit对应了此index的0/1值。

zifeihan commented 2 years ago

对AD 文件生成的函数进行断点调试

1.我们对 build/linux-riscv32-normal-custom-slowdebug/hotspot/variant-custom/gensrc/adfiles/ad_riscv32.hpp:bool valid(uint index) 函数断点。

image

或者使用GDB命令进行断点。

image

2.切换到线程7(C2编译线程),然后点击栈顶方法,会提示对应的源文件 ad_riscv32.hpp 不存在,然后我们在提示的目录下创建该文件,即可完成对某些函数的断点调试。

image
DingliZhang commented 2 years ago

对AD 文件生成的函数进行断点调试 中,可以执行以下gdb命令:

set substitute-path /home/dingli/jdk11u-jit/make/hotspot /home/dingli/jdk11u-jit/build/linux-riscv32-normal-custom-slowdebug/hotspot/variant-custom/gensrc/adfiles

因为build目录下的文件是在编译期间生成的,所以他会把make目录作为源文件的搜索路径,因此需要替换一下。

zifeihan commented 2 years ago

参考ARM32修改如下,可以向前推进一步。

diff --git a/src/hotspot/cpu/riscv32/riscv32.ad b/src/hotspot/cpu/riscv32/riscv32.ad
index 7aab43b3cc..6abf2ba7a4 100644
--- a/src/hotspot/cpu/riscv32/riscv32.ad
+++ b/src/hotspot/cpu/riscv32/riscv32.ad
@@ -5980,7 +5980,7 @@ instruct addI_reg_imm_l2i(iRegINoSp dst, iRegL src1, immIAdd src2) %{
 %}

 // Pointer Addition
-instruct addP_reg_reg(iRegPNoSp dst, iRegP src1, iRegL src2) %{
+instruct addP_reg_reg(iRegPNoSp dst, iRegP src1, iRegI src2) %{
   match(Set dst (AddP src1 src2));

   ins_cost(ALU_COST);
image
axiangyushanhaijing commented 2 years ago

基于 comment。 发现最终的log产生了差异 image


多次验证发现,导致差异产生的原因是编译执行的命令不是在jdk11u的主目录下执行的。

zifeihan commented 2 years ago

参考ARM32修复 addP_reg_reg instruct 在riscv32 下不能正确匹配 iRegI 的问题,PR:https://github.com/openjdk-riscv/jdk11u/pull/389 ,修复后可以向前推进一步。 执行命令/home/zifeihan/qemu32/bin/qemu-riscv32 -L /opt/riscv32/sysroot ./java -version 新的报错如下:

o560    CmpUL   === _ o612 o559  [[o561 o562 ]] 

--N: o560       CmpUL   === _ o612 o559  [[o561 o562 ]] 

   --N: o612    AddL    === _ o556 o611  [[o560 ]] 
   IREGLNOSP  100  addL_reg_imm
   IREGL_R10  100  addL_reg_imm
   IREGILNPNOSP  100  IREGLNOSP

      --N: o556 ConvI2L === _ o93  [[o612 o614 ]]  #long:minint..maxint
      IREGL  0  IREGL
      IREGLNOSP  1  IREGLNOSP
      IREGL_R0R1  0  IREGL_R0R1
      IREGL_R2R3  0  IREGL_R2R3
      IREGL_R10  0  IREGL_R10
      IREGIORL  0  IREGL
      IREGILNP  0  IREGL
      IREGILNPNOSP  1  IREGLNOSP

      --N: o611 ConL    === o0  [[o612 o583 ]]  #long:-1
      IMML  0  IMML
      IMML_M1  0  IMML_M1
      IMMLADD  0  IMMLADD
      IMMLSUB  0  IMMLSUB
      IMMLOFFSET  0  IMMLOFFSET
      IREGLNOSP  100  loadConL
      IREGL_R10  100  loadConL
      IREGILNPNOSP  100  IREGLNOSP
      IMMIORL  0  IMML

   --N: o559    ConvI2L === _ o381  [[o560 ]]  #long:minint..maxint
   IREGLNOSP  100  convI2L_reg_reg
   IREGL_R10  100  convI2L_reg_reg
   IREGILNPNOSP  100  IREGLNOSP
   _ConvI2L_iRegIorL2I_  0  _ConvI2L_iRegIorL2I_

      --N: o381 LoadRange       === o547 o7 o380  [[o605 o559 ]]  @bottom[int:>=0]+8 *, idx=5; #int:>=0
      IREGI  0  IREGI
      IREGINOSP  0  IREGINOSP
      IREGI_R10  0  IREGI_R10
      IREGI_R12  0  IREGI_R12
      IREGI_R13  0  IREGI_R13
      IREGI_R14  0  IREGI_R14
      IREGIHEAPBASE  0  IREGIHEAPBASE
      IREGIORL2I  0  IREGI
      IREGIORL  0  IREGI
      IREGILNP  0  IREGI
      IREGILNPNOSP  0  IREGINOSP

# To suppress the following error report, specify this argument
# after -XX: or in .hotspotrc:  SuppressErrorAt=/matcher.cpp:1589
#
# A fatal error has been detected by the Java Runtime Environment:
#
#  Internal Error (/home/zifeihan/jdk11u/src/hotspot/share/opto/matcher.cpp:1589), pid=434695, tid=434714
#  assert(false) failed: bad AD file
#
# JRE version: OpenJDK Runtime Environment (11.0.9) (slowdebug build 11.0.9-internal+0-adhoc.zifeihan.jdk11u)
# Java VM: OpenJDK Server VM (slowdebug 11.0.9-internal+0-adhoc.zifeihan.jdk11u, mixed mode, serial gc, linux-riscv32)
# No core dump will be written. Core dumps have been disabled. To enable core dumping, try "ulimit -c unlimited" before starting Java again
#
# An error report file with more information is saved as:
# /home/zifeihan/jdk11u/build/linux-riscv32-normal-custom-slowdebug/jdk/bin/hs_err_pid434695.log
#
# Compiler replay data is saved as:
# /home/zifeihan/jdk11u/build/linux-riscv32-normal-custom-slowdebug/jdk/bin/replay_pid434695.log
#
# If you would like to submit a bug report, please visit:
#   https://bugreport.java.com/bugreport/crash.jsp
#
Current thread is 434714
Dumping core ...
Aborted
shining1984 commented 2 years ago

目前riscv32.ad中,slli指令相关的偏移量的过滤器有几处设置为了63或者是0x3f,这明显是RV64的设置。根据规范,RV32的slli偏移量shamt【5】=0的时候,slli才能正常工作,所以过滤器应为0x1f。

390 更新了这个问题,并未影响当前的运行结果。

DingliZhang commented 2 years ago

当前报错信息中子节点里面的convI2L对应的instruct convI2L_reg_reg 需要进行修改。 参照 src/hotspot/cpu/riscv32/templateTable_riscv32.cpp:TemplateTable::convert()中的逻辑:

  switch (bytecode()) {
  case Bytecodes::_i2l:
    __ srai(x11, x10, 0x1f);
    break;

patch:

diff --git a/src/hotspot/cpu/riscv32/riscv32.ad b/src/hotspot/cpu/riscv32/riscv32.ad
index b2963bc811..8e7b36c76e 100644
--- a/src/hotspot/cpu/riscv32/riscv32.ad
+++ b/src/hotspot/cpu/riscv32/riscv32.ad
@@ -7339,10 +7339,12 @@ instruct convI2L_reg_reg(iRegLNoSp dst, iRegIorL2I src)
 %{
   match(Set dst (ConvI2L src));

-  ins_cost(ALU_COST);
-  format %{ "add  $dst, $src\t#@convI2L_reg_reg" %}
+  ins_cost(ALU_COST * 2);
+  format %{ "add   $dst.lo, $src, zr\n\t"
+            "srai  $dst.hi, $src, 31\t#@convI2L_reg_reg" %}
   ins_encode %{
     __ add(as_Register($dst$$reg), as_Register($src$$reg), zr);
+    __ srai(as_Register($dst$$reg)->successor(), as_Register($src$$reg), 0x1f);
   %}
   ins_pipe(ialu_reg);
 %}

对当前结果没有影响。

DingliZhang commented 2 years ago

根据当前报错,对long型reg进行修改:

diff --git a/src/hotspot/cpu/riscv32/riscv32.ad b/src/hotspot/cpu/riscv32/riscv32.ad
index b2963bc811..70274da74a 100644
--- a/src/hotspot/cpu/riscv32/riscv32.ad
+++ b/src/hotspot/cpu/riscv32/riscv32.ad
@@ -358,14 +358,9 @@ reg_class int_r13_reg(R13);
 // Singleton class for R14 int register
 reg_class int_r14_reg(R14);

-// Class for all long registers
-reg_class all_reg(
-    R0,R1,
-    R2,R3
-);
-
-reg_class long_r0r1_reg(R0, R1);
-reg_class long_r2r3_reg(R2, R3);
+reg_class long_reg (R10, R11, R12, R13);
+reg_class long_r10r11_reg(R10, R11);
+reg_class long_r12r13_reg(R12, R13);

 // Class for all long integer registers (excluding zr)
 reg_class any_reg %{
@@ -711,10 +706,10 @@ source %{
     _ANY_REG32_mask = _ALL_REG32_mask;
     _ANY_REG32_mask.Remove(OptoReg::as_OptoReg(x0->as_VMReg()));

-    _ANY_REG_mask = _ALL_REG_mask;
+    _ANY_REG_mask = _ALL_REG32_mask;
     _ANY_REG_mask.SUBTRACT(_ZR_REG_mask);

-    _PTR_REG_mask = _ALL_REG_mask;
+    _PTR_REG_mask = _ALL_REG32_mask;
     _PTR_REG_mask.SUBTRACT(_ZR_REG_mask);

     _NO_SPECIAL_REG32_mask = _ALL_REG32_mask;
@@ -2355,7 +2350,18 @@ frame %{
       R10_num                            // Op_RegL
     };

-    return OptoRegPair(lo[ideal_reg]);
+    static const int hi[Op_RegL + 1] = { // enum name
+      0,                                 // Op_Node
+      0,                                 // Op_Set
+      OptoReg::Bad,                      // Op_RegN
+      OptoReg::Bad,                      // Op_RegI
+      OptoReg::Bad,                      // Op_RegP
+      OptoReg::Bad,                      // Op_RegF
+      F10_H_num,                         // Op_RegD
+      R11_num                            // Op_RegL
+    };
+
+    return OptoRegPair(hi[ideal_reg], lo[ideal_reg]);
   %}
 %}

@@ -2780,37 +2786,40 @@ operand iRegI_R14()
 // Long Register Operands
 operand iRegL()
 %{
-  constraint(ALLOC_IN_RC(any_reg));
-  match(iRegL_R0R1);
-  match(iRegL_R2R3);
+  constraint(ALLOC_IN_RC(long_reg));
+  match(RegL);
+  match(iRegL_R10R11);
+  match(iRegL_R12R13);
   op_cost(0);
   format %{ %}
   interface(REG_INTER);
 %}

-// Integer 32 bit Register not Special
+// Long Register not Special
 operand iRegLNoSp()
 %{
   constraint(ALLOC_IN_RC(no_special_reg));
-  match(iRegL_R0R1);
-  match(iRegL_R2R3);
+  match(RegL);
+  match(iRegL_R10R11);
   format %{ %}
   interface(REG_INTER);
 %}

-operand iRegL_R0R1()
+operand iRegL_R10R11()
 %{
-  constraint(ALLOC_IN_RC(long_r0r1_reg));
+  constraint(ALLOC_IN_RC(long_r10r11_reg));
   match(RegL);
+  match(iRegLNoSp);
   op_cost(0);
   format %{ %}
   interface(REG_INTER);
 %}

-operand iRegL_R2R3()
+operand iRegL_R12R13()
 %{
-  constraint(ALLOC_IN_RC(long_r2r3_reg));
+  constraint(ALLOC_IN_RC(long_r12r13_reg));
   match(RegL);
+  match(iRegLNoSp);
   op_cost(0);
   format %{ %}
   interface(REG_INTER);
@@ -2960,17 +2969,6 @@ operand iRegIHeapbase()
   interface(REG_INTER);
 %}

-// Long 32 bit Register R10 only
-operand iRegL_R10()
-%{
-  constraint(ALLOC_IN_RC(r10_reg));
-  match(RegL);
-  match(iRegLNoSp);
-  op_cost(0);
-  format %{ %}
-  interface(REG_INTER);
-%}
-
 // Float Register
 // Float register operands
 operand fRegF()
@@ -7341,8 +7339,12 @@ instruct convI2L_reg_reg(iRegLNoSp dst, iRegIorL2I src)

   ins_cost(ALU_COST);
   format %{ "add  $dst, $src\t#@convI2L_reg_reg" %}
+  ins_cost(ALU_COST * 2);
+  format %{ "add   $dst.lo, $src, zr\n\t"
+            "srai  $dst.hi, $src, 31\t#@convI2L_reg_reg" %}
   ins_encode %{
     __ add(as_Register($dst$$reg), as_Register($src$$reg), zr);
+    __ srai(as_Register($dst$$reg)->successor(), as_Register($src$$reg), 0x1f);
   %}
   ins_pipe(ialu_reg);
 %}
@@ -9393,7 +9395,7 @@ instruct partialSubtypeCheckVsZero(iRegP_R14 sub, iRegP_R10 super, iRegP_R12 tem
 %}

 instruct string_compareU(iRegP_R11 str1, iRegI_R12 cnt1, iRegP_R13 str2, iRegI_R14 cnt2,
-                         iRegI_R10 result, iRegP_R28 tmp1, iRegL_R0R1 tmp2, iRegL_R2R3 tmp3, rFlagsReg cr)
+                         iRegI_R10 result, iRegP_R28 tmp1, iRegL_R10R11 tmp2, iRegL_R12R13 tmp3, rFlagsReg cr)
 %{
   predicate(((StrCompNode *)n)->encoding() == StrIntrinsicNode::UU);
   match(Set result(StrComp(Binary str1 cnt1)(Binary str2 cnt2)));
@@ -9411,7 +9413,7 @@ instruct string_compareU(iRegP_R11 str1, iRegI_R12 cnt1, iRegP_R13 str2, iRegI_R
 %}

 instruct string_compareL(iRegP_R11 str1, iRegI_R12 cnt1, iRegP_R13 str2, iRegI_R14 cnt2,
-                         iRegI_R10 result, iRegP_R28 tmp1, iRegL_R0R1 tmp2, iRegL_R2R3 tmp3, rFlagsReg cr)
+                         iRegI_R10 result, iRegP_R28 tmp1, iRegL_R10R11 tmp2, iRegL_R12R13 tmp3, rFlagsReg cr)
 %{
   predicate(((StrCompNode *)n)->encoding() == StrIntrinsicNode::LL);
   match(Set result(StrComp(Binary str1 cnt1)(Binary str2 cnt2)));
@@ -9428,7 +9430,7 @@ instruct string_compareL(iRegP_R11 str1, iRegI_R12 cnt1, iRegP_R13 str2, iRegI_R
 %}

 instruct string_compareUL(iRegP_R11 str1, iRegI_R12 cnt1, iRegP_R13 str2, iRegI_R14 cnt2,
-                          iRegI_R10 result, iRegP_R28 tmp1, iRegL_R0R1 tmp2, iRegL_R2R3 tmp3, rFlagsReg cr)
+                          iRegI_R10 result, iRegP_R28 tmp1, iRegL_R10R11 tmp2, iRegL_R12R13 tmp3, rFlagsReg cr)
 %{
   predicate(((StrCompNode *)n)->encoding() == StrIntrinsicNode::UL);
   match(Set result(StrComp(Binary str1 cnt1)(Binary str2 cnt2)));
@@ -9445,7 +9447,7 @@ instruct string_compareUL(iRegP_R11 str1, iRegI_R12 cnt1, iRegP_R13 str2, iRegI_
 %}

 instruct string_compareLU(iRegP_R11 str1, iRegI_R12 cnt1, iRegP_R13 str2, iRegI_R14 cnt2,
-                          iRegI_R10 result, iRegP_R28 tmp1, iRegL_R0R1 tmp2, iRegL_R2R3 tmp3,
+                          iRegI_R10 result, iRegP_R28 tmp1, iRegL_R10R11 tmp2, iRegL_R12R13 tmp3,
                           rFlagsReg cr)
 %{
   predicate(((StrCompNode *)n)->encoding() == StrIntrinsicNode::LU);
@@ -9589,7 +9591,7 @@ instruct string_indexof_conUL(iRegP_R11 str1, iRegI_R12 cnt1, iRegP_R13 str2,
 %}

 // clearing of an array
-instruct clearArray_reg_reg(iRegL_R0R1 cnt, iRegP_R28 base, Universe dummy, rFlagsReg cr)
+instruct clearArray_reg_reg(iRegL_R10R11 cnt, iRegP_R28 base, Universe dummy, rFlagsReg cr)
 %{
   match(Set dummy (ClearArray cnt base));
   effect(USE_KILL cnt, USE_KILL base, KILL cr);

修改点:

  1. 新增reg_class long_reg;删除reg_class all_reg,用all_reg32/long_reg代替。
  2. 将R0, R1, R2, R3替换为R10, R11, R12, R13;
  3. 新增long_reg,并将R10, R11, R12, R13代入;
  4. OptoRegPair中增加对hi数组的处理;
  5. 删除iRegL_R10;

报错信息:

#
# A fatal error has been detected by the Java Runtime Environment:
#
#  SIGSEGV (0xb) at pc=0x3b96ca98, pid=3223151, tid=3223156
#
# JRE version: OpenJDK Runtime Environment (11.0.9) (slowdebug build 11.0.9-internal+0-adhoc.dingli.jdk11u-jit)
# Java VM: OpenJDK Server VM (slowdebug 11.0.9-internal+0-adhoc.dingli.jdk11u-jit, mixed mode, serial gc, linux-riscv32)
# Problematic frame:
# J 11 c2 java.lang.StringLatin1.hashCode([B)I java.base (42 bytes) @ 0x3b96ca98 [0x3b96ca40+0x00000058]
#
# No core dump will be written. Core dumps have been disabled. To enable core dumping, try "ulimit -c unlimited" before starting Java again
#
# An error report file with more information is saved as:
# /home/dingli/jdk11u-jit/hs_err_pid3223151.log
Compiled method (c2)    2955   11             java.lang.StringLatin1::hashCode (42 bytes)
 total in heap  [0x3b96c908,0x3b96ce30] = 1320
 relocation     [0x3b96c9f8,0x3b96ca10] = 24
 main code      [0x3b96ca40,0x3b96cc40] = 512
 stub code      [0x3b96cc40,0x3b96cc74] = 52
 metadata       [0x3b96cc74,0x3b96cc78] = 4
 scopes data    [0x3b96cc78,0x3b96cce0] = 104
 scopes pcs     [0x3b96cce0,0x3b96ce20] = 320
 dependencies   [0x3b96ce20,0x3b96ce24] = 4
 nul chk table  [0x3b96ce24,0x3b96ce30] = 12
Loaded disassembler from /home/dingli/jdk11u-jit/build/linux-riscv32-normal-custom-slowdebug/jdk/lib/server/hsdis-riscv32.so
BFD: unrecognized disassembler option: 
#
# If you would like to submit a bug report, please visit:
#   https://bugreport.java.com/bugreport/crash.jsp
#
Current thread is 3223156
Dumping core ...
Aborted

但是之前的报错信息没有了,可以加上打印信息判断出来(73为之前的报错CmpUL对应的index):

diff --git a/src/hotspot/share/opto/matcher.cpp b/src/hotspot/share/opto/matcher.cpp
index 9437d379d3..93d2a64a23 100644
--- a/src/hotspot/share/opto/matcher.cpp
+++ b/src/hotspot/share/opto/matcher.cpp
@@ -1582,7 +1582,11 @@ Node* Matcher::Label_Root(const Node* n, State* svec, Node* control, Node
*& mem)
   for( x = 0; x < _LAST_MACH_OPER; x++ )
     if( svec->valid(x) )
       break;
-
+  if (n->Opcode() == 73) {
+    n->dump();
+    svec->dump();
+    warning("---------");
+  }
   if (x >= _LAST_MACH_OPER) {
     n->dump();
     svec->dump();

推测:

  1. 引发了新的问题
  2. 有可能之前走到CmpUL节点的路径本身就是错的,目前还在进行排查。
zifeihan commented 2 years ago

推测:

  1. 引发了新的问题
  2. 有可能之前走到CmpUL节点的路径本身就是错的,目前还在进行排查。

通过调试在报错的位置汇编如下: image 并且访问的 t2 并不是一个内存地址,t2的地址在上面被进行了左移16位,又右移了16位(被清零了): image

基于上述修改,经过简化。修改如下:

diff --git a/src/hotspot/cpu/riscv32/riscv32.ad b/src/hotspot/cpu/riscv32/riscv32.ad
index 6abf2ba7a4..c0de2c7a95 100644
--- a/src/hotspot/cpu/riscv32/riscv32.ad
+++ b/src/hotspot/cpu/riscv32/riscv32.ad
@@ -714,7 +714,7 @@ source %{
     _ANY_REG_mask = _ALL_REG_mask;
     _ANY_REG_mask.SUBTRACT(_ZR_REG_mask);

-    _PTR_REG_mask = _ALL_REG_mask;
+    _PTR_REG_mask = _ALL_REG32_mask;
     _PTR_REG_mask.SUBTRACT(_ZR_REG_mask);

     _NO_SPECIAL_REG32_mask = _ALL_REG32_mask;
@@ -1156,8 +1156,6 @@ uint MachSpillCopyNode::implementation(CodeBuffer *cbuf, PhaseRegAlloc *ra_, boo
       if (dst_lo_rc == rc_int) {  // gpr --> gpr copy
         __ mv(as_Register(Matcher::_regEncode[dst_lo]),
             as_Register(Matcher::_regEncode[src_lo]));
-        if (this->ideal_reg() != Op_RegI) // zero extended for narrow oop or klass
-          __ clear_upper_bits(as_Register(Matcher::_regEncode[dst_lo]), 16);
       } else if (dst_lo_rc == rc_float) { // gpr --> fpr copy
         __ fmv_w_x(as_FloatRegister(Matcher::_regEncode[dst_lo]),
             as_Register(Matcher::_regEncode[src_lo]));
@@ -2355,7 +2353,18 @@ frame %{
       R10_num                            // Op_RegL
     };

-    return OptoRegPair(lo[ideal_reg]);
+    static const int hi[Op_RegL + 1] = { // enum name
+      0,                                 // Op_Node
+      0,                                 // Op_Set
+      OptoReg::Bad,                      // Op_RegN
+      OptoReg::Bad,                      // Op_RegI
+      OptoReg::Bad,                      // Op_RegP
+      OptoReg::Bad,                      // Op_RegF
+      F10_H_num,                         // Op_RegD
+      R11_num                            // Op_RegL
+    };
+
+    return OptoRegPair(hi[ideal_reg], lo[ideal_reg]);
   %}
 %}

由于在32位上int类型和指针类型大小相同,因此将一下代码删除,不做特殊的清零操作,issue:https://github.com/openjdk-riscv/jdk11u/issues/367 也记录了这里需要删除。

-        if (this->ideal_reg() != Op_RegI) // zero extended for narrow oop or klass
-          __ clear_upper_bits(as_Register(Matcher::_regEncode[dst_lo]), 16);
DingliZhang commented 2 years ago

改动的PATCH

https://github.com/openjdk-riscv/jdk11u/issues/388#issuecomment-1127178246 的基础之上添加https://github.com/openjdk-riscv/jdk11u/issues/388#issuecomment-1127407958 的修改,可以往前推进一步,最新的报错信息:

o1629   ClearArray      === o1643 o1624 o1644 o1628  [[o1606  229 ]]   Memory: @rawptr:BotPTR, idx=Raw;

--N: o1629      ClearArray      === o1643 o1624 o1644 o1628  [[o1606  229 ]]   Memory: @rawptr:BotPTR, idx=Raw;

   --N: o1644   AddI    === _ o1626 o1249  [[o1629 ]] 
   IREGI  200  addI_reg_imm
   IREGINOSP  200  addI_reg_imm
   IREGI_R10  200  addI_reg_imm
   IREGI_R12  200  addI_reg_imm
   IREGI_R13  200  addI_reg_imm
   IREGI_R14  200  addI_reg_imm
   IREGIORL2I  200  IREGI
   IREGIORL  200  IREGI
   IREGILNP  200  IREGI
   IREGILNPNOSP  200  IREGINOSP

      --N: o1626        URShiftI        === _ o829 o1155  [[o1644 ]] 
      IREGI  100  urShiftI_reg_imm
      IREGINOSP  100  urShiftI_reg_imm
      IREGI_R10  100  urShiftI_reg_imm
      IREGI_R12  100  urShiftI_reg_imm
      IREGI_R13  100  urShiftI_reg_imm
      IREGI_R14  100  urShiftI_reg_imm
      IREGIORL2I  100  IREGI
      IREGIORL  100  IREGI
      IREGILNP  100  IREGI
      IREGILNPNOSP  100  IREGINOSP

         --N: o829      Phi     === o68 o830 o69 o69  [[o1626 o1610 ]]  #int
         IREGI  0  IREGI
         IREGINOSP  0  IREGINOSP
         IREGI_R10  0  IREGI_R10
         IREGI_R12  0  IREGI_R12
         IREGI_R13  0  IREGI_R13
         IREGI_R14  0  IREGI_R14
         IREGIHEAPBASE  0  IREGIHEAPBASE
         IREGIORL2I  0  IREGI
         IREGIORL  0  IREGI
         IREGILNP  0  IREGI
         IREGILNPNOSP  0  IREGINOSP

         --N: o1155     ConI    === o0  [[o1626 ]]  #int:3
         IMMI  0  IMMI
         IMMI_LE_4  0  IMMI_LE_4
         IMMIADD  0  IMMIADD
         IMMISUB  0  IMMISUB
         IMMIOFFSET  0  IMMIOFFSET
         IREGI  100  loadConI
         IREGINOSP  100  loadConI
         IREGI_R10  100  loadConI
         IREGI_R12  100  loadConI
         IREGI_R13  100  loadConI
         IREGI_R14  100  loadConI
         IREGIORL2I  100  IREGI
         IREGIORL  100  IREGI
         IREGILNP  100  IREGI
         IREGILNPNOSP  100  IREGINOSP
         IMMIORL  0  IMMI

      --N: o1249        ConI    === o0  [[o1644 ]]  #int:-2
      IMMI  0  IMMI
      IMMI_LE_4  0  IMMI_LE_4
      IMMIADD  0  IMMIADD
      IMMISUB  0  IMMISUB
      IMMIOFFSET  0  IMMIOFFSET
      IREGI  100  loadConI
      IREGINOSP  100  loadConI
      IREGI_R10  100  loadConI
      IREGI_R12  100  loadConI
      IREGI_R13  100  loadConI
      IREGI_R14  100  loadConI
      IREGIORL2I  100  IREGI
      IREGIORL  100  IREGI
      IREGILNP  100  IREGI
      IREGILNPNOSP  100  IREGINOSP
      IMMIORL  0  IMMI

   --N: o1628   AddP    === _ o1609 o1609 o69  [[o1629 ]] 
   IREGP  200  addP_reg_reg
   IREGPNOSP  200  addP_reg_reg
   IREGP_R10  200  addP_reg_reg
   IREGP_R11  200  addP_reg_reg
   IREGP_R12  200  addP_reg_reg
   IREGP_R13  200  addP_reg_reg
   IREGP_R14  200  addP_reg_reg
   IREGP_R15  200  addP_reg_reg
   IREGP_R16  200  addP_reg_reg
   IREGP_R28  200  addP_reg_reg
   JAVATHREAD_REGP  200  addP_reg_reg
   INDIRECT  200  addP_reg_reg
   INDOFFI  0  INDOFFI
   INLINE_CACHE_REGP  200  addP_reg_reg
   MEMORY  0  INDOFFI
   IREGNORP  200  IREGP
   IREGILNP  200  IREGP
   IREGILNPNOSP  200  IREGPNOSP

      --N: o1609        LoadP   === o68 o44 o1601  [[o1610 o1618 o1619 o1619 o1621 o1621 o1623 o1623 o1628 o1628 o1607 ]]  @rawptr:BotPTR, idx=Raw; #rawptr:BotPTR (does not depend only on test)
      IREGP  0  IREGP
      IREGPNOSP  0  IREGPNOSP
      IREGP_R10  0  IREGP_R10
      IREGP_R11  0  IREGP_R11
      IREGP_R12  0  IREGP_R12
      IREGP_R13  0  IREGP_R13
      IREGP_R14  0  IREGP_R14
      IREGP_R15  0  IREGP_R15
      IREGP_R16  0  IREGP_R16
      IREGP_R28  0  IREGP_R28
      JAVATHREAD_REGP  0  JAVATHREAD_REGP
      INDIRECT  0  INDIRECT
      INLINE_CACHE_REGP  0  INLINE_CACHE_REGP
      MEMORY  0  INDIRECT
      IREGNORP  0  IREGP
      IREGILNP  0  IREGP
      IREGILNPNOSP  0  IREGPNOSP

      --N: o69  ConI    === o0  [[o70 o829 o829 o1225 o1175 o1628 ]]  #int:16
      IMMI  0  IMMI
      IMMIADD  0  IMMIADD
      IMMISUB  0  IMMISUB
      IMMIOFFSET  0  IMMIOFFSET
      IREGI  100  loadConI
      IREGINOSP  100  loadConI
      IREGI_R10  100  loadConI
      IREGI_R12  100  loadConI
      IREGI_R13  100  loadConI
      IREGI_R14  100  loadConI
      IREGIORL2I  100  IREGI
      IREGIORL  100  IREGI
      IREGILNP  100  IREGI
      IREGILNPNOSP  100  IREGINOSP
      IMMIORL  0  IMMI

# To suppress the following error report, specify this argument
# after -XX: or in .hotspotrc:  SuppressErrorAt=/matcher.cpp:1589
#
# A fatal error has been detected by the Java Runtime Environment:
#
#  Internal Error (/home/dingli/jdk11u-jit/src/hotspot/share/opto/matcher.cpp:1589), pid=3694319, tid=3694338
#  assert(false) failed: bad AD file
#
# JRE version: OpenJDK Runtime Environment (11.0.9) (slowdebug build 11.0.9-internal+0-adhoc.dingli.jdk11u-jit)
# Java VM: OpenJDK Server VM (slowdebug 11.0.9-internal+0-adhoc.dingli.jdk11u-jit, mixed mode, serial gc, linux-riscv32)
# No core dump will be written. Core dumps have been disabled. To enable core dumping, try "ulimit -c unlimited" before starting Java again
#
# An error report file with more information is saved as:
# /home/dingli/jdk11u-jit/hs_err_pid3694319.log
#
# Compiler replay data is saved as:
# /home/dingli/jdk11u-jit/replay_pid3694319.log
#
# If you would like to submit a bug report, please visit:
#   https://bugreport.java.com/bugreport/crash.jsp
#
Current thread is 3694338
Dumping core ...
Aborted

是否推进的测试

是否往前推进可以通过对之前报错的CmpUL进行dump来测试:

diff --git a/src/hotspot/share/opto/matcher.cpp b/src/hotspot/share/opto/matcher.cpp
index 9437d379d3..6be2a2df74 100644
--- a/src/hotspot/share/opto/matcher.cpp
+++ b/src/hotspot/share/opto/matcher.cpp
@@ -1582,7 +1582,12 @@ Node* Matcher::Label_Root(const Node* n, State* svec, Node* control, Node*& mem)
   for( x = 0; x < _LAST_MACH_OPER; x++ )
     if( svec->valid(x) )
       break;
-
+  if (n->Opcode() == 73) {
+    n->dump();
+    svec->dump();
+    assert( false, "bad AD file" );
+    warning("---------");
+  }
   if (x >= _LAST_MACH_OPER) {
     n->dump();
     svec->dump();

输出信息:

o560    CmpUL   === _ o612 o559  [[o561 o562 ]] 

--N: o560       CmpUL   === _ o612 o559  [[o561 o562 ]] 
_CmpUL_iRegL_iRegL  200  _CmpUL_iRegL_iRegL

   --N: o612    AddL    === _ o556 o611  [[o560 ]] 
   IREGL  100  addL_reg_imm
   IREGLNOSP  100  addL_reg_imm
   IREGL_R10R11  100  addL_reg_imm
   IREGL_R12R13  100  addL_reg_imm
   IREGIORL  100  IREGL
   IREGILNP  100  IREGL
   IREGILNPNOSP  100  IREGLNOSP

      --N: o556 ConvI2L === _ o93  [[o612 o614 ]]  #long:minint..maxint
      IREGL  0  IREGL
      IREGLNOSP  1  IREGLNOSP
      IREGL_R10R11  0  IREGL_R10R11
      IREGL_R12R13  0  IREGL_R12R13
      IREGIORL  0  IREGL
      IREGILNP  0  IREGL
      IREGILNPNOSP  1  IREGLNOSP

      --N: o611 ConL    === o0  [[o612 o583 ]]  #long:-1
      IMML  0  IMML
      IMML_M1  0  IMML_M1
      IMMLADD  0  IMMLADD
      IMMLSUB  0  IMMLSUB
      IMMLOFFSET  0  IMMLOFFSET
      IREGL  100  loadConL
      IREGLNOSP  100  loadConL
      IREGL_R10R11  100  loadConL
      IREGL_R12R13  100  loadConL
      IREGIORL  100  IREGL
      IREGILNP  100  IREGL
      IREGILNPNOSP  100  IREGLNOSP
      IMMIORL  0  IMML

   --N: o559    ConvI2L === _ o381  [[o560 ]]  #long:minint..maxint
   IREGL  100  convI2L_reg_reg
   IREGLNOSP  100  convI2L_reg_reg
   IREGL_R10R11  100  convI2L_reg_reg
   IREGL_R12R13  100  convI2L_reg_reg
   IREGIORL  100  IREGL
   IREGILNP  100  IREGL
   IREGILNPNOSP  100  IREGLNOSP
   _ConvI2L_iRegIorL2I_  0  _ConvI2L_iRegIorL2I_

      --N: o381 LoadRange       === o547 o7 o380  [[o605 o559 ]]  @bottom[int:>=0]+8 *, idx=5; #int:>=0
      IREGI  0  IREGI
      IREGINOSP  0  IREGINOSP
      IREGI_R10  0  IREGI_R10
      IREGI_R12  0  IREGI_R12
      IREGI_R13  0  IREGI_R13
      IREGI_R14  0  IREGI_R14
      IREGIHEAPBASE  0  IREGIHEAPBASE
      IREGIORL2I  0  IREGI
      IREGIORL  0  IREGI
      IREGILNP  0  IREGI
      IREGILNPNOSP  0  IREGINOSP

# To suppress the following error report, specify this argument
# after -XX: or in .hotspotrc:  SuppressErrorAt=/matcher.cpp:1588
#
# A fatal error has been detected by the Java Runtime Environment:
#
#  Internal Error (/home/dingli/jdk11u-jit/src/hotspot/share/opto/matcher.cpp:1588), pid=3696555, tid=3696571
#  assert(false) failed: bad AD file
#
# JRE version: OpenJDK Runtime Environment (11.0.9) (slowdebug build 11.0.9-internal+0-adhoc.dingli.jdk11u-jit)
# Java VM: OpenJDK Server VM (slowdebug 11.0.9-internal+0-adhoc.dingli.jdk11u-jit, mixed mode, serial gc, linux-riscv32)
# No core dump will be written. Core dumps have been disabled. To enable core dumping, try "ulimit -c unlimited" before starting Java again
#
# An error report file with more information is saved as:
# /home/dingli/jdk11u-jit/hs_err_pid3696555.log
#
# Compiler replay data is saved as:
# /home/dingli/jdk11u-jit/replay_pid3696555.log
#
# If you would like to submit a bug report, please visit:
#   https://bugreport.java.com/bugreport/crash.jsp
#
Current thread is 3696571
Dumping core ...
Aborted

由此可以看出断言是由测试的时候添加的assert所触发的,之前报错的CmpUL的子节点已经满足了匹配条件。 已提交PR #392

zifeihan commented 2 years ago

修复 clearArray 不能匹配的问题,PR: https://github.com/openjdk-riscv/jdk11u/pull/393 ,修改如下 :

diff --git a/src/hotspot/cpu/riscv32/riscv32.ad b/src/hotspot/cpu/riscv32/riscv32.ad
index f6c34ed503..31c501b306 100644
--- a/src/hotspot/cpu/riscv32/riscv32.ad
+++ b/src/hotspot/cpu/riscv32/riscv32.ad
@@ -2799,7 +2799,7 @@ operand iRegL()
 // Long Register not Special
 operand iRegLNoSp()
 %{
-  constraint(ALLOC_IN_RC(no_special_reg));
+  constraint(ALLOC_IN_RC(long_reg));
   match(RegL);
   match(iRegL_R10R11);
   format %{ %}
@@ -9588,7 +9588,7 @@ instruct string_indexof_conUL(iRegP_R11 str1, iRegI_R12 cnt1, iRegP_R13 str2,
 %}

 // clearing of an array
-instruct clearArray_reg_reg(iRegL_R10R11 cnt, iRegP_R28 base, Universe dummy, rFlagsReg cr)
+instruct clearArray_reg_reg(iRegI_R14 cnt, iRegP_R28 base, Universe dummy, rFlagsReg cr)
 %{
   match(Set dummy (ClearArray cnt base));
   effect(USE_KILL cnt, USE_KILL base, KILL cr);

修改点:

  1. 在处理long类型数据节点时,使用 long_reg ,来代替no_special_reg
  2. 参考arm32 发现 clearArray 匹配时需要使用 iRegI 类型,因此将 iRegL_R10R11 修改为 iRegI_R14 类型 可以解决ClearArray 节点不匹配的问题,修复后报错如下:
    
    o1547   OrI     === _ o1546 o1544  [[o1548 o1566  448 ]] 

--N: o1547 OrI === _ o1546 o1544 [[o1548 o1566 448 ]]

--N: o1546 CastP2X === o1538 o310 [[o1547 ]] IREGL 100 castP2X IREGLNOSP 100 castP2X IREGL_R10R11 100 castP2X IREGL_R12R13 100 castP2X IREGIORL 100 IREGL IREGILNP 100 IREGL IREGILNPNOSP 100 IREGLNOSP _CastP2XiRegP 0 _CastP2XiRegP

  --N: o310 ThreadLocal     === o0  [[o312 o1526 o1576 o1546 o1603 o1601  397 ]] 
  IREGP  0  IREGP
  IREGPNOSP  0  IREGPNOSP
  IREGP_R10  0  IREGP_R10
  IREGP_R11  0  IREGP_R11
  IREGP_R12  0  IREGP_R12
  IREGP_R13  0  IREGP_R13
  IREGP_R14  0  IREGP_R14
  IREGP_R15  0  IREGP_R15
  IREGP_R16  0  IREGP_R16
  IREGP_R28  0  IREGP_R28
  JAVATHREAD_REGP  0  JAVATHREAD_REGP
  INDIRECT  0  INDIRECT
  INLINE_CACHE_REGP  0  INLINE_CACHE_REGP
  MEMORY  0  INDIRECT
  IREGNORP  0  IREGP
  IREGILNP  0  IREGP
  IREGILNPNOSP  0  IREGPNOSP

--N: o1544 LoadI === _ o44 o1543 [[o1547 o1665 ]] @klass java/lang/Object: 0x3e951298+112 *, idx=11; #int IREGI 0 IREGI IREGINOSP 0 IREGINOSP IREGI_R10 0 IREGI_R10 IREGI_R12 0 IREGI_R12 IREGI_R13 0 IREGI_R13 IREGI_R14 0 IREGI_R14 IREGIHEAPBASE 0 IREGIHEAPBASE IREGIORL2I 0 IREGI IREGIORL 0 IREGI IREGILNP 0 IREGI IREGILNPNOSP 0 IREGINOSP

To suppress the following error report, specify this argument

after -XX: or in .hotspotrc: SuppressErrorAt=/matcher.cpp:1589

#

A fatal error has been detected by the Java Runtime Environment:

#

Internal Error (/home/zifeihan/jdk11u/src/hotspot/share/opto/matcher.cpp:1589), pid=4175791, tid=4175807

assert(false) failed: bad AD file

#

JRE version: OpenJDK Runtime Environment (11.0.9) (slowdebug build 11.0.9-internal+0-adhoc.zifeihan.jdk11u)

Java VM: OpenJDK Server VM (slowdebug 11.0.9-internal+0-adhoc.zifeihan.jdk11u, mixed mode, serial gc, linux-riscv32)

No core dump will be written. Core dumps have been disabled. To enable core dumping, try "ulimit -c unlimited" before starting Java again

#

An error report file with more information is saved as:

/home/zifeihan/jdk11u/build/linux-riscv32-normal-custom-slowdebug/jdk/bin/hs_err_pid4175791.log

#

Compiler replay data is saved as:

/home/zifeihan/jdk11u/build/linux-riscv32-normal-custom-slowdebug/jdk/bin/replay_pid4175791.log

#

If you would like to submit a bug report, please visit:

https://bugreport.java.com/bugreport/crash.jsp

# Current thread is 4175807 Dumping core ... Aborted

zifeihan commented 2 years ago

可以通过修改 src/hotspot/share/opto/matcher.cpp: Label_Root 函数,加日志方式来验证是否 ClearArray 节点是否能够正常通过。

image
zifeihan commented 2 years ago

参考arm32 发现riscv32.ad: castP2X 这里也需要修改

diff --git a/src/hotspot/cpu/riscv32/riscv32.ad b/src/hotspot/cpu/riscv32/riscv32.ad
index 31c501b306..59086f8c5f 100644
--- a/src/hotspot/cpu/riscv32/riscv32.ad
+++ b/src/hotspot/cpu/riscv32/riscv32.ad
@@ -7251,7 +7251,7 @@ instruct castX2P(iRegPNoSp dst, iRegL src) %{
   ins_pipe(ialu_reg);
 %}

-instruct castP2X(iRegLNoSp dst, iRegP src) %{
+instruct castP2X(iRegI dst, iRegP src) %{
   match(Set dst (CastP2X src));

   ins_cost(ALU_COST);
DingliZhang commented 2 years ago

参考arm32 发现riscv32.ad: castP2X 这里也需要修改

diff --git a/src/hotspot/cpu/riscv32/riscv32.ad b/src/hotspot/cpu/riscv32/riscv32.ad
index 31c501b306..59086f8c5f 100644
--- a/src/hotspot/cpu/riscv32/riscv32.ad
+++ b/src/hotspot/cpu/riscv32/riscv32.ad
@@ -7251,7 +7251,7 @@ instruct castX2P(iRegPNoSp dst, iRegL src) %{
   ins_pipe(ialu_reg);
 %}

-instruct castP2X(iRegLNoSp dst, iRegP src) %{
+instruct castP2X(iRegI dst, iRegP src) %{
   match(Set dst (CastP2X src));

   ins_cost(ALU_COST);

我建议这里改成 iRegINoSp ,更符合原先的代码格式。

zifeihan commented 2 years ago

根据上文提交 PR: https://github.com/openjdk-riscv/jdk11u/pull/396 修改点:

  1. 参考 bishengJDK/aarch64 新增 iRegI_R29 来作为 clearArray 的 cnt 参数
  2. 参考arm32, 修复 castP2X 节点不匹配的问题, 使用 iRegINoSp 来代替 原来的 iRegLNoSp 类型 修复后最新报错如下:
    zifeihan@k9-plct:~/jdk11u/build/linux-riscv32-normal-custom-slowdebug/jdk/bin$ /home/zifeihan/qemu32/bin/qemu-riscv32 -L /opt/riscv32/sysroot ./java
    # To suppress the following error report, specify this argument
    # after -XX: or in .hotspotrc:  SuppressErrorAt=/frame_riscv32.inline.hpp:79
    #
    # A fatal error has been detected by the Java Runtime Environment:
    #
    #  Internal Error (/home/zifeihan/jdk11u/src/hotspot/cpu/riscv32/frame_riscv32.inline.hpp:79), pid=1019264, tid=1019266
    #  assert(pc != __null) failed: no pc?
    #
    # JRE version: OpenJDK Runtime Environment (11.0.9) (slowdebug build 11.0.9-internal+0-adhoc.zifeihan.jdk11u)
    # Java VM: OpenJDK Server VM (slowdebug 11.0.9-internal+0-adhoc.zifeihan.jdk11u, mixed mode, serial gc, linux-riscv32)
    # No core dump will be written. Core dumps have been disabled. To enable core dumping, try "ulimit -c unlimited" before starting Java again
    #
    # An error report file with more information is saved as:
    # /home/zifeihan/jdk11u/build/linux-riscv32-normal-custom-slowdebug/jdk/bin/hs_err_pid1019264.log
    #
    # If you would like to submit a bug report, please visit:
    #   https://bugreport.java.com/bugreport/crash.jsp
    #
    Current thread is 1019266
    Dumping core ...
    Aborted
    zifeihan@k9-plct:~/jdk11u/build/linux-riscv32-normal-custom-slowdebug/jdk/bin$

验证修复是否有效,我们可以打上如下日志,因为 OrI 报错时的 n->Opcode() 为221,修复前走不到最后的日志位置。修复后可以走到最后的日志位置。

diff --git a/src/hotspot/share/opto/matcher.cpp b/src/hotspot/share/opto/matcher.cpp
index 9437d379d3..07b8cf466a 100644
--- a/src/hotspot/share/opto/matcher.cpp
+++ b/src/hotspot/share/opto/matcher.cpp
@@ -1588,6 +1588,16 @@ Node* Matcher::Label_Root(const Node* n, State* svec, Node* control, Node*& mem)
     svec->dump();
     assert( false, "bad AD file" );
   }
+
+  int aa = n->Opcode();
+  if (aa == 221)
+  {
+    warning("----------------------");
+    n->dump();
+    svec->dump();
+    warning("----------------------");
+  }
+  
 #endif
   return control;
 }
DingliZhang commented 2 years ago

打上这个patch来输出日志:

diff --git a/src/hotspot/cpu/riscv32/frame_riscv32.inline.hpp b/src/hotspot/cpu/riscv32/frame_riscv32.inline.hpp
index 1f7a278ec6..c882d69cc7 100644
--- a/src/hotspot/cpu/riscv32/frame_riscv32.inline.hpp
+++ b/src/hotspot/cpu/riscv32/frame_riscv32.inline.hpp
@@ -77,6 +77,7 @@ inline frame::frame(intptr_t* ptr_sp, intptr_t* unextended_sp, intptr_t* ptr_fp,
   _fp = ptr_fp;
   _pc = pc;
   assert(pc != NULL, "no pc?");
+  warning("yes pc!");
   _cb = CodeCache::find_blob(pc);
   adjust_unextended_sp();

添加上这个修改 https://github.com/openjdk-riscv/jdk11u/issues/381#issue-1213836018

可以发现多打印了一行日志,报错信息也改变了(左侧为PR #396 之后的报错 ):

image
DingliZhang commented 2 years ago

在 PR #396 的代码下确实会有大概10%的概率出现下列报错:

# To suppress the following error report, specify this argument
# after -XX: or in .hotspotrc:  SuppressErrorAt=/sharedRuntime.cpp:1259
#
# A fatal error has been detected by the Java Runtime Environment:
#
#  Internal Error (/home/dingli/jdk11u-jit/src/hotspot/share/runtime/sharedRuntime.cpp:1259), pid=2794490, tid=2794492
#  guarantee(caller_cb != NULL && caller_cb->is_compiled()) failed: must be called from compiled method
#
# JRE version: OpenJDK Runtime Environment (11.0.9) (slowdebug build 11.0.9-internal+0-adhoc.dingli.jdk11u-jit)
# Java VM: OpenJDK Server VM (slowdebug 11.0.9-internal+0-adhoc.dingli.jdk11u-jit, mixed mode, serial gc, linux-riscv32)
# No core dump will be written. Core dumps have been disabled. To enable core dumping, try "ulimit -c unlimited" before starting Java again
#
# An error report file with more information is saved as:
# /home/dingli/jdk11u-jit/build/linux-riscv32-normal-custom-slowdebug/jdk/bin/hs_err_pid2794490.log
#
# If you would like to submit a bug report, please visit:
#   https://bugreport.java.com/bugreport/crash.jsp
#

https://github.com/openjdk-riscv/jdk11u/issues/381#issue-1213836018 修改前后分别运行100次,日志如下: log_run_8.log log_run_16.log

可以看到在其中StackAlignmentInBytes为8的情况下报错有89次是no pc,11次是 failed: must be called from compiled method ,StackAlignmentInBytes为16的时候报错全部是 failed: must be called from compiled method ,结合 https://github.com/openjdk-riscv/jdk11u/issues/388#issuecomment-1128552870https://github.com/openjdk-riscv/jdk11u/issues/381#issue-1213836018 确实可以往前推进,并且固定报错信息。 已提交PR #397

shining1984 commented 2 years ago

当下的entry_frame_call_wrapper_offset和RV64、aarch64是一样的,都是-8,但是X86和arm的32位用的都是0或者2。 这个值,是由stubGenerator_riscv32.cpp之中的enum call_stub_layout之中的call_wrapper_off = -8决定的。 目前,还没有其他架构的64位和32位使用相同的结果,所以,怀疑RV32的enum call_stub_layout和RV64一致是否合适。

zifeihan commented 2 years ago

OpenJDK for RV32G当前的报错如下:

zifeihan@k9-plct:~/jdk11u/build/linux-riscv32-normal-custom-slowdebug/jdk/bin$ /home/zifeihan/qemu32/bin/qemu-riscv32 -L /opt/riscv32/sysroot ./java
# To suppress the following error report, specify this argument
# after -XX: or in .hotspotrc:  SuppressErrorAt=/sharedRuntime.cpp:1259
#
# A fatal error has been detected by the Java Runtime Environment:
#
#  Internal Error (/home/zifeihan/jdk11u/src/hotspot/share/runtime/sharedRuntime.cpp:1259), pid=776332, tid=776334
#  guarantee(caller_cb != NULL && caller_cb->is_compiled()) failed: must be called from compiled method
#
# JRE version: OpenJDK Runtime Environment (11.0.9) (slowdebug build 11.0.9-internal+0-adhoc.zifeihan.jdk11u)
# Java VM: OpenJDK Server VM (slowdebug 11.0.9-internal+0-adhoc.zifeihan.jdk11u, mixed mode, serial gc, linux-riscv32)
# No core dump will be written. Core dumps have been disabled. To enable core dumping, try "ulimit -c unlimited" before starting Java again
#
# An error report file with more information is saved as:
# /home/zifeihan/jdk11u/build/linux-riscv32-normal-custom-slowdebug/jdk/bin/hs_err_pid776332.log
#
# If you would like to submit a bug report, please visit:
#   https://bugreport.java.com/bugreport/crash.jsp
#
Current thread is 776334
Dumping core ...
Aborted

通过如下参数打印编译日志:/home/zifeihan/qemu32/bin/qemu-riscv32 -L /opt/riscv32/sysroot ./java -XX:+LogCompilation -XX:LogFile=/home/zifeihan/aaaaa.xml

OpenJDK for RV32G 编译日志附件:aaaaa.xml.zip

可以看到如下方法编译失败:jdk.internal.org.objectweb.asm.ByteVector putUTF8 (Ljava/lang/String;)Ljdk/internal/org/objectweb/asm/ByteVector;

image

相同的方法在BishengJDK 里面并没有报错, 因为OpenJDK for RV32G是在第一次进入src/hotspot/share/runtime/sharedRuntime.cpp:SharedRuntime::resolve_sub_helper(JavaThread *thread,bool is_virtual,bool is_optimized, TRAPS)方法时报错的,通过在 bishengJDK 代码中对 OpenJDK for RV32G 报错的位置进行打印日志数据,发现本身 codeblob 指向的方法是 "jdk.internal.org.objectweb.asm.ByteVector.putUTF8(Ljava/lang/String;)Ljdk/internal/org/objectweb/asm/ByteVector;" 这个方法也正好对应了 OpenJDK for RV32G 编译日志中报错的方法。

image

BishengJDK 编译日志附件:bishengJDK.xml.zip

推测目前可能造成 OpenJDK for RV32G 报错 的问题有两个:

  1. 因为jdk.internal.org.objectweb.asm.ByteVector putUTF8 (Ljava/lang/String;)Ljdk/internal/org/objectweb/asm/ByteVector; 编译失败导致的报错,这个报错之前在aarch64上也出现过:https://bugs.openjdk.java.net/browse/JDK-8183543
  2. 因为不确定 OpenJDK for RV32G 当前的 codeblob 是否是指向jdk.internal.org.objectweb.asm.ByteVector putUTF8 (Ljava/lang/String;)Ljdk/internal/org/objectweb/asm/ByteVector; 的方法,也有可能OpenJDK for RV32G 当前的 codeblob 指向的是一个错误的codeblob
zifeihan commented 2 years ago
  1. 因为jdk.internal.org.objectweb.asm.ByteVector putUTF8 (Ljava/lang/String;)Ljdk/internal/org/objectweb/asm/ByteVector; 编译失败导致的报错,这个报错之前在aarch64上也出现过:https://bugs.openjdk.java.net/browse/JDK-8183543

参考arm, x86 的64位和32位对比,INTPRESSURE 参数应该是指明用作 long 类型数据运算寄存器的个数。

编译报错的问题打上如下patch,然后重新执行,编译日志里面就没有报错的日志了:

diff --git a/src/hotspot/cpu/riscv32/c2_globals_riscv32.hpp b/src/hotspot/cpu/riscv32/c2_globals_riscv32.hpp
index 08a2de1235..90c7b6d1dd 100644
--- a/src/hotspot/cpu/riscv32/c2_globals_riscv32.hpp
+++ b/src/hotspot/cpu/riscv32/c2_globals_riscv32.hpp
@@ -50,7 +50,7 @@ define_pd_global(intx, ConditionalMoveLimit,         0);
 define_pd_global(intx, FLOATPRESSURE,                64);
 define_pd_global(intx, FreqInlineSize,               325);
 define_pd_global(intx, MinJumpTableSize,             10);
-define_pd_global(intx, INTPRESSURE,                  24);
+define_pd_global(intx, INTPRESSURE,                  12);
 define_pd_global(intx, InteriorEntryAlignment,       16);
 define_pd_global(intx, NewSizeThreadIncrease, ScaleForWordSize(4*K));
 define_pd_global(intx, LoopUnrollLimit,              60);
diff --git a/src/hotspot/cpu/riscv32/riscv32.ad b/src/hotspot/cpu/riscv32/riscv32.ad
index a3837df4df..891d7125c8 100644
--- a/src/hotspot/cpu/riscv32/riscv32.ad
+++ b/src/hotspot/cpu/riscv32/riscv32.ad
@@ -361,7 +361,7 @@ reg_class int_r14_reg(R14);
 // Singleton class for R29 int register
 reg_class int_r29_reg(R29);

-reg_class long_reg (R10, R11, R12, R13);
+reg_class long_reg (R10,R11, R12,R13, R14,R15, R16,R17, R18,R19, R20,R21);
 reg_class long_r10r11_reg(R10, R11);
 reg_class long_r12r13_reg(R12, R13);
zifeihan commented 2 years ago

针对目前的报错:

zifeihan@k9-plct:~/jdk11u/build/linux-riscv32-normal-custom-slowdebug/jdk/bin$ /home/zifeihan/qemu32/bin/qemu-riscv32 -L /opt/riscv32/sysroot ./java
# To suppress the following error report, specify this argument
# after -XX: or in .hotspotrc:  SuppressErrorAt=/sharedRuntime.cpp:1259
#
# A fatal error has been detected by the Java Runtime Environment:
#
#  Internal Error (/home/zifeihan/jdk11u/src/hotspot/share/runtime/sharedRuntime.cpp:1259), pid=776332, tid=776334
#  guarantee(caller_cb != NULL && caller_cb->is_compiled()) failed: must be called from compiled method
#
# JRE version: OpenJDK Runtime Environment (11.0.9) (slowdebug build 11.0.9-internal+0-adhoc.zifeihan.jdk11u)
# Java VM: OpenJDK Server VM (slowdebug 11.0.9-internal+0-adhoc.zifeihan.jdk11u, mixed mode, serial gc, linux-riscv32)
# No core dump will be written. Core dumps have been disabled. To enable core dumping, try "ulimit -c unlimited" before starting Java again
#
# An error report file with more information is saved as:
# /home/zifeihan/jdk11u/build/linux-riscv32-normal-custom-slowdebug/jdk/bin/hs_err_pid776332.log
#
# If you would like to submit a bug report, please visit:
#   https://bugreport.java.com/bugreport/crash.jsp
#
Current thread is 776334
Dumping core ...
Aborted

为了查看报错时的codeblob 指针指向,我们加入如下日志:

diff --git a/src/hotspot/cpu/riscv32/frame_riscv32.cpp b/src/hotspot/cpu/riscv32/frame_riscv32.cpp
index 56fab75baa..4c966aa2dc 100644
--- a/src/hotspot/cpu/riscv32/frame_riscv32.cpp
+++ b/src/hotspot/cpu/riscv32/frame_riscv32.cpp
@@ -463,6 +463,7 @@ frame frame::sender_for_compiled_frame(RegisterMap* map) const {

   // the return_address is always the word on the stack
   address sender_pc = (address) *(l_sender_sp-1);
+  warning("sender pc: %p , value: %p", l_sender_sp-1, sender_pc);

   intptr_t** saved_fp_addr = (intptr_t**) (l_sender_sp - frame::sender_sp_offset);

首先我们将断点打在 /home/zifeihan/jdk11u/src/hotspot/share/runtime/sharedRuntime.cpp:1259 查看报错时的调用栈。

image

该函数大体汇编代码如下,并可以大致推测该函数保存了很多寄存器,并结合调用场景分析应该是src/hotspot/cpu/riscv32/sharedRuntime_riscv32.cpp:gen_c2i_adapter 函数生成的汇编代码。

image image

通过对bishengJDK的调试,发现bishengJDK的codeblob 的指针指向是通过类似上述汇编函数的第一条和第二条指令来修改的,也就是如下两条汇编代码,也就是这里通过 4(sp) 来指向codeblob,注意这条汇编的内存地址(*0x3b8a8684),下一步需要在该地址打断点。

image

第二步,查看通过warning("sender pc: %p , value: %p", l_sender_sp-1, sender_pc);打印出来的内存地址,是否是上一步所说的 4(sp) 指向的内存地址。

image

第三步,重新启动程序,并将断点打到*0x3b8a8684,并查看前后40条指令,对比是否是第一步所看的汇编函数的指令,此处可以看到确实是该函数。

image

这里我们查看 4(sp) 的地址为:sp + 4 = 0x3ec89ac0 + 4 = 0x3ec89ac4 , 这个地址和我们通过warning("sender pc: %p , value: %p", l_sender_sp-1, sender_pc);打印出来的内存地址:0x3ec89bc4 相差了 256

第四步,查看 src/hotspot/cpu/riscv32/sharedRuntime_riscv32.cpp:gen_c2i_adapter 函数逻辑,查看该函数中调用了push_CPU_state 函数,然而该函数保存浮点数寄存器,但是这里使用 fsd 指令把每个浮点数寄存器用了wordsize(4)字节的的内存空间来保存。于是我们修改此处代码如下:

diff --git a/src/hotspot/cpu/riscv32/frame_riscv32.cpp b/src/hotspot/cpu/riscv32/frame_riscv32.cpp
index 56fab75baa..4c966aa2dc 100644
--- a/src/hotspot/cpu/riscv32/frame_riscv32.cpp
+++ b/src/hotspot/cpu/riscv32/frame_riscv32.cpp
@@ -463,6 +463,7 @@ frame frame::sender_for_compiled_frame(RegisterMap* map) const {

   // the return_address is always the word on the stack
   address sender_pc = (address) *(l_sender_sp-1);
+  warning("sender pc: %p , value: %p", l_sender_sp-1, sender_pc);

   intptr_t** saved_fp_addr = (intptr_t**) (l_sender_sp - frame::sender_sp_offset);

diff --git a/src/hotspot/cpu/riscv32/macroAssembler_riscv32.cpp b/src/hotspot/cpu/riscv32/macroAssembler_riscv32.cpp
index a709354131..2c2509b580 100644
--- a/src/hotspot/cpu/riscv32/macroAssembler_riscv32.cpp
+++ b/src/hotspot/cpu/riscv32/macroAssembler_riscv32.cpp
@@ -1152,17 +1152,17 @@ void MacroAssembler::popa() {
 void MacroAssembler::push_CPU_state() {
   push_reg(0xfffffff8, sp);         // integer registers except zr(x0) & ra(x1) & sp(x2)
   // float registers
-  addi(sp, sp, - 32 * wordSize);
+  addi(sp, sp, - 32 * 2 * wordSize);
   for (int i = 0; i <= 31; i ++) {
-    fsd(as_FloatRegister(i), Address(sp, i * wordSize));
+    fsd(as_FloatRegister(i), Address(sp, i * 2 * wordSize));
   }
 }

 void MacroAssembler::pop_CPU_state() {
   for (int i = 0; i <= 31; i ++) {
-    fld(as_FloatRegister(i), Address(sp, i * wordSize));
+    fld(as_FloatRegister(i), Address(sp, i * 2 * wordSize));
   }
-  addi(sp, sp, 32 * wordSize);
+  addi(sp, sp, 32 * 2 * wordSize);
   pop_reg(0xfffffff8, sp);         // integer registers except zr(x0) & ra(x1) & sp(x2)
 }

然后编译重新启动,再次通过上面的办法调试,发现 4(sp) 的地址为:sp + 4 = 0x3ec89ac0 + 4 = 0x3ec89ac4 , 这个地址和我们通过warning("sender pc: %p , value: %p", l_sender_sp-1, sender_pc);打印出来的内存地址: 0x3ec89b44 相差了 128

通过这里的代码调试,我们发现在 src/hotspot/cpu/riscv32/sharedRuntime_riscv32.cpp:gen_c2i_adapter 中对 sp 的操作,会影响当前的报错问题。如果我们在这里将还缺失的128偏移量补上去,那么当前的问题就得以解决。

image

这里我们通过将开辟的大小 * 3 ,来补上缺失的 256 字节的大小。

image

注意:已提交pr: https://github.com/openjdk-riscv/jdk11u/pull/401 ,修复后对当前结果没影响。如上述,修复后通过调试发现,内存差距小了。目前这里我觉得改成将原有大小 * 2是合理的,因为 fsd 操作 8 字节的内存数据,但是改成 3 就不合理了,目前还相差的 128 字节数据还在排查中。

diff --git a/src/hotspot/cpu/riscv32/frame_riscv32.cpp b/src/hotspot/cpu/riscv32/frame_riscv32.cpp
index 56fab75baa..4c966aa2dc 100644
--- a/src/hotspot/cpu/riscv32/frame_riscv32.cpp
+++ b/src/hotspot/cpu/riscv32/frame_riscv32.cpp
@@ -463,6 +463,7 @@ frame frame::sender_for_compiled_frame(RegisterMap* map) const {

   // the return_address is always the word on the stack
   address sender_pc = (address) *(l_sender_sp-1);
+  warning("sender pc: %p , value: %p", l_sender_sp-1, sender_pc);

   intptr_t** saved_fp_addr = (intptr_t**) (l_sender_sp - frame::sender_sp_offset);

diff --git a/src/hotspot/cpu/riscv32/macroAssembler_riscv32.cpp b/src/hotspot/cpu/riscv32/macroAssembler_riscv32.cpp
index a709354131..2c2509b580 100644
--- a/src/hotspot/cpu/riscv32/macroAssembler_riscv32.cpp
+++ b/src/hotspot/cpu/riscv32/macroAssembler_riscv32.cpp
@@ -1152,17 +1152,17 @@ void MacroAssembler::popa() {
 void MacroAssembler::push_CPU_state() {
   push_reg(0xfffffff8, sp);         // integer registers except zr(x0) & ra(x1) & sp(x2)
   // float registers
-  addi(sp, sp, - 32 * wordSize);
+  addi(sp, sp, - 32 * 2 * wordSize);
   for (int i = 0; i <= 31; i ++) {
-    fsd(as_FloatRegister(i), Address(sp, i * wordSize));
+    fsd(as_FloatRegister(i), Address(sp, i * 2 * wordSize));
   }
 }

 void MacroAssembler::pop_CPU_state() {
   for (int i = 0; i <= 31; i ++) {
-    fld(as_FloatRegister(i), Address(sp, i * wordSize));
+    fld(as_FloatRegister(i), Address(sp, i * 2 * wordSize));
   }
-  addi(sp, sp, 32 * wordSize);
+  addi(sp, sp, 32 * 2 * wordSize);
   pop_reg(0xfffffff8, sp);         // integer registers except zr(x0) & ra(x1) & sp(x2)
 }
zifeihan commented 2 years ago

打上如下patch,即可解决当前遇到的编译问题,src/hotspot/share/runtime/sharedRuntime.cpp:SharedRuntime::resolve_sub_helper(JavaThread *thread,bool is_virtual,bool is_optimized, TRAPS) 也可以正常执行结束,修复后遇到了一个新的问题,目前正在排查新的问题。

diff --git a/src/hotspot/cpu/riscv32/c2_globals_riscv32.hpp b/src/hotspot/cpu/riscv32/c2_globals_riscv32.hpp
index 08a2de1235..90c7b6d1dd 100644
--- a/src/hotspot/cpu/riscv32/c2_globals_riscv32.hpp
+++ b/src/hotspot/cpu/riscv32/c2_globals_riscv32.hpp
@@ -50,7 +50,7 @@ define_pd_global(intx, ConditionalMoveLimit,         0);
 define_pd_global(intx, FLOATPRESSURE,                64);
 define_pd_global(intx, FreqInlineSize,               325);
 define_pd_global(intx, MinJumpTableSize,             10);
-define_pd_global(intx, INTPRESSURE,                  24);
+define_pd_global(intx, INTPRESSURE,                  12);
 define_pd_global(intx, InteriorEntryAlignment,       16);
 define_pd_global(intx, NewSizeThreadIncrease, ScaleForWordSize(4*K));
 define_pd_global(intx, LoopUnrollLimit,              60);
diff --git a/src/hotspot/cpu/riscv32/macroAssembler_riscv32.cpp b/src/hotspot/cpu/riscv32/macroAssembler_riscv32.cpp
index a709354131..2c2509b580 100644
--- a/src/hotspot/cpu/riscv32/macroAssembler_riscv32.cpp
+++ b/src/hotspot/cpu/riscv32/macroAssembler_riscv32.cpp
@@ -1152,17 +1152,17 @@ void MacroAssembler::popa() {
 void MacroAssembler::push_CPU_state() {
   push_reg(0xfffffff8, sp);         // integer registers except zr(x0) & ra(x1) & sp(x2)
   // float registers
-  addi(sp, sp, - 32 * wordSize);
+  addi(sp, sp, - 32 * 2 * wordSize);
   for (int i = 0; i <= 31; i ++) {
-    fsd(as_FloatRegister(i), Address(sp, i * wordSize));
+    fsd(as_FloatRegister(i), Address(sp, i * 2 * wordSize));
   }
 }

 void MacroAssembler::pop_CPU_state() {
   for (int i = 0; i <= 31; i ++) {
-    fld(as_FloatRegister(i), Address(sp, i * wordSize));
+    fld(as_FloatRegister(i), Address(sp, i * 2 * wordSize));
   }
-  addi(sp, sp, 32 * wordSize);
+  addi(sp, sp, 32 * 2 * wordSize);
   pop_reg(0xfffffff8, sp);         // integer registers except zr(x0) & ra(x1) & sp(x2)
 }

diff --git a/src/hotspot/cpu/riscv32/riscv32.ad b/src/hotspot/cpu/riscv32/riscv32.ad
index a3837df4df..891d7125c8 100644
--- a/src/hotspot/cpu/riscv32/riscv32.ad
+++ b/src/hotspot/cpu/riscv32/riscv32.ad
@@ -361,7 +361,7 @@ reg_class int_r14_reg(R14);
 // Singleton class for R29 int register
 reg_class int_r29_reg(R29);

-reg_class long_reg (R10, R11, R12, R13);
+reg_class long_reg (R10,R11, R12,R13, R14,R15, R16,R17, R18,R19, R20,R21);
 reg_class long_r10r11_reg(R10, R11);
 reg_class long_r12r13_reg(R12, R13);

diff --git a/src/hotspot/cpu/riscv32/sharedRuntime_riscv32.cpp b/src/hotspot/cpu/riscv32/sharedRuntime_riscv32.cpp
index 7fbcd0bc0f..468cce0810 100644
--- a/src/hotspot/cpu/riscv32/sharedRuntime_riscv32.cpp
+++ b/src/hotspot/cpu/riscv32/sharedRuntime_riscv32.cpp
@@ -94,13 +94,13 @@ class RegisterSaver {
   // |---ra---|
   static int reg_offset_in_bytes(Register r) {
     assert (r->encoding() > 2, "ra and sp not saved");
-    return (32 /* floats*/ + r->encoding() - 2 /* x1, x2*/) * wordSize;
+    return (r->encoding() - 2 /* x1, x2*/) * wordSize + 32 * 2 * wordSize /* floats*/ ;
   }
   static int x10_offset_in_bytes(void)        { return reg_offset_in_bytes(x10); } // x10
   static int xmethod_offset_in_bytes(void)    { return reg_offset_in_bytes(xmethod); } // x31
   static int tmp0_offset_in_bytes(void)       { return reg_offset_in_bytes(t0); } // x5
   static int f0_offset_in_bytes(void)         { return 0; }
-  static int f10_offset_in_bytes(void)        { return 10 /* floats*/ * wordSize; }
+  static int f10_offset_in_bytes(void)        { return 10 /* floats*/ * 2 * wordSize; }
   static int return_offset_in_bytes(void)     { return return_off * BytesPerInt; }

   // During deoptimization only the result registers need to be restored,
@@ -116,9 +116,9 @@ class RegisterSaver {
     // setting for it. We must therefore force the layout
     // so that it agrees with the frame sender code.
     x0_off        = fpu_state_off + FPUStateSizeInWords,
-    fp_off        = x0_off + 30 * 2,
-    return_off    = fp_off + 2,      // slot for return address
-    reg_save_size = return_off + 2
+    fp_off        = x0_off + 30,
+    return_off    = fp_off + 1,      // slot for return address
+    reg_save_size = return_off + 1
   };
 };

@@ -150,7 +150,7 @@ OopMap* RegisterSaver::save_live_registers(MacroAssembler* masm, int additional_
   for (int i = 3; i < RegisterImpl::number_of_registers; i++) {
     Register r = as_Register(i);
     if (r != xthread && r != t0 && r != t1) {
-      int sp_offset = 2 * ((i - 2) + 32); // SP offsets are in 4-byte words, register slots are 8 bytes
+      int sp_offset = (i - 2) + (32 * 2); // SP offsets are in 4-byte words, register slots are 8 bytes
                                           // wide, 32 floating-point registers
       oop_map->set_callee_saved(VMRegImpl::stack2reg(sp_offset + additional_frame_slots), r->as_VMReg());
     }

修复后的结果:

image

通过查看jit编译日志,也可以看到比原来编译的方法更多了,可以通过如下命令打印jit日志:/home/zifeihan/qemu32/bin/qemu-riscv32 -L /opt/riscv32/sysroot ./java -XX:+LogCompilation -XX:LogFile=jit.log

image

通过对原来的报错方法打断点,发现该方法可以正常执行完成

image
zifeihan commented 2 years ago
-    fp_off        = x0_off + 30 * 2,
-    return_off    = fp_off + 2,      // slot for return address
-    reg_save_size = return_off + 2
+    fp_off        = x0_off + 30,
+    return_off    = fp_off + 1,      // slot for return address
+    reg_save_size = return_off + 1

这一部分是参考arm尝试进行的修复,按照arm32位推测,整数寄存器宽度为4字节,因此这里不需要*2

shining1984 commented 2 years ago
  • return (32 / floats/ + r->encoding() - 2 / x1, x2/) * wordSize;
  • return (r->encoding() - 2 / x1, x2/) wordSize + 32 2 wordSize / floats*/ ;

建议改为: return (2 32 / floats/ + r->encoding() - 2 / x1, x2/) wordSize

zifeihan commented 2 years ago

打上如下patch,即可解决当前遇到的编译问题,src/hotspot/share/runtime/sharedRuntime.cpp:SharedRuntime::resolve_sub_helper(JavaThread *thread,bool is_virtual,bool is_optimized, TRAPS) 也可以正常执行结束

已提交PR:https://github.com/openjdk-riscv/jdk11u/pull/406

zifeihan commented 2 years ago

目前的报错如下

zifeihan@k9-plct:~/jdk11u/build/linux-riscv32-normal-custom-slowdebug/jdk/bin$ /home/zifeihan/qemu32/bin/qemu-riscv32 -L /opt/riscv32/sysroot -g 28080 ./java -XX:+LogCompilation -XX:LogFile=compile.log
Warning:  TraceDependencies results may be inflated by VerifyDependencies
OpenJDK Server VM warning: hello
# To suppress the following error report, specify this argument
# after -XX: or in .hotspotrc:  SuppressErrorAt=/oopMap.cpp:552
#
# A fatal error has been detected by the Java Runtime Environment:
#
#  Internal Error (/home/zifeihan/jdk11u/src/hotspot/share/compiler/oopMap.cpp:552), pid=2561590, tid=2561689
#  assert(last->pc_offset() == pc_offset) failed: oopmap not found
#
# JRE version: OpenJDK Runtime Environment (11.0.9) (slowdebug build 11.0.9-internal+0-adhoc.zifeihan.jdk11u)
# Java VM: OpenJDK Server VM (slowdebug 11.0.9-internal+0-adhoc.zifeihan.jdk11u, mixed mode, serial gc, linux-riscv32)
# No core dump will be written. Core dumps have been disabled. To enable core dumping, try "ulimit -c unlimited" before starting Java again
#
# An error report file with more information is saved as:
# /home/zifeihan/jdk11u/build/linux-riscv32-normal-custom-slowdebug/jdk/bin/hs_err_pid2561590.log
OpenJDK Server VM warning: hello
#
# If you would like to submit a bug report, please visit:
#   https://bugreport.java.com/bugreport/crash.jsp
#
Current thread is 2561689
Dumping core ...
Aborted
image

assert 中的80是从经过如下函数处理转换而来,主要是通过原来的值32 + 12 NativeInstruction::instruction_size = 80 , 抛开原来的值32,优先排查这里的 12 NativeInstruction::instruction_size 合理性。

image image
zifeihan commented 2 years ago

通过修改如下代码,会出现新的报错:

image

新的报错日志如下:

image

已提交PR : https://github.com/openjdk-riscv/jdk11u/pull/410

shining1984 commented 2 years ago

在昨天的测试中发现,使用make images编译的时候,会报错: image 这个错误经过排查是由 #396 引入的,后续需要解决。

DingliZhang commented 2 years ago

根据 @zifeihan 的分析,在pr 393的时候 虽然都是bad ad file的报错 ,但是make 和make images报错的node节点不同。可能在make images还有报错的节点也需要修改: image

分析报错信息,可以看到URShiftI是需要一个IREGIORL2I节点来匹配的,也就是castP2X需要在DFA中将IREGIORL2I设置为VALID,而在 https://github.com/openjdk-riscv/jdk11u/pull/396 中已经将castP2X的参数修改过了。我们可以回退到PR #393 的节点,只修改castP2X的参数,编译后可以看到: image 上图这里的castP2X已经拥有了IREGIORL2I节点,而报错信息对应了PR #396 中对R29的修改:

image

可以添加打印日志来查看是否修复了URShiftI的问题: 9K913K6{5@49D%FUF3(X562 可以看到URShiftI相关的报错已经修复了。

shining1984 commented 2 years ago

PR396共有两个修改,一个是castP2X参数由iRegLNoSp变为iRegINoSp的修改,一个是R29相关的修改。这两个修改都解决各自的问题。当这两个修改分开提交的时候,正常解决各自的问题,没有异常。但是当着两个修改同时提交之后,make images编译出来的结果,就会导致出现“Error occurred during initialization of boot layer”的错误。

zifeihan commented 2 years ago

当前通过make images编译出的可执行文件,在执行过程中存在如下报错:

Error occurred during initialization of boot layer
java.lang.module.FindException: Error reading module: /home/zifeihan/jdk11u/build/linux-riscv32-normal-custom-slowdebug/jdk/modules/jdk.naming.rmi
Caused by: java.lang.module.InvalidModuleDescriptorException: Package com.sun.jndi.rmi.registry missing from ModulePackages class file attribute

接下来通过添加打印日志,辅助排查该问题如:

diff --git a/src/java.base/share/classes/jdk/internal/module/ModuleInfo.java b/src/java.base/share/classes/jdk/internal/module/ModuleInfo.java
index 33e5b33f96..744fae0fba 100644
--- a/src/java.base/share/classes/jdk/internal/module/ModuleInfo.java
+++ b/src/java.base/share/classes/jdk/internal/module/ModuleInfo.java
@@ -310,7 +310,16 @@ public final class ModuleInfo {
         }
         if (allPackages != null) {
             Set<String> knownPackages = JLMA.packages(builder);
+            System.out.println("-------------");
+            System.out.println(allPackages);
+            System.out.println(knownPackages);
+            System.out.println("-------------");
             if (!allPackages.containsAll(knownPackages)) {
+
+                System.out.println("+++++++++++++");
+                System.out.println(allPackages);
+                System.out.println(knownPackages);
+                System.out.println("+++++++++++++");
                 Set<String> missingPackages = new HashSet<>(knownPackages);
                 missingPackages.removeAll(allPackages);
                 assert !missingPackages.isEmpty();

可以看到这里的 if (!allPackages.containsAll(knownPackages)) { 判断条件成立了,导致进入了报错的节点。但实际上通过打印出来的数据,自己写一个方法进行测试,也不会进入类似报错的节点。这里的Set 数据结构也很奇怪,按理来说Set不能有重复的元素,但是这里通过日志打印出来了。通过 if (!allPackages.containsAll(knownPackages)) { 本应该不成立的判断条件也说明了Set这个数据结构中的判断有问题。

image image

通过查看jit的编译日志,通过如下参数:/home/zifeihan/qemu32/bin/qemu-riscv32 -L /opt/riscv32/sysroot ./java -XX:+LogCompilation -XX:LogFile=compile.log 查看编译的java方法的日志。 日志如下:

<task_queued compile_id='16' method='java.lang.StringLatin1 replace ([BCC)Ljava/lang/String;' bytes='196' count='309' backedge_count='5000' iicount='309' stamp='2.895' comment='count' hot_count='309'/>
<task_queued compile_id='17' method='java.lang.StringLatin1 indexOf ([BII)I' bytes='61' count='1081' backedge_count='5000' iicount='1081' stamp='2.899' comment='count' hot_count='1081'/>
<task_queued compile_id='18' method='java.io.DataInputStream readUTF (Ljava/io/DataInput;)Ljava/lang/String;' bytes='501' count='414' backedge_count='5000' iicount='414' stamp='2.921' comment='count' hot_count='414'/>
<task_queued compile_id='19' method='java.lang.StringUTF16 compress ([CI[BII)I' bytes='50' count='414' backedge_count='5000' iicount='414' stamp='2.922' comment='count' hot_count='414'/>
<task_queued compile_id='20' method='jdk.internal.module.ModuleInfo$ConstantPool checkUnqualifiedName (Ljava/lang/String;ILjava/lang/String;)V' bytes='131' count='358' backedge_count='5000' iicount='358' stamp='2.941' comment='count' hot_count='358'/>
<task_queued compile_id='21' method='java.lang.StringLatin1 inflate ([BI[CII)V' bytes='34' count='127' backedge_count='5000' iicount='127' stamp='2.951' comment='count' hot_count='127'/>
<task_queued compile_id='22' method='sun.nio.cs.UTF_8$Encoder encodeArrayLoop (Ljava/nio/CharBuffer;Ljava/nio/ByteBuffer;)Ljava/nio/charset/CoderResult;' bytes='489' count='117' backedge_count='5000' iicount='117' stamp='2.952' comment='count' hot_count='117'/>
<task_queued compile_id='23' method='java.lang.Object &lt;init&gt; ()V' bytes='1' count='5000' backedge_count='1' iicount='10000' stamp='3.035' comment='count' hot_count='10000'/>
<

我们在启动过程中通过屏蔽某个方法的jit编译,来查看是否是该方法导致了当前问题的发生,通过类似如下参数:/home/zifeihan/qemu32/bin/qemu-riscv32 -L /opt/riscv32/sysroot ./java -XX:CompileCommand=exclude,"java/lang/StringLatin1.replace" -XX:+LogCompilation -XX:LogFile=compile.log当屏蔽到java.lang.StringLatin1 indexOf方法时,发现原本报错的数据正常了。因此推测Set数据结构在添加或者判断数据时,可能调用到了java.lang.StringLatin1 indexOf方法,目前需要通过对java.lang.StringLatin1 indexOf方法生成的jit代码调试,排查问题发生的具体位置。

image image
axiangyushanhaijing commented 2 years ago

基于 comment 的分析,观察了此时的报错

# To suppress the following error report, specify this argument
# after -XX: or in .hotspotrc:  SuppressErrorAt=/icBuffer_riscv32.cpp:65
#
# A fatal error has been detected by the Java Runtime Environment:
#
#  Internal Error (/home/zhangxiang/rv32/jdk11u/src/hotspot/cpu/riscv32/icBuffer_riscv32.cpp:65), pid=754419, tid=754421
#  assert(masm-> pc() - start == ic_stub_code_size()) failed: must be
#
# JRE version: OpenJDK Runtime Environment (11.0.9) (slowdebug build 11.0.9-internal+0-adhoc.zhangxiang.jdk11u)
# Java VM: OpenJDK Server VM (slowdebug 11.0.9-internal+0-adhoc.zhangxiang.jdk11u, mixed mode, serial gc, linux-riscv32)
# No core dump will be written. Core dumps have been disabled. To enable core dumping, try "ulimit -c unlimited" before starting Java again
#
# An error report file with more information is saved as:
# /home/zhangxiang/rv32/jdk11u/build/linux-riscv32-normal-custom-slowdebug/jdk/bin/hs_err_pid754419.log
#
# If you would like to submit a bug report, please visit:
#   https://bugreport.java.com/bugreport/crash.jsp
#
Current thread is 754421
Dumping core ...
Aborted

再看报错处函数


void InlineCacheBuffer::assemble_ic_buffer_code(address code_begin, void* cached_value, address entry_point) {
  assert_cond(code_begin != NULL && entry_point != NULL);
  ResourceMark rm;
  CodeBuffer      code(code_begin, ic_stub_code_size());
  MacroAssembler* masm            = new MacroAssembler(&code);
  // note: even though the code contains an embedded value, we do not need reloc info
  // because
  // (1) the value is old (i.e., doesn't matter for scavenges)
  // (2) these ICStubs are removed *before* a GC happens, so the roots disappear

  address start = __ pc();
  Label l;
  __ lw(t1, l);
  __ far_jump(ExternalAddress(entry_point));
  __ align(wordSize);
  __ bind(l);
  __ emit_int32((intptr_t)cached_value);
  // Only need to invalidate the 1st two instructions - not the whole ic stub
  ICache::invalidate_range(code_begin, InlineCacheBuffer::ic_stub_code_size());
  int temp=__ pc() - start;
  assert(__ pc() - start == ic_stub_code_size(), "must be");
}

对ic_stub_code_size()阅读发现,


int InlineCacheBuffer::ic_stub_code_size() {
  // 6: auipc + lw + auipc + jalr + address(2 * instruction_size)
  // 5: auipc + lw + j + address(2 * instruction_size )
  return (MacroAssembler::far_branches() ? 6 : 5) * NativeInstruction::instruction_size;
}

其中address(2 * instruction_size)在rv64中,地址长度为8字节,由于instruction_size值为4,所以需要×2.而在rv32中,不需要再x2,那么相应的返回值的6-->5,5-->4.

int InlineCacheBuffer::ic_stub_code_size() {
  // 5: auipc + lw + auipc + jalr + address(1 * instruction_size)
  // 4: auipc + lw + j + address(1 * instruction_size )
  return (MacroAssembler::far_branches() ? 5 : 4) * NativeInstruction::instruction_size;
}

修改后的 qemu32 ./java-bak -version image

qemu32 ./java-bak -XX:CompileCommand=exclude,"java/lang/StringLatin1.replace" -version make

# To suppress the following error report, specify this argument
# after -XX: or in .hotspotrc:  SuppressErrorAt=/oopMap.cpp:547
#
# A fatal error has been detected by the Java Runtime Environment:
#
#  Internal Error (/home/zhangxiang/rv32/jdk11u/src/hotspot/share/compiler/oopMap.cpp:547), pid=1379443, tid=1379445
#  assert(last->pc_offset() == pc_offset) failed: oopmap not found
#
# JRE version: OpenJDK Runtime Environment (11.0.9) (slowdebug build 11.0.9-internal+0-adhoc.zhangxiang.jdk11u)
# Java VM: OpenJDK Server VM (slowdebug 11.0.9-internal+0-adhoc.zhangxiang.jdk11u, mixed mode, serial gc, linux-riscv32)
# No core dump will be written. Core dumps have been disabled. To enable core dumping, try "ulimit -c unlimited" before starting Java again
#
# An error report file with more information is saved as:
# /home/zhangxiang/rv32/jdk11u/build/linux-riscv32-normal-custom-slowdebug/jdk/bin/hs_err_pid1379443.log
#
# If you would like to submit a bug report, please visit:
#   https://bugreport.java.com/bugreport/crash.jsp
#
Current thread is 1379445
Dumping core ...
Aborted

make images

Error occurred during initialization of boot layer
java.lang.module.FindException: Error reading module: /home/zhangxiang/rv32/jdk11u/build/linux-riscv32-normal-custom-slowdebug/jdk/modules/java.compiler
Caused by: java.lang.module.InvalidModuleDescriptorException: Module attribute not found

且此时make images与make的结果不一致。

基于 qemu32 ./java-bak -XX:+LogCompilation -XX:LogFile=compile.log -version 查看log后发现

<nmethod compile_id='11' compiler='c2' entry='0x3b960d40' size='1320' address='0x3b960c08' relocation_offset='240' insts_offset='312' stub_offset='824' scopes_data_offset='880' scopes_pcs_offset='984' dependencies_offset='1304' nul_chk_table_offset='1308' metadata_offset='876' method='java.lang.StringLatin1 hashCode ([B)I' bytes='42' count='582' backedge_count='8556' iicount='582' stamp='2.798'/>
<nmethod compile_id='12' compiler='c2' entry='0x3b960980' size='904' address='0x3b960848' relocation_offset='240' insts_offset='312' stub_offset='504' scopes_data_offset='584' scopes_pcs_offset='680' dependencies_offset='888' nul_chk_table_offset='892' metadata_offset='572' method='java.lang.String charAt (I)C' bytes='25' count='7278' backedge_count='1' iicount='17277' stamp='2.831'/>
<nmethod compile_id='13' compiler='c2' entry='0x3b9606c0' size='676' address='0x3b960588' relocation_offset='240' insts_offset='312' stub_offset='440' scopes_data_offset='496' scopes_pcs_offset='532' dependencies_offset='660' nul_chk_table_offset='664' metadata_offset='492' method='java.lang.StringLatin1 charAt ([BI)C' bytes='28' count='7278' backedge_count='1' iicount='17277' stamp='2.843'/>
<writer thread='773840'/>
<task_queued compile_id='16' method='java.lang.StringLatin1 replace ([BCC)Ljava/lang/String;' bytes='196' count='308' backedge_count='5000' iicount='308' stamp='2.857' comment='count' hot_count='308'/>
<task_queued compile_id='17' method='java.lang.StringLatin1 indexOf ([BII)I' bytes='61' count='1144' backedge_count='5000' iicount='1144' stamp='2.861' comment='count' hot_count='1144'/>
<task_queued compile_id='18' method='java.io.DataInputStream readUTF (Ljava/io/DataInput;)Ljava/lang/String;' bytes='501' count='414' backedge_count='5000' iicount='414' stamp='2.884' comment='count' hot_count='414'/>
<task_queued compile_id='19' method='java.lang.StringUTF16 compress ([CI[BII)I' bytes='50' count='414' backedge_count='5000' iicount='414' stamp='2.884' comment='count' hot_count='414'/>
<task_queued compile_id='20' method='jdk.internal.module.ModuleInfo$ConstantPool checkUnqualifiedName (Ljava/lang/String;ILjava/lang/String;)V' bytes='131' count='358' backedge_count='5000' iicount='358' stamp='2.903' comment='count' hot_count='358'/>
<task_queued compile_id='21' method='java.lang.StringLatin1 inflate ([BI[CII)V' bytes='34' count='127' backedge_count='5000' iicount='127' stamp='2.915' comment='count' hot_count='127'/>
<task_queued compile_id='22' method='sun.nio.cs.UTF_8$Encoder encodeArrayLoop (Ljava/nio/CharBuffer;Ljava/nio/ByteBuffer;)Ljava/nio/charset/CoderResult;' bytes='489' count='117' backedge_count='5000' iicount='117' stamp='2.915' comment='count' hot_count='117'/>
<task_queued compile_id='23' method='java.lang.Object &lt;init&gt; ()V' bytes='1' count='5000' backedge_count='1' iicount='10000' stamp='3.004' comment='count' hot_count='10000'/>
<writer thread='773855'/>

comment 中的log一致。

DingliZhang commented 2 years ago

make

da0122 的基础上,观察 https://github.com/openjdk-riscv/jdk11u/issues/388#issuecomment-1157460071 的报错,报错位于: https://github.com/openjdk-riscv/jdk11u/blob/da01225aa369883c93bffaab75ab17fba5de604f/src/hotspot/cpu/riscv32/abstractInterpreter_riscv32.cpp#L150-L159 观察ARM的逻辑: image 发现32位和64位的逻辑是不同的,在rv32与rv64的处理也可能是不一样的,明显的一点是 intptr_t* locals 中的 intptr_t 在rv32和rv64中的长度不同分别是4和8(intptr_t总是与地址的字节数相同)。参照ARM将locals的赋值判断更改为只有 interpreter_frame->sender_sp() + max_locals ,同时加上https://github.com/openjdk-riscv/jdk11u/issues/388#issuecomment-1160522308 中的改动,patch为:

diff --git a/src/hotspot/cpu/riscv32/abstractInterpreter_riscv32.cpp b/src/hotspot/cpu/riscv32/abstractInterpreter_riscv32.cpp
index b8a408a592..a2470c9a97 100644
--- a/src/hotspot/cpu/riscv32/abstractInterpreter_riscv32.cpp
+++ b/src/hotspot/cpu/riscv32/abstractInterpreter_riscv32.cpp
@@ -147,17 +147,7 @@ void AbstractInterpreter::layout_activation(Method* method,
   // expression stack. For other types of caller frame it doesn't
   // matter.
   intptr_t* locals = NULL;
-  if (caller->is_interpreted_frame()) {
-    locals = caller->interpreter_frame_last_sp() + caller_actual_parameters - 1;
-  } else {
     locals = interpreter_frame->sender_sp() + max_locals - 1;
-  }
-
-#ifdef ASSERT
-  if (caller->is_interpreted_frame()) {
-    assert(locals < caller->fp() + frame::interpreter_frame_initial_sp_offset, "bad placement");
-  }
-#endif

   interpreter_frame->interpreter_frame_set_locals(locals);
   BasicObjectLock* montop = interpreter_frame->interpreter_frame_monitor_begin();
diff --git a/src/hotspot/cpu/riscv32/icBuffer_riscv32.cpp b/src/hotspot/cpu/riscv32/icBuffer_riscv32.cpp
index b571e97812..0966fed0a3 100644
--- a/src/hotspot/cpu/riscv32/icBuffer_riscv32.cpp
+++ b/src/hotspot/cpu/riscv32/icBuffer_riscv32.cpp
@@ -37,7 +37,7 @@
 int InlineCacheBuffer::ic_stub_code_size() {
   // 6: auipc + lw + auipc + jalr + address(2 * instruction_size)
   // 5: auipc + lw + j + address(2 * instruction_size )
-  return (MacroAssembler::far_branches() ? 6 : 5) * NativeInstruction::instruction_size;
+  return (MacroAssembler::far_branches() ? 5 : 4) * NativeInstruction::instruction_size;
 }

 #define __ masm->
diff --git a/src/hotspot/cpu/riscv32/riscv32.ad b/src/hotspot/cpu/riscv32/riscv32.ad
index b9f4e08981..0d6f5ebfa3 100644
--- a/src/hotspot/cpu/riscv32/riscv32.ad
+++ b/src/hotspot/cpu/riscv32/riscv32.ad
@@ -872,7 +872,7 @@ int MachCallRuntimeNode::ret_addr_offset() {
   if (cb != NULL) {
     return MacroAssembler::far_branch_size();
   } else {
-    return 12 * NativeInstruction::instruction_size;
+    return 8 * NativeInstruction::instruction_size;
   }
 }

输出信息为:

$ qemu32 build/linux-riscv32-normal-custom-slowdebug/jdk/bin/java -version
#
# A fatal error has been detected by the Java Runtime Environment:
#
#  SIGSEGV (0xb) at pc=0x3f1a6dd4, pid=2220290, tid=2220292
#
# JRE version: OpenJDK Runtime Environment (11.0.9) (slowdebug build 11.0.9-internal+0-adhoc.dingli.jdk11u-jit)
# Java VM: OpenJDK Server VM (slowdebug 11.0.9-internal+0-adhoc.dingli.jdk11u-jit, mixed mode, serial gc, linux-riscv32)
# Problematic frame:
# V  [libjvm.so+0x45cdd4]  frame::interpreter_frame_method() const+0x86
#
# No core dump will be written. Core dumps have been disabled. To enable core dumping, try "ulimit -c unlimited" before starting Java again
#
# An error report file with more information is saved as:
# /home/dingli/jdk11u-jit/hs_err_pid2220290.log
#
# If you would like to submit a bug report, please visit:
#   https://bugreport.java.com/bugreport/crash.jsp
#
Current thread is 2220292
Dumping core ...
Aborted

make images

在打上上述make中的patch的情况下执行 make images,输出如下:

$ qemu32 build/linux-riscv32-normal-custom-slowdebug/jdk/bin/java -version
Error occurred during initialization of boot layer
java.lang.module.FindException: Error reading module: /home/dingli/jdk11u-jit/build/linux-riscv32-normal-custom-slowdebug/jdk/modules/jdk.management
Caused by: java.lang.module.InvalidModuleDescriptorException: Package com.sun.management.internal missing from ModulePackages class file attribute

参照 https://github.com/openjdk-riscv/jdk11u/issues/388#issuecomment-1160359846 重中的方法执行:

$ qemu32 build/linux-riscv32-normal-custom-slowdebug/jdk/bin/java -XX:CompileCommand=exclude,"java.lang.StringLatin1::replace" -XX:+LogCompilation -XX:LogFile=compile.log -version

查看compile.log中的方法:

<task compile_id='18' method='jdk.internal.module.ModuleInfo$ConstantPool checkUnqualifiedName (Ljava/lang/String;ILjava/lang/String;)V' bytes='131' count='5000' backedge_count='5000' iicount='786' stamp='3.233'>
<task compile_id='9' method='java.lang.String isLatin1 ()Z' bytes='19' count='5025' backedge_count='1' iicount='10025' stamp='2.616'>
<task compile_id='11' method='java.lang.StringLatin1 hashCode ([B)I' bytes='42' count='453' backedge_count='5035' iicount='453' stamp='2.739'>
<task compile_id='12' method='java.lang.String charAt (I)C' bytes='25' count='6271' backedge_count='1' iicount='16270' stamp='2.869'>
<task compile_id='13' method='java.lang.StringLatin1 charAt ([BI)C' bytes='28' count='8874' backedge_count='1' iicount='18873' stamp='2.903'>
<task compile_id='16' method='java.io.DataInputStream readUTF (Ljava/io/DataInput;)Ljava/lang/String;' bytes='501' count='414' backedge_count='5017' iicount='414' stamp='2.926'>
<task compile_id='17' method='java.lang.StringUTF16 compress ([CI[BII)I' bytes='50' count='5000' backedge_count='5006' iicount='934' stamp='3.233'>

分别屏蔽上述几个方法,发现当前的报错是由 java.io.DataInputStream::readUTF 引起的,将这个方法加入到屏蔽的行列之中:

$ qemu32 build/linux-riscv32-normal-custom-slowdebug/jdk/bin/java -XX:CompileCommand=exclude,"java.lang.StringLatin1::replace" -XX:CompileCommand=exclude,"java.io.DataInputStream::readUTF" -version
CompileCommand: exclude java/lang/StringLatin1.replace
CompileCommand: exclude java/io/DataInputStream.readUTF
#
# A fatal error has been detected by the Java Runtime Environment:
#
#  SIGSEGV (0xb) at pc=0x3b874230, pid=2389683, tid=2389685
#
# JRE version: OpenJDK Runtime Environment (11.0.9) (slowdebug build 11.0.9-internal+0-adhoc.dingli.jdk11u-jit)
# Java VM: OpenJDK Server VM (slowdebug 11.0.9-internal+0-adhoc.dingli.jdk11u-jit, mixed mode, serial gc, linux-riscv32)
# Problematic frame:
# 
[error occurred during error reporting (printing problematic frame), id 0xb, SIGSEGV (0xb) at pc=0x3f1a6dc6]

# No core dump will be written. Core dumps have been disabled. To enable core dumping, try "ulimit -c unlimited" before starting Java again
#
# An error report file with more information is saved as:
# /home/dingli/jdk11u-jit/hs_err_pid2389683.log
Could not load hsdis-riscv32.so; library not loadable; PrintAssembly is disabled
#
# If you would like to submit a bug report, please visit:
#   https://bugreport.java.com/bugreport/crash.jsp
#
Current thread is 2389685
Dumping core ...
Aborted

如果把patch中的这一部分删除:

diff --git a/src/hotspot/cpu/riscv32/abstractInterpreter_riscv32.cpp b/src/hotspot/cpu/riscv32/abstractInterpreter_riscv32.cpp
index b8a408a592..a2470c9a97 100644
--- a/src/hotspot/cpu/riscv32/abstractInterpreter_riscv32.cpp
+++ b/src/hotspot/cpu/riscv32/abstractInterpreter_riscv32.cpp
@@ -147,17 +147,7 @@ void AbstractInterpreter::layout_activation(Method* method,
   // expression stack. For other types of caller frame it doesn't
   // matter.
   intptr_t* locals = NULL;
-  if (caller->is_interpreted_frame()) {
-    locals = caller->interpreter_frame_last_sp() + caller_actual_parameters - 1;
-  } else {
     locals = interpreter_frame->sender_sp() + max_locals - 1;
-  }
-
-#ifdef ASSERT
-  if (caller->is_interpreted_frame()) {
-    assert(locals < caller->fp() + frame::interpreter_frame_initial_sp_offset, "bad placement");
-  }
-#endif

那么输出结果为:

$ qemu32 build/linux-riscv32-normal-custom-slowdebug/jdk/bin/java -XX:CompileCommand=exclude,"java.lang.StringLatin1::replace" -XX:CompileCommand=exclude,"java.io.DataInputStream::readUTF" -version
CompileCommand: exclude java/lang/StringLatin1.replace
CompileCommand: exclude java/io/DataInputStream.readUTF
#
# A fatal error has been detected by the Java Runtime Environment:
#
#  SIGSEGV (0xb) at pc=0x3ee20fa0, pid=2366721, tid=2366723
#
# JRE version: OpenJDK Runtime Environment (11.0.9) (slowdebug build 11.0.9-internal+0-adhoc.dingli.jdk11u-jit)
# Java VM: OpenJDK Server VM (slowdebug 11.0.9-internal+0-adhoc.dingli.jdk11u-jit, mixed mode, serial gc, linux-riscv32)
# Problematic frame:
# V  [libjvm.so+0xd6fa0]  frame::interpreter_frame_last_sp() const+0x16
#
# No core dump will be written. Core dumps have been disabled. To enable core dumping, try "ulimit -c unlimited" before starting Java again
#
# An error report file with more information is saved as:
# /home/dingli/jdk11u-jit/hs_err_pid2366721.log
#
# If you would like to submit a bug report, please visit:
#   https://bugreport.java.com/bugreport/crash.jsp
#
Current thread is 2366723
Dumping core ...
Aborted

可以看到报错都是 frame::interpreter_frameXX,接下来准备研究相关的逻辑。

shining1984 commented 2 years ago

make images的Error occurred during initialization of boot layer 问题分析(以slowdebug模式为例): 1、make images执行是先执行了make,生成了build/linux-riscv32-normal-custom-slowdebug/jdk目录,然后再执行images相关内容,生成build/linux-riscv32-normal-custom-slowdebug/images目录; 2、make和make jdk是同样的效果; 3、build/linux-riscv32-normal-custom-slowdebug/images/jdk目录的内容是可以拿到别的地方直接运行的,但是build/linux-riscv32-normal-custom-slowdebug/jdk目录的不行; 4、build/linux-riscv32-normal-custom-slowdebug/images目录的下的java -version可以直接运行,不会遇到错误; 5、这个问题只有slowdebug和fastdebug才会产生,release模式下不会产生该问题,release模式下可以得到和make相同的运行结果。

其他可能:有可能本身构建images的问题,参见:https://bugs.openjdk.org/browse/JDK-8216489

DingliZhang commented 2 years ago

make images的Error occurred during initialization of boot layer 问题分析(以slowdebug模式为例): 1、make images执行是先执行了make,生成了build/linux-riscv32-normal-custom-slowdebug/jdk目录,然后再执行images相关内容,生成build/linux-riscv32-normal-custom-slowdebug/images目录; 2、make和make jdk是同样的效果; 3、build/linux-riscv32-normal-custom-slowdebug/images/jdk目录的内容是可以拿到别的地方直接运行的,但是build/linux-riscv32-normal-custom-slowdebug/jdk目录的不行; 4、build/linux-riscv32-normal-custom-slowdebug/images目录的下的java -version可以直接运行,不会遇到错误; 5、这个问题只有slowdebug和fastdebug才会产生,release模式下不会产生该问题,release模式下可以得到和make相同的运行结果。

其他可能:有可能本身构建images的问题,参见:https://bugs.openjdk.org/browse/JDK-8216489

zifeihan commented 2 years ago

目前C2 make出现如下报错:

zifeihan@k9-plct:~/jdk11u/build/linux-riscv32-normal-custom-slowdebug/jdk/bin$ /home/zifeihan/qemu32/bin/qemu-riscv32 -L /opt/riscv32/sysroot ./java   -XX:+LogCompilation -XX:LogFile=compile.logWarning:  TraceDependencies results may be inflated by VerifyDependencies
OpenJDK Server VM warning: hello
# To suppress the following error report, specify this argument
# after -XX: or in .hotspotrc:  SuppressErrorAt=/abstractInterpreter_riscv32.cpp:166
#
# A fatal error has been detected by the Java Runtime Environment:
#
#  Internal Error (/home/zifeihan/jdk11u/src/hotspot/cpu/riscv32/abstractInterpreter_riscv32.cpp:166), pid=2671342, tid=2671347
#  assert(locals < caller->fp() + frame::interpreter_frame_initial_sp_offset) failed: bad placement
#
# JRE version: OpenJDK Runtime Environment (11.0.9) (slowdebug build 11.0.9-internal+0-adhoc.zifeihan.jdk11u)
# Java VM: OpenJDK Server VM (slowdebug 11.0.9-internal+0-adhoc.zifeihan.jdk11u, mixed mode, serial gc, linux-riscv32)
# No core dump will be written. Core dumps have been disabled. To enable core dumping, try "ulimit -c unlimited" before starting Java again
#
# An error report file with more information is saved as:
# /home/zifeihan/jdk11u/build/linux-riscv32-normal-custom-slowdebug/jdk/bin/hs_err_pid2671342.log
#
# If you would like to submit a bug report, please visit:
#   https://bugreport.java.com/bugreport/crash.jsp
#
Current thread is 2671347
Dumping core ...
Aborted

通过打上如下patch (含有部分的打印日志),原本报错的断言会正常通过 ,而且通过调试日志可以看出 ,此时的locals , ccccc 的数据也正常了 , 数据差为4字节。主要修改 __ add(sp, sp, (SimpleRuntimeFrame::framesize) << 1); 因为在bishengJDK下,SP 需要16字节对其,但是32位下目前都是按照8字节对其的。

diff --git a/src/hotspot/cpu/riscv32/abstractInterpreter_riscv32.cpp b/src/hotspot/cpu/riscv32/abstractInterpreter_riscv32.cpp
index b8a408a592..9e45e515fe 100644
--- a/src/hotspot/cpu/riscv32/abstractInterpreter_riscv32.cpp
+++ b/src/hotspot/cpu/riscv32/abstractInterpreter_riscv32.cpp
@@ -153,8 +153,16 @@ void AbstractInterpreter::layout_activation(Method* method,
     locals = interpreter_frame->sender_sp() + max_locals - 1;
   }

+char* aaaaaa = method->name_and_sig_as_C_string();
+char* ddd = "sun.nio.fs.UnixPath.hasDotOrDotDot()Z";
+intptr_t* ccccc = caller->fp() + frame::interpreter_frame_initial_sp_offset;
+
 #ifdef ASSERT
   if (caller->is_interpreted_frame()) {
+    if (strcmp(aaaaaa, ddd) == 0)
+    {
+      warning("hello");
+    }
     assert(locals < caller->fp() + frame::interpreter_frame_initial_sp_offset, "bad placement");
   }
 #endif
diff --git a/src/hotspot/cpu/riscv32/sharedRuntime_riscv32.cpp b/src/hotspot/cpu/riscv32/sharedRuntime_riscv32.cpp
index 841151126f..89bac2b671 100644
--- a/src/hotspot/cpu/riscv32/sharedRuntime_riscv32.cpp
+++ b/src/hotspot/cpu/riscv32/sharedRuntime_riscv32.cpp
@@ -2491,7 +2491,7 @@ void SharedRuntime::generate_uncommon_trap_blob() {
   // 2: deopting frame  (no frame link)
   // 3: caller of deopting frame (could be compiled/interpreted).

-  __ add(sp, sp, (SimpleRuntimeFrame::framesize) << LogBytesPerInt); // Epilog!
+  __ add(sp, sp, (SimpleRuntimeFrame::framesize) << 1); // Epilog!

   // Pop deoptimized frame (int)
   __ lw(x12, Address(x14,
image

patch打上后的报错如下,通过调试,发现确实是往下推进了。

image

在修复前,可以看到locals , ccccc的数据差很大,并且所在的数据段也和caller的数据段相差很大。

image

通过对bishengJDK的调试,发现locals , ccccc的数据差为8字节。

image
shining1984 commented 2 years ago

在上述的修改基础上,执行make,当前的错误提示: Error occurred during initialization of boot layer java.lang.module.FindException: Error reading module: /home/shining/jdk11u/build/linux-riscv32-normal-custom-slowdebug/jdk/modules/jdk.scripting.nashorn Caused by: java.lang.module.InvalidModuleDescriptorException: Package jdk.nashorn.api.scripting not found in module 其中Package jdk.nashorn.api.scripting是存在的。这里找不到是有问题的。根据网络查询资料,可以将/home/shining/jdk11u/build/linux-riscv32-normal-custom-slowdebug/jdk/modules/jdk.scripting.nashorn目录下的module-info.class删除掉,就可以找到Package jdk.nashorn.api.scripting。

之后,会遇到错误: Error occurred during initialization of boot layer java.lang.module.FindException: Error reading module: /home/shining/jdk11u/build/linux-riscv32-normal-custom-slowdebug/jdk/modules/java.net.http Caused by: java.lang.module.InvalidModuleDescriptorException: Package java.net.http not found in modul

同样,删除/home/shining/jdk11u/build/linux-riscv32-normal-custom-slowdebug/jdk/modules/java.net.http目录下的module-info.class也可以解决该问题。

最后,会遇到问题: image

zifeihan commented 2 years ago

最后,会遇到问题: image

在执行时加上 -XX:CompileCommand=exclude,java/lang/StringLatin1.* 参数,屏蔽 StringLatin1 类被JIT编译后,也会出现同样的报错:

image
zifeihan commented 2 years ago

可以使用如下命令,/home/zifeihan/qemu32/bin/qemu-riscv32 -L /opt/riscv32/sysroot ./java -XX:CompileCommand=exclude,"java/lang/StringLatin1.*" -XX:CompileCommand=exclude,"java/lang/String.*" -XX:+LogCompilation -XX:LogFile=compile.log 将类java/lang/StringLatin1 , java/lang/String 屏蔽JIT编译,会继续向前推进一步:

image
axiangyushanhaijing commented 2 years ago

通过脚本重复执行“./java -version”命令,将生成log总结到一起发现:

Error occurred during initialization of boot layer
java.lang.module.FindException: Error reading module: /home/zhangxiang/rv32/jdk11u/build/linux-riscv32-normal-custom-slowdebug/jdk/modules/jdk.scripting.nashorn
Caused by: java.lang.module.InvalidModuleDescriptorException: Package jdk.nashorn.api.scripting not found in module

以及

Dumping core ...
# To suppress the following error report, specify this argument
# after -XX: or in .hotspotrc:  SuppressErrorAt=/iterator.inline.hpp:60
#
# A fatal error has been detected by the Java Runtime Environment:
#
#  Internal Error (/home/zhangxiang/rv32/jdk11u/src/hotspot/share/memory/iterator.inline.hpp:60), pid=1246259, tid=1246294
#  assert(Universe::heap()->is_in_closed_subset(o)) failed: should be in closed *p 0x2e64ab64 0xbaadbabe
#
# JRE version: OpenJDK Runtime Environment (11.0.9) (slowdebug build 11.0.9-internal+0-adhoc.zhangxiang.jdk11u)
# Java VM: OpenJDK Server VM (slowdebug 11.0.9-internal+0-adhoc.zhangxiang.jdk11u, mixed mode, serial gc, linux-riscv32)
# No core dump will be written. Core dumps have been disabled. To enable core dumping, try "ulimit -c unlimited" before starting Java again
#
# An error report file with more information is saved as:
# /home/zhangxiang/rv32/jdk11u/hs_err_pid1246259.log
#
# If you would like to submit a bug report, please visit:
#   https://bugreport.java.com/bugreport/crash.jsp
#

两种报错都会产生。所以目前的报错结果不稳定。

DingliZhang commented 2 years ago

https://github.com/openjdk-riscv/jdk11u/commit/5f22cb8c12a3bb4ff5c6ea40fc65fdfe0eae3ac2 的基础上,同时加上以下两个patch: https://github.com/openjdk-riscv/jdk11u/issues/388#issuecomment-1166691134 https://github.com/openjdk-riscv/jdk11u/issues/388#issuecomment-1160522308

执行100次下列命令:

/home/dingli/qemu-5.2.0-rv32/bin/qemu-riscv32 -L /opt/riscv32/sysroot /home/dingli/jdk11u-jit/build/linux-riscv32-normal-custom-slowdebug/jdk/bin/java -XX:CompileCommand=exclude,"java/lang/StringLatin1.*" -XX:CompileCommand=exclude,"java/lang/String.*" -XX:+LogCompilation -XX:LogFile=compile.log >> log_100.log 2>&1

会出现两种情况:

CompileCommand: exclude java/lang/StringLatin1.*
CompileCommand: exclude java/lang/String.*
Warning:  TraceDependencies results may be inflated by VerifyDependencies
#
# A fatal error has been detected by the Java Runtime Environment:
#
#  SIGSEGV (0xb) at pc=0x3b893a1c, pid=881672, tid=881678
#
# JRE version: OpenJDK Runtime Environment (11.0.9) (slowdebug build 11.0.9-internal+0-adhoc.dingli.jdk11u-jit)
# Java VM: OpenJDK Server VM (slowdebug 11.0.9-internal+0-adhoc.dingli.jdk11u-jit, mixed mode, serial gc, linux-riscv32)
# Problematic frame:
# j  jdk.internal.module.ModulePath.toPackageName(Ljava/nio/file/Path;)Ljava/util/Optional;+44 java.base
#
# No core dump will be written. Core dumps have been disabled. To enable core dumping, try "ulimit -c unlimited" before starting Java again
#
# An error report file with more information is saved as:
# /home/dingli/jdk11u-jit/hs_err_pid881672.log
Loaded disassembler from /home/dingli/jdk11u-jit/build/linux-riscv32-normal-custom-slowdebug/jdk/lib/server/hsdis-riscv32.so
BFD: unrecognized disassembler option: 
#
# If you would like to submit a bug report, please visit:
#   https://bugreport.java.com/bugreport/crash.jsp
#
Current thread is 881678
Dumping core ...
CompileCommand: exclude java/lang/StringLatin1.*
CompileCommand: exclude java/lang/String.*
Warning:  TraceDependencies results may be inflated by VerifyDependencies
# To suppress the following error report, specify this argument
# after -XX: or in .hotspotrc:  SuppressErrorAt=/riscv32.ad:1137
#
# A fatal error has been detected by the Java Runtime Environment:
#
#  Internal Error (/home/dingli/jdk11u-jit/src/hotspot/cpu/riscv32/riscv32.ad:1137), pid=922692, tid=926513
#  assert((src_lo & 1) == 0 && src_lo + 1 == src_hi && (dst_lo & 1) == 0 && dst_lo + 1 == dst_hi) failed: expected aligned-adjacent pairs
#
# JRE version: OpenJDK Runtime Environment (11.0.9) (slowdebug build 11.0.9-internal+0-adhoc.dingli.jdk11u-jit)
# Java VM: OpenJDK Server VM (slowdebug 11.0.9-internal+0-adhoc.dingli.jdk11u-jit, mixed mode, serial gc, linux-riscv32)
# No core dump will be written. Core dumps have been disabled. To enable core dumping, try "ulimit -c unlimited" before starting Java again
#
# An error report file with more information is saved as:
# /home/dingli/jdk11u-jit/hs_err_pid922692.log
[thread 922922 also had an error]
#
# Compiler replay data is saved as:
# /home/dingli/jdk11u-jit/replay_pid922692.log
#
# If you would like to submit a bug report, please visit:
#   https://bugreport.java.com/bugreport/crash.jsp
#
Current thread is 926513
Dumping core ...

但是在之后的多次测试中,结果都为上述第一种报错。

zifeihan commented 2 years ago

bishengJDK java.lang.StringLatin1 hashCode JIT日志,通过类似如下参数打印:/home/zifeihan/qemu64/bin/qemu-riscv64 -L /opt/riscv64/sysroot ./java -XX:-UseCompressedOops -XX:+PrintOptoAssembly -XX:+LogCompilation -XX:LogFile=compile.log

<opto_assembly compile_id='11'>
{method}
 - this oop:          0x00000047fabb0800
 - method holder:     &apos;java/lang/StringLatin1&apos;
 - constants:         0x00000047fabae8f0 constant pool [314] {0x00000047fabae8f0} for &apos;java/lang/StringLatin1&apos; cache=0x00000047fabb2d20
 - access:            0xc1000009  public static 
 - name:              &apos;hashCode&apos;
 - signature:         &apos;([B)I&apos;
 - max stack:         4
 - max locals:        6
 - size of params:    1
 - method size:       12
 - vtable index:      -2
 - i2i entry:         0x000000400b1038c0
 - adapters:          AHE@0x000000400437bfa0: 0xb0000000 i2c: 0x000000400b1c5480 c2i: 0x000000400b1c54b8 c2iUV: 0x000000400b1c5490
 - compiled entry     0x000000400b1c54b8
 - code size:         42
 - code start:        0x00000047fabb07a0
 - code end (excl):   0x00000047fabb07ca
 - method data:       0x00000047fadc3228
 - checked ex length: 0
 - linenumber start:  0x00000047fabb07ca
 - localvar length:   3
 - localvar start:    0x00000047fabb07da
#
#  int ( byte[int:&gt;=0]:exact * )
#
#r012 c_rarg1:c_rarg1   : parm 0: byte[int:&gt;=0]:exact *
# -- Old sp -- Framesize: 48 --
#r135 sp+44: in_preserve
#r134 sp+40: return address
#r133 sp+36: in_preserve
#r132 sp+32: saved fp register
#r131 sp+28: pad2, stack alignment
#r130 sp+24: pad2, stack alignment
#r129 sp+20: Fixed slot 1
#r128 sp+16: Fixed slot 0
#r139 sp+12: spill
#r138 sp+ 8: spill
#r137 sp+ 4: spill
#r136 sp+ 0: spill
#
abababab   N1: #    B1 &lt;- B15 B14 B12  Freq: 1
abababab
000   B1: # B15 B2 &lt;- BLOCK HEAD IS JUNK   Freq: 1
000     # stack bang size=48
    sd  fp, [sp, #-16]sd  lr, [sp, #-8]sub sp, sp, #48

01c     spill R11 -&gt; R7  # spill size = 64
020     lwu  R8, [R11, #16] # range, #@loadRange
024     NullCheck R11
024
024   B2: # B13 B3 &lt;- B1  Freq: 0.999999
024 +   ble  R8, zr, B13    #@cmpUEqNeLeGt_reg_imm0_branch  P=0.044228 C=6783.000000
024
028   B3: # B14 B4 &lt;- B2  Freq: 0.955771
028 +   addiw  R29, R8, #-1 #@addI_reg_imm
02c +   bgeu  R29, R8, B14  #@cmpU_branch  P=0.000001 C=-1.000000
02c
030   B4: # B9 B5 &lt;- B3  Freq: 0.95577
030 +   li R28, #-2147483648    # int, #@loadConI
034 +   addiw  R12, R8, #-7 #@addI_reg_imm
038 +   cmplt op1, op2  #@cmpI
    mv_t R12, R28   #@cmovI
040 +   li R13, #1  # int, #@loadConI
044 +   lbu  R10, [R11, #24]    # byte, #@loadUB
048 +   ble  R12, R13, B9   #@cmpI_branch  P=0.000001 C=-1.000000
048
04c   B5: # B6 &lt;- B4  Freq: 0.955769
04c +   slliw  R28, R10, (#5 &amp; 0x1f)    #@lShiftI_reg_imm
050 +   subw  R29, R28, R10 #@subI_reg_reg
054 +   li R11, #8000   # int, #@loadConI
05c +    --     // R23=Thread::current(), empty, #@tlsLoadP
05c
05c   B6: # B7 &lt;- B5 B8  Loop: B6-B8  Freq: 21.6099
05c     subw  R28, R12, R13 #@subI_reg_reg
060 +   ble R28, R11, Lsrc1.    #@minI_rReg
    mv R30, R11
    j Ldone
    bind Lsrc1
    mv R30, R28
    bind    #@minI_rReg
070 +   addw  R14, R30, R13 #@addI_reg_reg
        nop     # 3 bytes pad for loops and calls

080   B7: # B7 B8 &lt;- B6 B7   Loop: B7-B7 inner main of N58 strip mined Freq: 488.601
080 +   addw  R28, R13  #@convI2L_reg_reg
084 +   add R10, R7, R28    # ptr, #@addP_reg_reg
088 +   lbu  R28, [R10, #24]    # byte, #@loadUB
08c +   addw  R28, R29, R28 #@addI_reg_reg
090 +   lbu  R31, [R10, #25]    # byte, #@loadUB
094 +   slliw  R30, R28, (#5 &amp; 0x1f)    #@lShiftI_reg_imm
098 +   subw  R28, R30, R28 #@subI_reg_reg
09c +   addw  R28, R28, R31 #@addI_reg_reg
0a0 +   lbu  R30, [R10, #26]    # byte, #@loadUB
0a4 +   slliw  R31, R28, (#5 &amp; 0x1f)    #@lShiftI_reg_imm
0a8 +   subw  R28, R31, R28 #@subI_reg_reg
0ac +   addw  R28, R28, R30 #@addI_reg_reg
0b0 +   lbu  R31, [R10, #27]    # byte, #@loadUB
0b4 +   slliw  R29, R28, (#5 &amp; 0x1f)    #@lShiftI_reg_imm
0b8 +   subw  R29, R29, R28 #@subI_reg_reg
0bc +   addw  R28, R29, R31 #@addI_reg_reg
0c0 +   lbu  R30, [R10, #28]    # byte, #@loadUB
0c4 +   slliw  R31, R28, (#5 &amp; 0x1f)    #@lShiftI_reg_imm
0c8 +   subw  R28, R31, R28 #@subI_reg_reg
0cc +   addw  R28, R28, R30 #@addI_reg_reg
0d0 +   lbu  R31, [R10, #29]    # byte, #@loadUB
0d4 +   slliw  R30, R28, (#5 &amp; 0x1f)    #@lShiftI_reg_imm
0d8 +   subw  R28, R30, R28 #@subI_reg_reg
0dc +   addw  R28, R28, R31 #@addI_reg_reg
0e0 +   lbu  R30, [R10, #30]    # byte, #@loadUB
0e4 +   slliw  R31, R28, (#5 &amp; 0x1f)    #@lShiftI_reg_imm
0e8 +   subw  R28, R31, R28 #@subI_reg_reg
0ec +   addw  R28, R28, R30 #@addI_reg_reg
0f0 +   lbu  R31, [R10, #31]    # byte, #@loadUB
0f4 +   slliw  R30, R28, (#5 &amp; 0x1f)    #@lShiftI_reg_imm
0f8 +   subw  R28, R30, R28 #@subI_reg_reg
0fc +   addw  R10, R28, R31 #@addI_reg_reg
100 +   slliw  R29, R10, (#5 &amp; 0x1f)    #@lShiftI_reg_imm
104 +   addiw  R13, R13, #8 #@addI_reg_imm
108 +   subw  R29, R29, R10 #@subI_reg_reg
10c +   blt  R13, R14, B7   #@cmpI_loop  P=0.955772 C=6483.000000
10c
110   B8: # B6 B9 &lt;- B7  Freq: 21.6099
110 +   ld  R28, [R23, #288]    # ptr, #@loadP
114 +   lwu zr, [R28]   # Safepoint: poll for GC, #@safePoint        # java.lang.StringLatin1::hashCode @ bci:37  L[0]=_ L[1]=R10 L[2]=R7 L[3]=R8 L[4]=R13 L[5]=_
        # OopMap{x7=Oop off=276}
118 +   blt  R13, R12, B6   #@cmpI_branch  P=0.955772 C=6483.000000
118
11c   B9: # B12 B10 &lt;- B4 B8  Freq: 0.95577
11c +   bge  R13, R8, B12   #@cmpI_branch  P=0.500000 C=-1.000000
11c
120   B10: #    B11 &lt;- B9  Freq: 0.477885
120 +   # castII of R13, #@castII
120
120   B11: #    B11 B12 &lt;- B10 B11   Loop: B11-B11 inner post of N167 Freq: 0.95577
120     addw  R28, R13  #@convI2L_reg_reg
124 +   add R28, R7, R28    # ptr, #@addP_reg_reg
128 +   slliw  R30, R10, (#5 &amp; 0x1f)    #@lShiftI_reg_imm
12c +   lbu  R28, [R28, #24]    # byte, #@loadUB
130 +   subw  R29, R30, R10 #@subI_reg_reg
134 +   addiw  R13, R13, #1 #@addI_reg_imm
138 +   addw  R10, R29, R28 #@addI_reg_reg
13c +   blt  R13, R8, B11   #@cmpI_loop  P=0.500000 C=6483.000000
13c
140   B12: #    N1 &lt;- B11 B9 B13  Freq: 0.999998
140     # pop frame 48
    add  sp, sp, #48
    ld  lr, [sp,#-16]
    ld  fp, [sp,#-8]
    # touch polling page
    li  t0, #0x400b044000
    ld zr, [t0]
154 +   ret // return register, #@Ret
154
158   B13: #    B12 &lt;- B2  Freq: 0.0442282
158 +   li R10, #0  # int, #@loadConI
15c +   j  B12  #@branch
15c
160   B14: #    N1 &lt;- B3  Freq: 9.68462e-07
160 +   li R11, #-130   # int, #@loadConI
164     spill R7 -&gt; [sp, #0] # spill size = 64
168     CALL,static 0x000000400b133a40  #@CallStaticJavaDirect wrapper for: uncommon_trap(reason=&apos;predicate&apos; action=&apos;maybe_recompile&apos;)
        # java.lang.StringLatin1::hashCode @ bci:13  L[0]=_ L[1]=#0 L[2]=sp + #0 L[3]=R8 L[4]=#0 L[5]=_ STK[0]=#0 STK[1]=R8
        # OopMap{[0]=Oop off=364}
16c     #@ShouldNotReachHere
16c
170   B15: #    N1 &lt;- B1  Freq: 1.01328e-06
170 +   li R11, #-10    # int, #@loadConI
174     CALL,static 0x000000400b133a40  #@CallStaticJavaDirect wrapper for: uncommon_trap(reason=&apos;null_check&apos; action=&apos;maybe_recompile&apos;)
        # java.lang.StringLatin1::hashCode @ bci:5  L[0]=_ L[1]=_ L[2]=_ L[3]=_ L[4]=_ L[5]=_ STK[0]=#NULL
        # OopMap{off=376}
178     #@ShouldNotReachHere
178

</opto_assembly>

OpenJDK for RV32G java.lang.StringLatin1 hashCode JIT日志,通过类似如下参数打印:/home/zifeihan/qemu32/bin/qemu-riscv32 -L /opt/riscv32/sysroot ./java -XX:+PrintOptoAssembly -XX:+LogCompilation -XX:LogFile=compile.log

<opto_assembly compile_id='13'>
{method}
 - this oop:          0x2ddae070
 - method holder:     &apos;java/lang/StringLatin1&apos;
 - constants:         0x2ddacb30 constant pool [314] {0x2ddacb30} for &apos;java/lang/StringLatin1&apos; cache=0x2ddaff48
 - access:            0xc1000009  public static 
 - name:              &apos;hashCode&apos;
 - signature:         &apos;([B)I&apos;
 - max stack:         4
 - max locals:        6
 - size of params:    1
 - method size:       14
 - vtable index:      -2
 - i2i entry:         0x3b87f100
 - adapters:          AHE@0x3e9ae8a0: 0xa0000000 i2c: 0x3b92cb40 c2i: 0x3b92cb78 c2iUV: 0x3b92cb50
 - compiled entry     0x3b92cb78
 - code size:         42
 - code start:        0x2ddae010
 - code end (excl):   0x2ddae03a
 - method data:       0x2df20468
 - checked ex length: 0
 - linenumber start:  0x2ddae03a
 - localvar length:   3
 - localvar start:    0x2ddae046
#
#  int ( byte[int:&gt;=0]:exact * )
#
#r006 c_rarg1   : parm 0: byte[int:&gt;=0]:exact *
# -- Old sp -- Framesize: 32 --
#r131 sp+28: return address
#r130 sp+24: saved fp register
#r129 sp+20: pad2, stack alignment
#r128 sp+16: Fixed slot 0
#r135 sp+12: spill
#r134 sp+ 8: spill
#r133 sp+ 4: spill
#r132 sp+ 0: spill
#
abababab   N1: #    B1 &lt;- B14 B13 B11  Freq: 1
abababab
000   B1: # B14 B2 &lt;- BLOCK HEAD IS JUNK   Freq: 1
000     # stack bang size=32
    sw  fp, [sp, #-8]sw  lr, [sp, #-4]sub sp, sp, #32

020     spill R11 -&gt; R7  # spill size = 32
024     lw  R8, [R11, #8]   # range, #@loadRange
028     NullCheck R11
028
028   B2: # B12 B3 &lt;- B1  Freq: 0.999999
028 +   ble  R8, zr, B12    #@cmpUEqNeLeGt_reg_imm0_branch  P=0.042304 C=8628.000000
028
02c   B3: # B13 B4 &lt;- B2  Freq: 0.957695
02c +   addi  R28, R8, #-1  #@addI_reg_imm
030 +   bgeu  R28, R8, B13  #@cmpU_branch  P=0.000001 C=-1.000000
030
034   B4: # B8 B5 &lt;- B3  Freq: 0.957694
034 +   li R30, #-2147483648    # int, #@loadConI
03c +   addi  R11, R8, #-15 #@addI_reg_imm
040 +   cmplt op1, op2  #@cmpI
    mv_t R11, R30   #@cmovI
048 +   li R31, #1  # int, #@loadConI
050 +   lbu  R10, [R7, #12] # byte, #@loadUB
054 +   ble  R11, R31, B8   #@cmpI_branch  P=0.000001 C=-1.000000
054
058   B5: # B7 &lt;- B4  Freq: 0.957693
058 +   slli  R29, R10, (#5 &amp; 0x1f) #@lShiftI_reg_imm
05c +   sub  R28, R29, R10  #@subI_reg_reg
060 +   j  B7   #@branch
        nop     # 3 bytes pad for loops and calls

070   B6: # B7 &lt;- B7  top-of-loop Freq: 21.6806
070 +   slli  R29, R10, (#5 &amp; 0x1f) #@lShiftI_reg_imm
074 +   sub  R28, R29, R10  #@subI_reg_reg
074
078   B7: # B6 B8 &lt;- B5 B6   Loop: B7-B6 inner main of N50 Freq: 22.6383
078 +   add R12, R7, R31    # ptr, #@addP_reg_reg
07c +   lbu  R30, [R12, #12]    # byte, #@loadUB
080 +   add  R30, R28, R30  #@addI_reg_reg
084 +   slli  R28, R30, (#5 &amp; 0x1f) #@lShiftI_reg_imm
088 +   lbu  R29, [R12, #13]    # byte, #@loadUB
08c +   sub  R30, R28, R30  #@subI_reg_reg
090 +   add  R30, R30, R29  #@addI_reg_reg
094 +   slli  R29, R30, (#5 &amp; 0x1f) #@lShiftI_reg_imm
098 +   lbu  R28, [R12, #14]    # byte, #@loadUB
09c +   sub  R30, R29, R30  #@subI_reg_reg
0a0 +   add  R30, R30, R28  #@addI_reg_reg
0a4 +   slli  R28, R30, (#5 &amp; 0x1f) #@lShiftI_reg_imm
0a8 +   lbu  R29, [R12, #15]    # byte, #@loadUB
0ac +   sub  R30, R28, R30  #@subI_reg_reg
0b0 +   add  R30, R30, R29  #@addI_reg_reg
0b4 +   slli  R29, R30, (#5 &amp; 0x1f) #@lShiftI_reg_imm
0b8 +   lbu  R28, [R12, #16]    # byte, #@loadUB
0bc +   sub  R30, R29, R30  #@subI_reg_reg
0c0 +   add  R28, R30, R28  #@addI_reg_reg
0c4 +   slli  R10, R28, (#5 &amp; 0x1f) #@lShiftI_reg_imm
0c8 +   lbu  R29, [R12, #17]    # byte, #@loadUB
0cc +   sub  R28, R10, R28  #@subI_reg_reg
0d0 +   add  R28, R28, R29  #@addI_reg_reg
0d4 +   slli  R30, R28, (#5 &amp; 0x1f) #@lShiftI_reg_imm
0d8 +   lbu  R10, [R12, #18]    # byte, #@loadUB
0dc +   sub  R28, R30, R28  #@subI_reg_reg
0e0 +   add  R28, R28, R10  #@addI_reg_reg
0e4 +   slli  R10, R28, (#5 &amp; 0x1f) #@lShiftI_reg_imm
0e8 +   lbu  R30, [R12, #19]    # byte, #@loadUB
0ec +   sub  R28, R10, R28  #@subI_reg_reg
0f0 +   add  R28, R28, R30  #@addI_reg_reg
0f4 +   slli  R30, R28, (#5 &amp; 0x1f) #@lShiftI_reg_imm
0f8 +   lbu  R10, [R12, #20]    # byte, #@loadUB
0fc +   sub  R28, R30, R28  #@subI_reg_reg
100 +   add  R28, R28, R10  #@addI_reg_reg
104 +   lbu  R30, [R12, #21]    # byte, #@loadUB
108 +   slli  R10, R28, (#5 &amp; 0x1f) #@lShiftI_reg_imm
10c +   sub  R28, R10, R28  #@subI_reg_reg
110 +   add  R28, R28, R30  #@addI_reg_reg
114 +   lbu  R10, [R12, #22]    # byte, #@loadUB
118 +   slli  R30, R28, (#5 &amp; 0x1f) #@lShiftI_reg_imm
11c +   sub  R28, R30, R28  #@subI_reg_reg
120 +   add  R28, R28, R10  #@addI_reg_reg
124 +   lbu  R30, [R12, #23]    # byte, #@loadUB
128 +   slli  R10, R28, (#5 &amp; 0x1f) #@lShiftI_reg_imm
12c +   sub  R28, R10, R28  #@subI_reg_reg
130 +   add  R28, R28, R30  #@addI_reg_reg
134 +   lbu  R10, [R12, #24]    # byte, #@loadUB
138 +   slli  R30, R28, (#5 &amp; 0x1f) #@lShiftI_reg_imm
13c +   sub  R28, R30, R28  #@subI_reg_reg
140 +   add  R28, R28, R10  #@addI_reg_reg
144 +   lbu  R30, [R12, #25]    # byte, #@loadUB
148 +   slli  R10, R28, (#5 &amp; 0x1f) #@lShiftI_reg_imm
14c +   sub  R28, R10, R28  #@subI_reg_reg
150 +   add  R28, R28, R30  #@addI_reg_reg
154 +   lbu  R10, [R12, #26]    # byte, #@loadUB
158 +   slli  R30, R28, (#5 &amp; 0x1f) #@lShiftI_reg_imm
15c +   sub  R28, R30, R28  #@subI_reg_reg
160 +   add  R28, R28, R10  #@addI_reg_reg
164 +   slli  R10, R28, (#5 &amp; 0x1f) #@lShiftI_reg_imm
168 +   lbu  R30, [R12, #27]    # byte, #@loadUB
16c +   sub  R28, R10, R28  #@subI_reg_reg
170 +   addi  R31, R31, #16 #@addI_reg_imm
174 +   add  R10, R28, R30  #@addI_reg_reg
178 +   blt  R31, R11, B6   #@cmpI_loop  P=0.957696 C=8263.000000
178
17c   B8: # B11 B9 &lt;- B4 B7  Freq: 0.957694
17c +   bge  R31, R8, B11   #@cmpI_branch  P=0.500000 C=-1.000000
17c
180   B9: # B10 &lt;- B8  Freq: 0.478847
180 +   # castII of R31, #@castII
180
180   B10: #    B10 B11 &lt;- B9 B10    Loop: B10-B10 inner post of N161 Freq: 0.957694
180     add R28, R7, R31    # ptr, #@addP_reg_reg
184 +   lbu  R29, [R28, #12]    # byte, #@loadUB
188 +   slli  R28, R10, (#5 &amp; 0x1f) #@lShiftI_reg_imm
18c +   sub  R30, R28, R10  #@subI_reg_reg
190 +   addi  R31, R31, #1  #@addI_reg_imm
194 +   add  R10, R30, R29  #@addI_reg_reg
198 +   blt  R31, R8, B10   #@cmpI_loop  P=0.500000 C=8263.000000
198
19c   B11: #    N1 &lt;- B10 B8 B12  Freq: 0.999998
19c     # pop frame 32
    add  sp, sp, #32
    lw  lr, [sp,#-8]
    lw  fp, [sp,#-4]
    # touch polling page
    li  t0, #0x3e829000
    lw zr, [t0]
1b0 +   ret // return register, #@Ret
1b0
1b4   B12: #    B11 &lt;- B2  Freq: 0.0423041
1b4 +   li R10, #0  # int, #@loadConI
1bc +   j  B11  #@branch
1bc
1c0   B13: #    N1 &lt;- B3  Freq: 9.70412e-07
1c0 +   li R11, #-130   # int, #@loadConI
1c8     spill R7 -&gt; [sp, #0] # spill size = 32
1cc     CALL,static 0x3b8a8d40  #@CallStaticJavaDirect wrapper for: uncommon_trap(reason=&apos;predicate&apos; action=&apos;maybe_recompile&apos;)
        # java.lang.StringLatin1::hashCode @ bci:13  L[0]=_ L[1]=#0 L[2]=sp + #0 L[3]=R8 L[4]=#0 L[5]=_ STK[0]=#0 STK[1]=R8
        # OopMap{[0]=Oop off=464}
1d0     #@ShouldNotReachHere
1d0
1d4   B14: #    N1 &lt;- B1  Freq: 1.01328e-06
1d4 +   li R11, #-10    # int, #@loadConI
1dc     CALL,static 0x3b8a8d40  #@CallStaticJavaDirect wrapper for: uncommon_trap(reason=&apos;null_check&apos; action=&apos;maybe_recompile&apos;)
        # java.lang.StringLatin1::hashCode @ bci:5  L[0]=_ L[1]=_ L[2]=_ L[3]=_ L[4]=_ L[5]=_ STK[0]=#NULL
        # OopMap{off=480}
1e0     #@ShouldNotReachHere
1e0

</opto_assembly>

关于在bishengJDK下会生成了一个关于Long类型操作的节点 convI2L_reg_reg 因为这个节点并没有做做64位的兼容操作,尝试修复如下:

zifeihan@k9-plct:~/jdk11u$ git diff
diff --git a/src/hotspot/cpu/riscv32/riscv32.ad b/src/hotspot/cpu/riscv32/riscv32.ad
index 0d6f5ebfa3..19de4c2364 100644
--- a/src/hotspot/cpu/riscv32/riscv32.ad
+++ b/src/hotspot/cpu/riscv32/riscv32.ad
@@ -7353,9 +7353,11 @@ instruct convI2L_reg_reg(iRegLNoSp dst, iRegIorL2I src)
   match(Set dst (ConvI2L src));

   ins_cost(ALU_COST);
-  format %{ "add  $dst, $src\t#@convI2L_reg_reg" %}
+  format %{ "mv  $dst.lo, $src\t# \n\t"
+            "srai $dst.hi, $dst.lo, 0x1f\t# #@convI2L_reg_reg" %}
   ins_encode %{
-    __ add(as_Register($dst$$reg), as_Register($src$$reg), zr);
+    __ mv(as_Register($dst$$reg), as_Register($src$$reg));
+    __ srai(as_Register($dst$$reg)->successor(), as_Register($dst$$reg), 0x1f);
   %}
   ins_pipe(ialu_reg);
 %}

修复后OpenJDK for RV32G使用 -XX:+PrintOptoAssembly 打印编译日志,但是 java.lang.StringLatin1 hashCode 方法中依然没有convI2L_reg_reg 节点,但是别的方法中的convI2L_reg_reg的汇编生成逻辑被修改了

image

然后通过 -XX:+PrintAssembly 打印最终执行时的汇编,发现最终汇编如下:

image
DingliZhang commented 2 years ago

FYI:参考 https://github.com/openjdk-riscv/jdk11u/issues/388#issuecomment-1180611255 中的方法对新版本https://github.com/openjdk-riscv/jdk11u/commit/84b6b047bb0da023780587b748f85052d22eaa82 进行了打印,发现与旧版本 https://github.com/openjdk-riscv/jdk11u/commit/8ecab9f0bfda037e081a424af9f2e1537f94ecce 相比编译的方法减少了:

image

但是在又尝试了几次之后,新版本https://github.com/openjdk-riscv/jdk11u/commit/84b6b047bb0da023780587b748f85052d22eaa82 的编译方法的最大id也变为了55,目前还在分析出现差异的原因,以及减少是否是偶发性的情况。

zifeihan commented 2 years ago

FYI:参考 #388 (comment) 中的方法对新版本84b6b04 进行了打印,发现与旧版本 8ecab9f 相比编译的方法减少了:

这种 task_queued 标签的方法,是还在编译队列中,并不一定是成功编译的,这里对比的话,可能需要参考 nmethod 标签的内容,这种才是已经编译成功的方法,也标识了编译后的汇编代码的起始位置。

image
zifeihan commented 2 years ago

已提交PR:https://github.com/openjdk-riscv/jdk11u/pull/433 ,用来修复 convI2L_reg_reg 对Long类型的处理。对当前结果无影响,PR验证参考:https://github.com/openjdk-riscv/jdk11u/issues/388#issuecomment-1180611255