-
-
Notifications
You must be signed in to change notification settings - Fork 5.5k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
automatic recompilation of dependent functions #265
Comments
I believe this is because the code for |
I was hoping nobody would notice this, but I guess that wasn't realistic of me :) |
It's more fun than that; it really lets you see the JIT at work, since it isn't resolved until execution: julia> function f2()
a
end
julia> function f1()
f2()
end
julia> function f2()
2
end
julia> f1()
2 However, I fear this can lead to some unexpected results at the REPL, although I don't really know the best way to deal with it. Although I used an error to show the difference in dramatic fashion, it could also happens if I was trying to see the effect of changing an inner equation or constant! |
There are two types of locations that may need to be updated when a method is altered:
The former could be updated just by changing the function body: it could be altered in place, or the calling sites could be actively updated to call a new location, or the old function body could be replaced with a stub that jumps to the new version, optionally patching the calling site. For inlining, we need to track the callers that have inlined the function and re-JIT them. |
Really all we can do is discard code, because even if a method wasn't inlined any function that calls it might depend on type behavior that can change if the method changes. This is mostly for interactive cases so re-compiling code is not a huge deal. |
Bummer. Well, since it's primarily the repl that's affected, doing the right thing slowly is fine. At run-time, this should almost never kick in — why would someone define something and then redefine it again except interactively? If the solution ends up inducing a lot of overhead maybe turning it one should be optional and automatically done in the repl? |
We need to document that this is undefined currently. |
Technically, this isn't bug, it's an undefined behavior. When you redefine a method, the resulting behavior is undefined. So Julia can do whatever it likes, including what it currently does. Providing a well-defined behavior upon method redefinition is a feature, not a bug fix. I'm also not convinced that this is a v1.0 issue since going from an undefined behavior to providing a well-defined behavior is not a breaking change. This could be implemented in v1.1 without breaking any valid v1.0 code. |
Greg Clayton from Apple's LLVM/LLDB staff was kind enough to document how to elicit (with lldb libraries, a subproject of llvm) the necessary information to determine a binary's dependencies from the embedded symbol info (symbol imports); as well as those symbols exported by a binary (necessary to construct the complete dependency graph).
On Mon, Apr 2, 2012 at 3:13 PM, Greg Clayton [email protected] wrote:
On Mon, Apr 2, 2012 at 4:05 PM, Greg Clayton [email protected] wrote:
|
Dev-list discussion here: https://groups.google.com/forum/?fromgroups=#!topic/julia-dev/snnGKJul4vg. |
This is dredging up an amazingly old thread, but I realized I am possibly flirting around the edges of this problem with my codespeed benchmarking code. I repeatedly |
Might be better to include them in a module repeatedly, but I realize that bumps up against the anonymous module problem that's also been raised on the dev list. In this case, it may be fine, however, since you can just define the same module multiple times and ignore the warning that emits. |
Perhaps an old thread, but as relevant as ever. |
I was referring to this: #3661. |
…s as long as we reflect on world=typemax(UInt) Note that this is not technically correct, since always treating world=typemax(UInt) is basically equivalent to reintroducing JuliaLang/julia#265. Thus, we still need to fix #6 eventually.
I'm still getting this on Julia 1.5 and master on occasion, where julia> using VectorizationBase, VectorizedRNG
julia> @code_typed VectorizedRNG.setrand64counter!(local_rng(), 0x01) # we have a constant offset of 514
CodeInfo(
1 ─ %1 = Base.getfield(rng, :ptr)::Ptr{UInt64}
│ %2 = Base.bitcast(Ptr{UInt8}, %1)::Ptr{UInt8}
│ %3 = VectorizationBase.llvmcall(("", "%ptr.0 = inttoptr i64 %0 to i8*\n%ptr.1 = getelementptr inbounds i8, i8* %ptr.0, i64 %2\nstore i8 %1, i8* %ptr.1, align 1\nret void"), VectorizationBase.Cvoid, Tuple{Ptr{UInt8},UInt8,Int64}, %2, v, 514)::Nothing
└── return %3
) => Nothing
julia> @code_llvm VectorizedRNG.setrand64counter!(local_rng(), 0x01) # we have a constant offset of 514
; @ /home/chriselrod/.julia/dev/VectorizedRNG/src/xoshiro.jl:97 within `setrand64counter!'
define void @"julia_setrand64counter!_1785"([1 x i64]* nocapture nonnull readonly dereferenceable(8), i8) {
top:
; @ /home/chriselrod/.julia/dev/VectorizedRNG/src/xoshiro.jl:98 within `setrand64counter!'
; ┌ @ essentials.jl:392 within `unsafe_convert'
; │┌ @ pointer.jl:30 within `convert'
%2 = bitcast [1 x i64]* %0 to i8**
%3 = load i8*, i8** %2, align 8
; └└
; ┌ @ /home/chriselrod/.julia/dev/VectorizationBase/src/llvm_intrin/memory_addr.jl:782 within `vstore!' @ /home/chriselrod/.julia/dev/VectorizationBase/src/llvm_intrin/memory_addr.jl:638
; │┌ @ /home/chriselrod/.julia/dev/VectorizationBase/src/llvm_intrin/memory_addr.jl:638 within `macro expansion'
%ptr.1.i = getelementptr inbounds i8, i8* %3, i64 514
store i8 %1, i8* %ptr.1.i, align 1
; └└
ret void
}
julia> VectorizationBase.has_feature(::Val{:x86_64_avx512f}) = VectorizationBase.False()
julia> VectorizationBase.has_feature(::Val{:x86_64_avx2}) = VectorizationBase.False()
julia> @code_typed VectorizedRNG.setrand64counter!(local_rng(), 0x01) # we have a constant offset of 130
CodeInfo(
1 ─ %1 = Base.getfield(rng, :ptr)::Ptr{UInt64}
│ %2 = Base.bitcast(Ptr{UInt8}, %1)::Ptr{UInt8}
│ %3 = VectorizationBase.llvmcall(("", "%ptr.0 = inttoptr i64 %0 to i8*\n%ptr.1 = getelementptr inbounds i8, i8* %ptr.0, i64 %2\nstore i8 %1, i8* %ptr.1, align 1\nret void"), VectorizationBase.Cvoid, Tuple{Ptr{UInt8},UInt8,Int64}, %2, v, 130)::Nothing
└── return %3
) => Nothing
julia> @code_llvm VectorizedRNG.setrand64counter!(local_rng(), 0x01) # we have a constant offset of 130
; @ /home/chriselrod/.julia/dev/VectorizedRNG/src/xoshiro.jl:97 within `setrand64counter!'
define void @"julia_setrand64counter!_1790"([1 x i64]* nocapture nonnull readonly dereferenceable(8), i8) {
top:
; @ /home/chriselrod/.julia/dev/VectorizedRNG/src/xoshiro.jl:98 within `setrand64counter!'
; ┌ @ essentials.jl:392 within `unsafe_convert'
; │┌ @ pointer.jl:30 within `convert'
%2 = bitcast [1 x i64]* %0 to i8**
%3 = load i8*, i8** %2, align 8
; └└
; ┌ @ /home/chriselrod/.julia/dev/VectorizationBase/src/llvm_intrin/memory_addr.jl:782 within `vstore!' @ /home/chriselrod/.julia/dev/VectorizationBase/src/llvm_intrin/memory_addr.jl:638
; │┌ @ /home/chriselrod/.julia/dev/VectorizationBase/src/llvm_intrin/memory_addr.jl:638 within `macro expansion'
%ptr.1.i = getelementptr inbounds i8, i8* %3, i64 130
store i8 %1, i8* %ptr.1.i, align 1
; └└
ret void
} We start with a 514, and then after the redefinitions, the offset is 130 (the offset equals 2 + 8 * number of integers it can process efficiently with SIMD instructions). julia> using VectorizationBase
julia> VectorizationBase.has_feature(::Val{:x86_64_avx512f}) = VectorizationBase.False()
julia> VectorizationBase.has_feature(::Val{:x86_64_avx2}) = VectorizationBase.False()
julia> using VectorizationBase, VectorizedRNG
julia> @code_typed VectorizedRNG.setrand64counter!(local_rng(), 0x01) # we have a constant offset of 130
CodeInfo(
1 ─ %1 = Base.getfield(rng, :ptr)::Ptr{UInt64}
│ %2 = Base.bitcast(Ptr{UInt8}, %1)::Ptr{UInt8}
│ %3 = VectorizationBase.llvmcall(("", "%ptr.0 = inttoptr i64 %0 to i8*\n%ptr.1 = getelementptr inbounds i8, i8* %ptr.0, i64 %2\nstore i8 %1, i8* %ptr.1, align 1\nret void"), VectorizationBase.Cvoid, Tuple{Ptr{UInt8},UInt8,Int64}, %2, v, 130)::Nothing
└── return %3
) => Nothing
julia> @code_llvm VectorizedRNG.setrand64counter!(local_rng(), 0x01) # we have a constant offset of 130
; @ /home/chriselrod/.julia/dev/VectorizedRNG/src/xoshiro.jl:97 within `setrand64counter!'
define void @"julia_setrand64counter!_1660"([1 x i64]* nocapture nonnull readonly dereferenceable(8), i8) {
top:
; @ /home/chriselrod/.julia/dev/VectorizedRNG/src/xoshiro.jl:98 within `setrand64counter!'
; ┌ @ essentials.jl:392 within `unsafe_convert'
; │┌ @ pointer.jl:30 within `convert'
%2 = bitcast [1 x i64]* %0 to i8**
%3 = load i8*, i8** %2, align 8
; └└
; ┌ @ /home/chriselrod/.julia/dev/VectorizationBase/src/llvm_intrin/memory_addr.jl:782 within `vstore!' @ /home/chriselrod/.julia/dev/VectorizationBase/src/llvm_intrin/memory_addr.jl:638
; │┌ @ /home/chriselrod/.julia/dev/VectorizationBase/src/llvm_intrin/memory_addr.jl:638 within `macro expansion'
%ptr.1.i = getelementptr inbounds i8, i8* %3, i64 514
store i8 %1, i8* %ptr.1.i, align 1
; └└
ret void
}
|
Might be related: https://github.com/chriselrod/VectorizationBase.jl/search?q=pure
|
Oops, might be my fault! Thanks -- I'll try taking them out. Without |
Unfortunately not: (@v1.7) pkg> st VectorizationBase
Status `~/.julia/environments/v1.7/Project.toml`
[3d5dd08c] VectorizationBase v0.18.3 `~/.julia/dev/VectorizationBase`
julia> using VectorizationBase
julia> run(`grep -nr "pure" $(dirname(pathof(VectorizationBase)))`) # all instances of `pure` are commented out
/home/chriselrod/.julia/dev/VectorizationBase/src/VectorizationBase.jl:14:# Base.@pure asvalbool(r) = Val(map(Bool, r))
/home/chriselrod/.julia/dev/VectorizationBase/src/VectorizationBase.jl:15:# Base.@pure asvalint(r) = Val(map(Int, r))
/home/chriselrod/.julia/dev/VectorizationBase/src/llvm_intrin/vbroadcast.jl:54: # $(Expr(:meta,:pure,:inline))
Process(`grep -nr pure /home/chriselrod/.julia/dev/VectorizationBase/src`, ProcessExited(0))
julia> VectorizationBase.has_feature(::Val{:x86_64_avx512f}) = VectorizationBase.False()
julia> VectorizationBase.has_feature(::Val{:x86_64_avx2}) = VectorizationBase.False()
julia> using VectorizedRNG
[ Info: Precompiling VectorizedRNG [33b4df10-0173-11e9-2a0c-851a7edac40e]
julia> @code_typed VectorizedRNG.setrand64counter!(local_rng(), 0x01) # we have a constant offset of 130
CodeInfo(
1 ─ %1 = Base.getfield(rng, :ptr)::Ptr{UInt64}
│ %2 = Base.bitcast(Ptr{UInt8}, %1)::Ptr{UInt8}
│ %3 = VectorizationBase.llvmcall((" \n\n define void @entry(i64, i8, i64) alwaysinline {\n top:\n %ptr.0 = inttoptr i64 %0 to i8*\n%ptr.1 = getelementptr inbounds i8, i8* %ptr.0, i64 %2\nstore i8 %1, i8* %ptr.1, align 1\nret void\n }\n", "entry"), VectorizationBase.Cvoid, Tuple{Ptr{UInt8}, UInt8, Int64}, %2, v, 130)::Nothing
└── return %3
) => Nothing
julia> @code_llvm VectorizedRNG.setrand64counter!(local_rng(), 0x01) # we have a constant offset of 514
; @ /home/chriselrod/.julia/dev/VectorizedRNG/src/xoshiro.jl:97 within `setrand64counter!'
define void @"julia_setrand64counter!_1414"([1 x i64]* nocapture nonnull readonly align 8 dereferenceable(8) %0, i8 zeroext %1) {
top:
; @ /home/chriselrod/.julia/dev/VectorizedRNG/src/xoshiro.jl:98 within `setrand64counter!'
; ┌ @ essentials.jl:402 within `unsafe_convert'
; │┌ @ pointer.jl:30 within `convert'
%2 = bitcast [1 x i64]* %0 to i8**
%3 = load i8*, i8** %2, align 8
; └└
; ┌ @ /home/chriselrod/.julia/dev/VectorizationBase/src/llvm_intrin/memory_addr.jl:782 within `vstore!' @ /home/chriselrod/.julia/dev/VectorizationBase/src/llvm_intrin/memory_addr.jl:638
; │┌ @ /home/chriselrod/.julia/dev/VectorizationBase/src/llvm_intrin/memory_addr.jl:638 within `macro expansion'
%ptr.1.i = getelementptr inbounds i8, i8* %3, i64 514
store i8 %1, i8* %ptr.1.i, align 1
; └└
ret void
} EDIT: I just pushed the commit to remove all the EDIT: Although ArrrayInterface.jl is also using it at some locations. I'll try taking those out too. EDIT: Also removing them from ArrayInterface solved the problem. |
On 1.5, removing all julia> using VectorizationBase
julia> !success(run(`grep -nr "pure" $(dirname(pathof(VectorizationBase)))`, wait=false))
true
julia> VectorizationBase.has_feature(::Val{:x86_64_avx512f}) = VectorizationBase.False()
julia> VectorizationBase.has_feature(::Val{:x86_64_avx2}) = VectorizationBase.False()
julia> using VectorizedRNG
julia> @code_typed VectorizedRNG.setrand64counter!(local_rng(), 0x01) # we have a constant offset of 130
CodeInfo(
1 ─ %1 = Base.getfield(rng, :ptr)::Ptr{UInt64}
│ %2 = Base.bitcast(Ptr{UInt8}, %1)::Ptr{UInt8}
│ %3 = VectorizationBase.llvmcall(("", "%ptr.0 = inttoptr i64 %0 to i8*\n%ptr.1 = getelementptr inbounds i8, i8* %ptr.0, i64 %2\nstore i8 %1, i8* %ptr.1, align 1\nret void"), VectorizationBase.Cvoid, Tuple{Ptr{UInt8},UInt8,Int64}, %2, v, 130)::Nothing
└── return %3
) => Nothing
julia> @code_llvm VectorizedRNG.setrand64counter!(local_rng(), 0x01) # we have a constant offset of 514
; @ /home/chriselrod/.julia/dev/VectorizedRNG/src/xoshiro.jl:97 within `setrand64counter!'
define void @"julia_setrand64counter!_1692"([1 x i64]* nocapture nonnull readonly dereferenceable(8), i8) {
top:
; @ /home/chriselrod/.julia/dev/VectorizedRNG/src/xoshiro.jl:98 within `setrand64counter!'
; ┌ @ essentials.jl:392 within `unsafe_convert'
; │┌ @ pointer.jl:30 within `convert'
%2 = bitcast [1 x i64]* %0 to i8**
%3 = load i8*, i8** %2, align 8
; └└
; ┌ @ /home/chriselrod/.julia/dev/VectorizationBase/src/llvm_intrin/memory_addr.jl:782 within `vstore!' @ /home/chriselrod/.julia/dev/VectorizationBase/src/llvm_intrin/memory_addr.jl:638
; │┌ @ /home/chriselrod/.julia/dev/VectorizationBase/src/llvm_intrin/memory_addr.jl:638 within `macro expansion'
%ptr.1.i = getelementptr inbounds i8, i8* %3, i64 130
store i8 %1, i8* %ptr.1.i, align 1
; └└
ret void
}
julia> using ArrayInterface
julia> !success(run(`grep -nr "pure" $(dirname(pathof(ArrayInterface)))`, wait=false))
true
julia> versioninfo()
Julia Version 1.5.3
Commit 788b2c77c1 (2020-11-09 13:37 UTC)
Platform Info:
OS: Linux (x86_64-generic-linux)
CPU: Intel(R) Core(TM) i9-7900X CPU @ 3.30GHz
WORD_SIZE: 64
LIBM: libopenlibm
LLVM: libLLVM-9.0.1 (ORCJIT, skylake-avx512)
Environment:
JULIA_NUM_THREADS = auto But on master: julia> using VectorizationBase
julia> !success(run(`grep -nr "pure" $(dirname(pathof(VectorizationBase)))`, wait=false))
true
julia> VectorizationBase.has_feature(::Val{:x86_64_avx512f}) = VectorizationBase.False()
julia> VectorizationBase.has_feature(::Val{:x86_64_avx2}) = VectorizationBase.False()
julia> using VectorizedRNG
julia> @code_typed VectorizedRNG.setrand64counter!(local_rng(), 0x01) # we have a constant offset of 130
CodeInfo(
1 ─ %1 = Base.getfield(rng, :ptr)::Ptr{UInt64}
│ %2 = Base.bitcast(Ptr{UInt8}, %1)::Ptr{UInt8}
│ %3 = VectorizationBase.llvmcall((" \n\n define void @entry(i64, i8, i64) alwaysinline {\n top:\n %ptr.0 = inttoptr i64 %0 to i8*\n%ptr.1 = getelementptr inbounds i8, i8* %ptr.0, i64 %2\nstore i8 %1, i8* %ptr.1, align 1\nret void\n }\n", "entry"), VectorizationBase.Cvoid, Tuple{Ptr{UInt8}, UInt8, Int64}, %2, v, 130)::Nothing
└── return %3
) => Nothing
julia> @code_llvm VectorizedRNG.setrand64counter!(local_rng(), 0x01) # we have a constant offset of 514
; @ /home/chriselrod/.julia/dev/VectorizedRNG/src/xoshiro.jl:97 within `setrand64counter!'
define void @"julia_setrand64counter!_1161"([1 x i64]* nocapture nonnull readonly align 8 dereferenceable(8) %0, i8 zeroext %1) {
top:
; @ /home/chriselrod/.julia/dev/VectorizedRNG/src/xoshiro.jl:98 within `setrand64counter!'
; ┌ @ essentials.jl:402 within `unsafe_convert'
; │┌ @ pointer.jl:30 within `convert'
%2 = bitcast [1 x i64]* %0 to i8**
%3 = load i8*, i8** %2, align 8
; └└
; ┌ @ /home/chriselrod/.julia/dev/VectorizationBase/src/llvm_intrin/memory_addr.jl:782 within `vstore!' @ /home/chriselrod/.julia/dev/VectorizationBase/src/llvm_intrin/memory_addr.jl:638
; │┌ @ /home/chriselrod/.julia/dev/VectorizationBase/src/llvm_intrin/memory_addr.jl:638 within `macro expansion'
%ptr.1.i = getelementptr inbounds i8, i8* %3, i64 514
store i8 %1, i8* %ptr.1.i, align 1
; └└
ret void
}
julia> using ArrayInterface
julia> !success(run(`grep -nr "pure" $(dirname(pathof(ArrayInterface)))`, wait=false))
true
julia> versioninfo()
Julia Version 1.7.0-DEV.421
Commit 22858a0d29* (2021-02-01 19:04 UTC)
Platform Info:
OS: Linux (x86_64-generic-linux)
CPU: Intel(R) Core(TM) i9-7900X CPU @ 3.30GHz
WORD_SIZE: 64
LIBM: libopenlibm
LLVM: libLLVM-11.0.1 (ORCJIT, skylake-avx512)
Environment:
JULIA_NUM_THREADS = auto EDIT: No longer works on 1.5. |
Note that |
Could that explain why While there is a lot of |
Also, redefining after the module has been loaded does trigger recompilation: julia> @code_llvm VectorizedRNG.setrand64counter!(local_rng(), 0x01) # we have a constant offset of 514
; @ /home/chriselrod/.julia/dev/VectorizedRNG/src/xoshiro.jl:97 within `setrand64counter!'
define void @"julia_setrand64counter!_1161"([1 x i64]* nocapture nonnull readonly align 8 dereferenceable(8) %0, i8 zeroext %1) {
top:
; @ /home/chriselrod/.julia/dev/VectorizedRNG/src/xoshiro.jl:98 within `setrand64counter!'
; ┌ @ essentials.jl:402 within `unsafe_convert'
; │┌ @ pointer.jl:30 within `convert'
%2 = bitcast [1 x i64]* %0 to i8**
%3 = load i8*, i8** %2, align 8
; └└
; ┌ @ /home/chriselrod/.julia/dev/VectorizationBase/src/llvm_intrin/memory_addr.jl:782 within `vstore!' @ /home/chriselrod/.julia/dev/VectorizationBase/src/llvm_intrin/memory_addr.jl:638
; │┌ @ /home/chriselrod/.julia/dev/VectorizationBase/src/llvm_intrin/memory_addr.jl:638 within `macro expansion'
%ptr.1.i = getelementptr inbounds i8, i8* %3, i64 514
store i8 %1, i8* %ptr.1.i, align 1
; └└
ret void
}
julia> VectorizationBase.has_feature(Val{:x86_64_avx2}())
False()
julia> VectorizationBase.has_feature(::Val{:x86_64_avx2}) = VectorizationBase.False()
julia> @code_llvm VectorizedRNG.setrand64counter!(local_rng(), 0x01) # we have a constant offset of 514
; @ /home/chriselrod/.julia/dev/VectorizedRNG/src/xoshiro.jl:97 within `setrand64counter!'
define void @"julia_setrand64counter!_1287"([1 x i64]* nocapture nonnull readonly align 8 dereferenceable(8) %0, i8 zeroext %1) {
top:
; @ /home/chriselrod/.julia/dev/VectorizedRNG/src/xoshiro.jl:98 within `setrand64counter!'
; ┌ @ essentials.jl:402 within `unsafe_convert'
; │┌ @ pointer.jl:30 within `convert'
%2 = bitcast [1 x i64]* %0 to i8**
%3 = load i8*, i8** %2, align 8
; └└
; ┌ @ /home/chriselrod/.julia/dev/VectorizationBase/src/llvm_intrin/memory_addr.jl:782 within `vstore!' @ /home/chriselrod/.julia/dev/VectorizationBase/src/llvm_intrin/memory_addr.jl:638
; │┌ @ /home/chriselrod/.julia/dev/VectorizationBase/src/llvm_intrin/memory_addr.jl:638 within `macro expansion'
%ptr.1.i = getelementptr inbounds i8, i8* %3, i64 130
store i8 %1, i8* %ptr.1.i, align 1
; └└
ret void
} The code created the bodies of generated functions shouldn't depend on any of these methods being redefined julia> VectorizedRNG.getoffset()
514
julia> @code_typed VectorizedRNG.getoffset()
CodeInfo(
1 ─ return 130
) => Int64
julia> VectorizedRNG.getoffset()
514
julia> @code_warntype VectorizedRNG.getoffset()
MethodInstance for VectorizedRNG.getoffset()
from getoffset() in VectorizedRNG at /home/chriselrod/.julia/dev/VectorizedRNG/src/xoshiro.jl:97
Arguments
#self#::Core.Const(VectorizedRNG.getoffset)
Body::Int64
1 ─ %1 = VectorizedRNG.simd_integer_register_size()::Core.Const(static(16))
│ %2 = (4 * %1)::Core.Const(64)
│ %3 = (%2 * 2)::Core.Const(128)
│ %4 = (%3 + 2)::Core.Const(130)
└── return %4
julia> VectorizedRNG.simd_integer_register_size()
static(16) Downstream of By checking out the master branches, there is this simpler reproducer: julia> using VectorizationBase
julia> VectorizationBase.has_feature(::Val{:x86_64_avx2}) = VectorizationBase.False()
julia> using VectorizedRNG
[ Info: Precompiling VectorizedRNG [33b4df10-0173-11e9-2a0c-851a7edac40e]
julia> VectorizedRNG.getoffset()
514
julia> @code_warntype VectorizedRNG.getoffset()
MethodInstance for VectorizedRNG.getoffset()
from getoffset() in VectorizedRNG at /home/chriselrod/.julia/dev/VectorizedRNG/src/xoshiro.jl:98
Arguments
#self#::Core.Const(VectorizedRNG.getoffset)
Body::Int64
1 ─ %1 = VectorizedRNG.sirs()::Core.Const(static(16))
│ %2 = (4 * %1)::Core.Const(64)
│ %3 = (%2 * 2)::Core.Const(128)
│ %4 = (%3 + 2)::Core.Const(130)
└── return %4
julia> VectorizedRNG.sirs()
static(16)
julia> VectorizedRNG.getoffset()
514
|
if I define a function d2 before a function d1 which calls d2 then change d2, d1 uses the old definition for d2.
I assume this is because it is all precompiled, but maybe there should be a note warning of this? Or would it be possible to replace the old definition with a longjmp to the new one?
(Mostly important for the REPL, since I don't always do a full load)
The text was updated successfully, but these errors were encountered: