I have a query compiler which emits Julia code. The code contains lots of
calls to generated functions, which include sections like this:

    hi = gallop(column, column[finger.lo], finger.lo, finger.hi, <=)
    Finger{$(C+1)}(finger.lo, hi)

Finger is an immutable, isbits type:

  immutable Finger{C}

When I run the generated code I see many millions of allocations. Using
code_warntype I can see that all the generated functions have been inlined,
every variable has a concrete inferred type and there are no generic calls.
And yet I see many sections in the llvm code like this:

  %235 = call %jl_value_t* @jl_gc_pool_alloc(i8* %ptls_i8, i32 1456, i32 32)
  %236 = getelementptr inbounds %jl_value_t, %jl_value_t* %235, i64 -1, i32
  store %jl_value_t* inttoptr (i64 139661604385936 to %jl_value_t*),
%jl_value_t** %236, align 8
  %237 = bitcast %jl_value_t* %235 to i64*
  store i64 %229, i64* %237, align 8
  %238 = getelementptr inbounds %jl_value_t, %jl_value_t* %235, i64 1
  %239 = bitcast %jl_value_t* %238 to i64*
  store i64 %234, i64* %239, align 8
  store %jl_value_t* %235, %jl_value_t** %finger_2_2, align 8
  %.pr = load %jl_value_t*, %jl_value_t** %finger_1_2, align 8

The pointer on the third line is:

  unsafe_pointer_to_objref(convert(Ptr{Any}, 139661604385936))
  # => Data.Finger{1}

So it appears that these fingers are still being heap-allocated.

What could cause this? And more generally, how does one debug issues like
this? Is there any way to introspect on the decision?

Reply via email to