hoshiumiarata · GitHub

The pool lookup logic for bigints was broken in the code generation for NODE_NEGATE.
It searched for positive bigints instead of negative ones, leading to two problems.

  1. It reused the same pool entry for negative bigints if the positive one was already present.

For example:

def f
  puts(36893488147419102235)
  puts(-36893488147419102235)
end
f

Will print:

36893488147419102235
36893488147419102235

After the fix, it will print:

36893488147419102235
-36893488147419102235

Codegen before fix:

irep 0x7f954ff49cd0 nregs=5 nlocals=2 pools=1 syms=1 reps=0 ilen=20
file: (mirb)
    4 000 ENTER         0:0:0:0:0:0:0 (0x0)
    5 004 LOADL         R3      L[0]                        <--------- SAME
    5 007 SSEND         R2      :puts   n=1
    6 011 LOADL         R3      L[0]                        <--------- SAME
    6 014 SSEND         R2      :puts   n=1
    6 018 RETURN        R2

Codegen after fix:

irep 0x7fcdfbf0f310 nregs=5 nlocals=2 pools=2 syms=1 reps=0 ilen=20
file: (mirb)
    4 000 ENTER         0:0:0:0:0:0:0 (0x0)
    5 004 LOADL         R3      L[0]                        <--------- DIFFERENT
    5 007 SSEND         R2      :puts   n=1
    6 011 LOADL         R3      L[1]                        <--------- DIFFERENT
    6 014 SSEND         R2      :puts   n=1
    6 018 RETURN        R2
  1. It generates new pool entries for negative bigints even if it is already present.

For example:

def f
  puts(-36893488147419102235)
  puts(-36893488147419102235)
  puts(-36893488147419102235)
  puts(-36893488147419102235)
  puts(-36893488147419102235)
  puts(-36893488147419102235)
  puts(-36893488147419102235)
  puts(-36893488147419102235)
  puts(-36893488147419102235)
  puts(-36893488147419102235)
end
f

Codegen before fix:

irep 0x7f9550b04390 nregs=5 nlocals=2 pools=10 syms=1 reps=0 ilen=76
file: (mirb)
   17 000 ENTER         0:0:0:0:0:0:0 (0x0)
   18 004 LOADL         R3      L[0]                        <--------- NEW POOL ENTRY
   18 007 SSEND         R2      :puts   n=1
   19 011 LOADL         R3      L[1]                        <--------- NEW POOL ENTRY
   19 014 SSEND         R2      :puts   n=1
   20 018 LOADL         R3      L[2]                        <--------- NEW POOL ENTRY
   20 021 SSEND         R2      :puts   n=1
   21 025 LOADL         R3      L[3]                        <--------- NEW POOL ENTRY
   21 028 SSEND         R2      :puts   n=1
   22 032 LOADL         R3      L[4]                        <--------- NEW POOL ENTRY
   22 035 SSEND         R2      :puts   n=1
   23 039 LOADL         R3      L[5]                        <--------- NEW POOL ENTRY
   23 042 SSEND         R2      :puts   n=1
   24 046 LOADL         R3      L[6]                        <--------- NEW POOL ENTRY
   24 049 SSEND         R2      :puts   n=1
   25 053 LOADL         R3      L[7]                        <--------- NEW POOL ENTRY
   25 056 SSEND         R2      :puts   n=1
   26 060 LOADL         R3      L[8]                        <--------- NEW POOL ENTRY
   26 063 SSEND         R2      :puts   n=1
   27 067 LOADL         R3      L[9]                        <--------- NEW POOL ENTRY
   27 070 SSEND         R2      :puts   n=1
   27 074 RETURN        R2

Codegen after fix:

irep 0x7f9cbfe04360 nregs=5 nlocals=2 pools=1 syms=1 reps=0 ilen=76
file: (mirb)
   12 000 ENTER         0:0:0:0:0:0:0 (0x0)
   13 004 LOADL         R3      L[0]                        <--------- SAME
   13 007 SSEND         R2      :puts   n=1
   14 011 LOADL         R3      L[0]                        <--------- SAME
   14 014 SSEND         R2      :puts   n=1
   15 018 LOADL         R3      L[0]                        <--------- SAME
   15 021 SSEND         R2      :puts   n=1
   16 025 LOADL         R3      L[0]                        <--------- SAME
   16 028 SSEND         R2      :puts   n=1
   17 032 LOADL         R3      L[0]                        <--------- SAME
   17 035 SSEND         R2      :puts   n=1
   18 039 LOADL         R3      L[0]                        <--------- SAME
   18 042 SSEND         R2      :puts   n=1
   19 046 LOADL         R3      L[0]                        <--------- SAME
   19 049 SSEND         R2      :puts   n=1
   20 053 LOADL         R3      L[0]                        <--------- SAME
   20 056 SSEND         R2      :puts   n=1
   21 060 LOADL         R3      L[0]                        <--------- SAME
   21 063 SSEND         R2      :puts   n=1
   22 067 LOADL         R3      L[0]                        <--------- SAME
   22 070 SSEND         R2      :puts   n=1
   22 074 RETURN        R2

Read the original on github.com ↗