reactorlabs/rir

partially defined values cause boxing

Aberta

#788 aberto em 22 de jan. de 2020

 (1 comentário) (0 reação) (0 responsável)C++ (19 forks)github user discovery
backendhelp wanted

Métricas do repositório

Stars
 (61 estrelas)
Métricas de merge de PR
 (Mesclagem média 1m) (1 fundiu PR em 30d)

Description

Reproduce

First disable loop peeling (rir/src/ir/Compiler.cpp Compiler::loopPeelingEnabled) Then run the following code:

f = function(u) {
  for (i in 1:10) {
    1+u  # this causes speculation (and a deopt)
    a=1  # this declares a
  }
}

# call with non-reflective, but not trivial promise
a=1
f(a)
f(a)
f(a)

with PIR_DEBUG=PrintPirAfterOpt bin/R

Issue

The variable a is captured by the deopt point. But in the first iteration it is uninitialized. This causes us to have the variable as:

(real|_)"       %1.0  = Phi                      unboundValue:BB0, %0.1:BB3

First of all, the type inference seems to drop the scalar flag $, but even worse, the type of unboundValue (ie. _) is represented as a boxed value in the native backend (rir/src/compiler/native/lower_llvm.cpp). Therefore the real will also be boxed.

Solutions

I see two solutions:

1. At the PIR level

Have a PIR pass that does sth like:

real$       %1.0  = Phi                      undefined:BB0, %0.1:BB3
t           %1.1  = Phi                      TRUE:BB0,      FALSE:BB3

and then (using pseudo PIR code)

  • when a it is used as a variable:
if (!%1.1) error("missing object a")
  • when a is used to create an env:
MKEnv                    a= (%1.1 ? %1.0 : unboundValue)

2. In the native backend

  1. Compile any T|_ to a T instead, initialize it with undef.
  2. Keep a bitset that remembers which of those are initialized
  3. Automatically insert the above checks when such a variable is accessed

Guia do colaborador