Skip to content

Start excising LinearAlgebra #51904

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

Closed
wants to merge 7 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion base/Base.jl
Original file line number Diff line number Diff line change
Expand Up @@ -479,6 +479,10 @@ include("docs/basedocs.jl")
# Documentation -- should always be included last in sysimg.
include("docs/Docs.jl")
using .Docs

# excised stdlib stubs, needs to be after docs
include("stubs.jl")

if isdefined(Core, :Compiler) && is_primary_base_module
Docs.loaddocs(Core.Compiler.CoreDocs.DOCS)
end
Expand Down Expand Up @@ -621,7 +625,7 @@ end
# enable threads support
@eval PCRE PCRE_COMPILE_LOCK = Threads.SpinLock()

end
end # is_primary_base_module

# Ensure this file is also tracked
@assert !isassigned(_included_files, 1)
Expand Down
1 change: 1 addition & 0 deletions base/compiler/typeinfer.jl
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
# Tracking of newly-inferred CodeInstances during precompilation
const track_newly_inferred = RefValue{Bool}(false)
const newly_inferred = CodeInstance[]
const newly_deleted = Method[]

# build (and start inferring) the inference frame for the top-level MethodInstance
function typeinf(interp::AbstractInterpreter, result::InferenceResult, cache::Symbol)
Expand Down
1 change: 1 addition & 0 deletions base/loading.jl
Original file line number Diff line number Diff line change
Expand Up @@ -2306,6 +2306,7 @@ function include_package_for_output(pkg::PkgId, input::String, depot_path::Vecto
end

ccall(:jl_set_newly_inferred, Cvoid, (Any,), Core.Compiler.newly_inferred)
ccall(:jl_set_newly_deleted, Cvoid, (Any,), Core.Compiler.newly_deleted)
Core.Compiler.track_newly_inferred.x = true
try
Base.include(Base.__toplevel__, input)
Expand Down
142 changes: 142 additions & 0 deletions base/stubs.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,142 @@
module Stubs

module Random
let Random_PkgID = Base.PkgId(Base.UUID(0x9a3f8284_a2c9_5f02_9a11_845980a1fd5c), "Random")
RANDOM_MODULE_REF = Ref{Module}()

global delay_initialize
function delay_initialize()
if !isassigned(RANDOM_MODULE_REF)
RANDOM_MODULE_REF[] = Base.require(Random_PkgID)
end
return ccall(:jl_module_world, Csize_t, (Any,), RANDOM_MODULE_REF[])
end
end

import Base: rand, randn
function rand(args...)
Base.invoke_in_world(delay_initialize(), rand, args...)
end

function randn(args...)
Base.invoke_in_world(delay_initialize(), randn, args...)
end
end

for name in names(Random, imported=true)
func = getglobal(Random, name)
if func isa Function
@eval Base.Docs.getdoc(::typeof($func)) = (Random.delay_initialize(); nothing)
end
end

module LinearAlgebra
let LinearAlgebra_PkgID = Base.PkgId(Base.UUID(0x37e2e46d_f89d_539d_b4ee_838fcccc9c8e), "LinearAlgebra")
LINALG_MODULE_REF = Ref{Module}()

global delay_initialize
function delay_initialize()
if !isassigned(LINALG_MODULE_REF)
LINALG_MODULE_REF[] = Base.require(LinearAlgebra_PkgID)
end
return ccall(:jl_module_world, Csize_t, (Any,), LINALG_MODULE_REF[])
end
end

import Base: adjoint, *, \, ^, acos, acosh, acot, acoth, acsc, acsch, asec, asech, asin, asinh, atan, atanh, cis,
cos, cosh, cot, coth, csc, csch, exp, inv, isone, kron, kron!, log, sec, sech, sin, sinh,
sincos, sqrt, tan, tanh, transpose, sqrt, isapprox

adjoint(B::Union{BitMatrix, BitVector}) = Base.invoke_in_world(delay_initialize(), adjoint, B)
adjoint(a::AbstractArray) = Base.invoke_in_world(delay_initialize(), adjoint, B)

*(A::AbstractMatrix, B::AbstractMatrix, C::AbstractMatrix, D::AbstractMatrix) = Base.invoke_in_world(delay_initialize(), *, A, B, C, D)
*(A::AbstractMatrix, B::AbstractMatrix, C::AbstractMatrix, x::AbstractVector) = Base.invoke_in_world(delay_initialize(), *, A, B, C, x)
*(A::AbstractMatrix, B::AbstractMatrix, x::AbstractVector) = Base.invoke_in_world(delay_initialize(), *, A, B, x)
*(A::AbstractMatrix, B::AbstractMatrix, C::AbstractMatrix) = Base.invoke_in_world(delay_initialize(), *, A, B, C)
*(a::AbstractVector, B::AbstractMatrix) = Base.invoke_in_world(delay_initialize(), *, a, B)
*(A::AbstractMatrix{T}, x::AbstractVector{S}) where {T, S} = Base.invoke_in_world(delay_initialize(), *, A, x)
*(A::AbstractMatrix, B::AbstractMatrix) = Base.invoke_in_world(delay_initialize(), *, A, B)
\(a::AbstractVector, b::AbstractArray) = Base.invoke_in_world(delay_initialize(), \, a, b)
^(i::Irrational{:ℯ}, A::AbstractMatrix) = Base.invoke_in_world(delay_initialize(), ^, i, A)

acos(A::AbstractMatrix) = Base.invoke_in_world(delay_initialize(), acos, A)
acosh(A::AbstractMatrix) = Base.invoke_in_world(delay_initialize(), acosh, A)
acot(A::AbstractMatrix{T}) where T = Base.invoke_in_world(delay_initialize(), acot, A)
acoth(A::AbstractMatrix{T}) where T = Base.invoke_in_world(delay_initialize(), acoth, A)
acsc(A::AbstractMatrix{T}) where T = Base.invoke_in_world(delay_initialize(), acsc, A)
acsch(A::AbstractMatrix{T}) where T = Base.invoke_in_world(delay_initialize(), acsch, A)
asec(A::AbstractMatrix{T}) where T = Base.invoke_in_world(delay_initialize(), asec, A)
asech(A::AbstractMatrix{T}) where T= Base.invoke_in_world(delay_initialize(), asech, A)
asin(A::AbstractMatrix) = Base.invoke_in_world(delay_initialize(), asin, A)
asinh(A::AbstractMatrix) = Base.invoke_in_world(delay_initialize(), asinh, A)
atan(A::AbstractMatrix) = Base.invoke_in_world(delay_initialize(), atan, A)
atanh(A::AbstractMatrix) = Base.invoke_in_world(delay_initialize(), atanh, A)
# cis(A::AbstractMatrix{<:Union{Float32, Float64, Int16, Int32, Int64, Int8, UInt16, UInt32, UInt64, UInt8, Complex{<:Union{Float32, Float64, Int16, Int32, Int64, Int8, UInt16, UInt32, UInt64, UInt8}}, Rational{<:Union{Float32, Float64, Int16, Int32, Int64, Int8, UInt16, UInt32, UInt64, UInt8}}}}) @ LinearAlgebra ~/.julia/juliaup/julia-1.10.0-beta2+0.x64.linux.gnu/share/julia/stdlib/v1.10/LinearAlgebra/src/dense.jl:616
cis(A::AbstractMatrix) = Base.invoke_in_world(delay_initialize(), cis, A)
cos(A::AbstractMatrix{<:Complex}) = Base.invoke_in_world(delay_initialize(), cos, A)
cos(A::AbstractMatrix{<:Real}) = Base.invoke_in_world(delay_initialize(), cos, A)
cosh(A::AbstractMatrix) = Base.invoke_in_world(delay_initialize(), cosh, A)
cot(A::AbstractMatrix{T}) where T = Base.invoke_in_world(delay_initialize(), cot, A)
coth(A::AbstractMatrix{T}) where T = Base.invoke_in_world(delay_initialize(), coth, A)
csc(A::AbstractMatrix{T}) where T = Base.invoke_in_world(delay_initialize(), csc, A)
csch(A::AbstractMatrix{T}) where T = Base.invoke_in_world(delay_initialize(), csch, A)


exp(A::AbstractMatrix) = Base.invoke_in_world(delay_initialize(), exp, A)
inv(A::AbstractMatrix{T}) where T = Base.invoke_in_world(delay_initialize(), inv, A)
isone(A::AbstractMatrix) = Base.invoke_in_world(delay_initialize(), isone, A)
kron(a::BitMatrix, b::BitMatrix) = Base.invoke_in_world(delay_initialize(), kron, a, b)
kron(a::BitVector, b::BitVector) = Base.invoke_in_world(delay_initialize(), kron, a, b)
kron(a::AbstractVector{T}, b::AbstractVector{S}) where {T, S} = Base.invoke_in_world(delay_initialize(), kron, a, b)
kron!(R::BitMatrix, a::BitMatrix, b::BitMatrix) = Base.invoke_in_world(delay_initialize(), kron!, R, a, B)
kron!(R::BitVector, a::BitVector, b::BitVector) = Base.invoke_in_world(delay_initialize(), kron!, R, a, b)
kron!(c::AbstractVector, a::AbstractVector, b::AbstractVector) = Base.invoke_in_world(delay_initialize(), kron!, c, a, b)
log(A::AbstractMatrix) = Base.invoke_in_world(delay_initialize(), log, A)
sec(A::AbstractMatrix{T}) where T = Base.invoke_in_world(delay_initialize(), sec, A)
sech(A::AbstractMatrix{T}) where T = Base.invoke_in_world(delay_initialize(), sech, A)
sin(A::AbstractMatrix{<:Complex}) = Base.invoke_in_world(delay_initialize(), sin, A)
sin(A::AbstractMatrix{<:Real}) = Base.invoke_in_world(delay_initialize(), sin, A)
sincos(A::AbstractMatrix{<:Real}) = Base.invoke_in_world(delay_initialize(), sincos, A)
sincos(A::AbstractMatrix{<:Complex}) = Base.invoke_in_world(delay_initialize(), sincos, A)
sinh(A::AbstractMatrix) = Base.invoke_in_world(delay_initialize(), sinh, A)
sqrt(A::AbstractMatrix{T}) where T<:Union{Real, Complex} = Base.invoke_in_world(delay_initialize(), sqrt, A)
tan(A::AbstractMatrix) = Base.invoke_in_world(delay_initialize(), tan, A)
tanh(A::AbstractMatrix) = Base.invoke_in_world(delay_initialize(), tanh, A)
transpose(B::Union{BitMatrix, BitVector}) = Base.invoke_in_world(delay_initialize(), transpose, B)
transpose(a::AbstractArray) = Base.invoke_in_world(delay_initialize(), transpose, a)
# isapprox(x::AbstractArray, y::AbstractArray; atol, rtol, nans, norm) = Base.invoke_in_world(delay_initialize(), isapprox, x, y; atol, rtol, nans, norm)
isapprox(x::AbstractArray, y::AbstractArray; kwargs...) = Base.invoke_in_world(delay_initialize(), isapprox, x, y; kwargs...)

end

for name in names(LinearAlgebra, imported=true)
func = getglobal(LinearAlgebra, name)
if func isa Function
@eval Base.Docs.getdoc(::typeof($func)) = (LinearAlgebra.delay_initialize(); nothing)
end
end

function delete_stubs(mod)
function delete(m)
ccall(:jl_push_newly_deleted, Cvoid, (Any,), m)
ccall(:jl_method_table_disable_incremental, Cvoid, (Any, Any), Base.get_methodtable(m), m)
end

for name in names(mod, imported=true)
if name == :delay_initialize
continue
end
obj = getglobal(mod, name)
if obj isa Function
for m in Base.methods(obj, mod)
delete(m)
end
end
end
for m in Base.methods(Core.kwcall, mod)
delete(m)
end
end

end
11 changes: 0 additions & 11 deletions base/sysimg.jl
Original file line number Diff line number Diff line change
Expand Up @@ -28,18 +28,7 @@ let
stdlibs = [
# No dependencies
:FileWatching, # used by loading.jl -- implicit assumption that init runs
:Libdl, # Transitive through LinAlg
:Artifacts, # Transitive through LinAlg
:SHA, # transitive through Random
:Sockets, # used by stream.jl

# Transitive through LingAlg
# OpenBLAS_jll
# libblastrampoline_jll

# 1-depth packages
:LinearAlgebra, # Commits type-piracy and GEMM
:Random, # Can't be removed due to rand being exported by Base
]
# PackageCompiler can filter out stdlibs so it can be empty
maxlen = maximum(textwidth.(string.(stdlibs)); init=0)
Expand Down
1 change: 1 addition & 0 deletions doc/src/devdocs/locks.md
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ The following is a leaf lock (level 2), and only acquires level 1 locks (safepoi
> * Module->lock
> * JLDebuginfoPlugin::PluginMutex
> * newly_inferred_mutex
> * newly_deleted_mutex

The following is a level 3 lock, which can only acquire level 1 or level 2 locks internally:

Expand Down
3 changes: 2 additions & 1 deletion src/clangsa/GCChecker.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1438,7 +1438,8 @@ bool GCChecker::evalCall(const CallEvent &Call, CheckerContext &C) const {
} else if (name == "JL_GC_PUSH1" || name == "JL_GC_PUSH2" ||
name == "JL_GC_PUSH3" || name == "JL_GC_PUSH4" ||
name == "JL_GC_PUSH5" || name == "JL_GC_PUSH6" ||
name == "JL_GC_PUSH7" || name == "JL_GC_PUSH8") {
name == "JL_GC_PUSH7" || name == "JL_GC_PUSH8" ||
name == "JL_GC_PUSH9") {
ProgramStateRef State = C.getState();
// Transform slots to roots, transform values to rooted
unsigned NumArgs = CE->getNumArgs();
Expand Down
20 changes: 16 additions & 4 deletions src/gf.c
Original file line number Diff line number Diff line change
Expand Up @@ -1858,9 +1858,9 @@ static jl_typemap_entry_t *do_typemap_search(jl_methtable_t *mt JL_PROPAGATES_RO
}
#endif

static void jl_method_table_invalidate(jl_methtable_t *mt, jl_typemap_entry_t *methodentry, size_t max_world)
static void jl_method_table_invalidate(jl_methtable_t *mt, jl_typemap_entry_t *methodentry, size_t max_world, int tracked)
{
if (jl_options.incremental && jl_generating_output())
if (!tracked && jl_options.incremental && jl_generating_output())
jl_error("Method deletion is not possible during Module precompile.");
jl_method_t *method = methodentry->func.method;
assert(!method->is_for_opaque_closure);
Expand Down Expand Up @@ -1917,10 +1917,22 @@ JL_DLLEXPORT void jl_method_table_disable(jl_methtable_t *mt, jl_method_t *metho
JL_LOCK(&mt->writelock);
// Narrow the world age on the method to make it uncallable
size_t world = jl_atomic_fetch_add(&jl_world_counter, 1);
jl_method_table_invalidate(mt, methodentry, world);
jl_method_table_invalidate(mt, methodentry, world, 0);
JL_UNLOCK(&mt->writelock);
}

JL_DLLEXPORT void jl_method_table_disable_incremental(jl_methtable_t *mt, jl_method_t *method)
{
jl_typemap_entry_t *methodentry = do_typemap_search(mt, method);
JL_LOCK(&mt->writelock);
// Narrow the world age on the method to make it uncallable
// size_t world = jl_atomic_load_acquire(&jl_world_counter);
size_t world = jl_atomic_fetch_add(&jl_world_counter, 1);
jl_method_table_invalidate(mt, methodentry, world, 1);
JL_UNLOCK(&mt->writelock);
}


static int jl_type_intersection2(jl_value_t *t1, jl_value_t *t2, jl_value_t **isect JL_REQUIRE_ROOTED_SLOT, jl_value_t **isect2 JL_REQUIRE_ROOTED_SLOT)
{
*isect2 = NULL;
Expand Down Expand Up @@ -2011,7 +2023,7 @@ JL_DLLEXPORT void jl_method_table_insert(jl_methtable_t *mt, jl_method_t *method
oldvalue = (jl_value_t*)replaced;
invalidated = 1;
method_overwrite(newentry, replaced->func.method);
jl_method_table_invalidate(mt, replaced, max_world);
jl_method_table_invalidate(mt, replaced, max_world, 0);
}
else {
jl_method_t *const *d;
Expand Down
2 changes: 2 additions & 0 deletions src/init.c
Original file line number Diff line number Diff line change
Expand Up @@ -709,6 +709,7 @@ static void jl_set_io_wait(int v)
extern jl_mutex_t jl_modules_mutex;
extern jl_mutex_t precomp_statement_out_lock;
extern jl_mutex_t newly_inferred_mutex;
extern jl_mutex_t newly_deleted_mutex;
extern jl_mutex_t global_roots_lock;

static void restore_fp_env(void)
Expand All @@ -726,6 +727,7 @@ static void init_global_mutexes(void) {
JL_MUTEX_INIT(&jl_modules_mutex, "jl_modules_mutex");
JL_MUTEX_INIT(&precomp_statement_out_lock, "precomp_statement_out_lock");
JL_MUTEX_INIT(&newly_inferred_mutex, "newly_inferred_mutex");
JL_MUTEX_INIT(&newly_deleted_mutex, "newly_deleted_mutex");
JL_MUTEX_INIT(&global_roots_lock, "global_roots_lock");
JL_MUTEX_INIT(&jl_codegen_lock, "jl_codegen_lock");
JL_MUTEX_INIT(&typecache_lock, "typecache_lock");
Expand Down
2 changes: 2 additions & 0 deletions src/jl_exported_funcs.inc
Original file line number Diff line number Diff line change
Expand Up @@ -323,6 +323,7 @@
XX(jl_method_instance_add_backedge) \
XX(jl_method_table_add_backedge) \
XX(jl_method_table_disable) \
XX(jl_method_table_disable_incremental) \
XX(jl_method_table_for) \
XX(jl_method_table_insert) \
XX(jl_methtable_lookup) \
Expand Down Expand Up @@ -353,6 +354,7 @@
XX(jl_new_method_table) \
XX(jl_new_method_uninit) \
XX(jl_new_module) \
XX(jl_module_world) \
XX(jl_new_primitivetype) \
XX(jl_new_struct) \
XX(jl_new_structt) \
Expand Down
8 changes: 8 additions & 0 deletions src/julia.h
Original file line number Diff line number Diff line change
Expand Up @@ -932,6 +932,7 @@ extern void JL_GC_PUSH4(void *, void *, void *, void *) JL_NOTSAFEPOINT;
extern void JL_GC_PUSH5(void *, void *, void *, void *, void *) JL_NOTSAFEPOINT;
extern void JL_GC_PUSH7(void *, void *, void *, void *, void *, void *, void *) JL_NOTSAFEPOINT;
extern void JL_GC_PUSH8(void *, void *, void *, void *, void *, void *, void *, void *) JL_NOTSAFEPOINT;
extern void JL_GC_PUSH9(void *, void *, void *, void *, void *, void *, void *, void *, void *) JL_NOTSAFEPOINT;
extern void _JL_GC_PUSHARGS(jl_value_t **, size_t) JL_NOTSAFEPOINT;
// This is necessary, because otherwise the analyzer considers this undefined
// behavior and terminates the exploration
Expand Down Expand Up @@ -974,6 +975,9 @@ extern void JL_GC_POP() JL_NOTSAFEPOINT;
#define JL_GC_PUSH8(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8) \
void *__gc_stkf[] = {(void*)JL_GC_ENCODE_PUSH(8), jl_pgcstack, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8}; \
jl_pgcstack = (jl_gcframe_t*)__gc_stkf;
#define JL_GC_PUSH9(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9) \
void *__gc_stkf[] = {(void*)JL_GC_ENCODE_PUSH(9), jl_pgcstack, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9}; \
jl_pgcstack = (jl_gcframe_t*)__gc_stkf;


#define JL_GC_PUSHARGS(rts_var,n) \
Expand Down Expand Up @@ -1737,6 +1741,7 @@ extern JL_DLLIMPORT jl_module_t *jl_base_module JL_GLOBALLY_ROOTED;
extern JL_DLLIMPORT jl_module_t *jl_top_module JL_GLOBALLY_ROOTED;
extern JL_DLLIMPORT jl_module_t *jl_libdl_module JL_GLOBALLY_ROOTED;
JL_DLLEXPORT jl_module_t *jl_new_module(jl_sym_t *name, jl_module_t *parent);
JL_DLLEXPORT size_t jl_module_world(jl_module_t *m);
JL_DLLEXPORT void jl_set_module_nospecialize(jl_module_t *self, int on);
JL_DLLEXPORT void jl_set_module_optlevel(jl_module_t *self, int lvl);
JL_DLLEXPORT int jl_get_module_optlevel(jl_module_t *m);
Expand Down Expand Up @@ -1900,6 +1905,9 @@ JL_DLLEXPORT jl_value_t *jl_restore_incremental(const char *fname, jl_array_t *d

JL_DLLEXPORT void jl_set_newly_inferred(jl_value_t *newly_inferred);
JL_DLLEXPORT void jl_push_newly_inferred(jl_value_t *ci);
JL_DLLEXPORT void jl_method_table_disable_incremental(jl_methtable_t *mt, jl_method_t *m);
JL_DLLEXPORT void jl_set_newly_deleted(jl_value_t *newly_deleted);
JL_DLLEXPORT void jl_push_newly_deleted(jl_value_t *m);
JL_DLLEXPORT void jl_write_compiler_output(void);

// parsing
Expand Down
5 changes: 5 additions & 0 deletions src/module.c
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,11 @@ uint32_t jl_module_next_counter(jl_module_t *m)
return jl_atomic_fetch_add(&m->counter, 1);
}

JL_DLLEXPORT size_t jl_module_world(jl_module_t *m)
{
return m->primary_world;
}

JL_DLLEXPORT jl_value_t *jl_f_new_module(jl_sym_t *name, uint8_t std_imports, uint8_t default_names)
{
// TODO: should we prohibit this during incremental compilation?
Expand Down
Loading