Skip to content
Draft
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
30 changes: 28 additions & 2 deletions base/boot.jl
Original file line number Diff line number Diff line change
Expand Up @@ -370,12 +370,38 @@
msg::AbstractString
end

struct BoundsErrorSummary
desc::Union{Nothing,String}
size::Union{Nothing, Tuple{Vararg{Int}}}
atype::DataType
function BoundsErrorSummary(a)
# try to get a summary of `a` here now rather than capturing it for later inspection,
# in order to allow compiler analyses or optimization passes to assume the invariant
# that this `BoundsError` doesn't escape `a` when it is a certain primitive object
# that they can reason about
atype = typeof(a)
desc = nothing
size = nothing
if isa(a, Array)
size = a.size
elseif isa(a, GenericMemory)
size = (a.length,)
elseif isa(a, Tuple)
size = (nfields(a),)
elseif isdefined(Main, :Base)
desc = Main.Base.summary(a)::String
else
desc = "bootstraping threw `BoundsError` with unknown type $(atype). Please define `BoundsErrorSummary` on this type"

Check warning on line 394 in base/boot.jl

View workflow job for this annotation

GitHub Actions / Check for new typos

perhaps "bootstraping" should be "bootstrapping".
end
new(desc, size, atype)
end
end
struct BoundsError <: Exception
a::Any
i::Any
BoundsError() = new()
BoundsError(@nospecialize(a)) = (@noinline; new(a))
BoundsError(@nospecialize(a), i) = (@noinline; new(a,i))
BoundsError(a) = new(BoundsErrorSummary(a))
BoundsError(a, i) = new(BoundsErrorSummary(a),i)
end
struct DivideError <: Exception end
struct OutOfMemoryError <: Exception end
Expand Down
18 changes: 17 additions & 1 deletion base/errorshow.jl
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,23 @@ function showerror(io::IO, ex::BoundsError)
print(io, "BoundsError")
if isdefined(ex, :a)
print(io, ": attempt to access ")
summary(io, ex.a)
a = ex.a
if isa(a, Core.BoundsErrorSummary)
if isnothing(a.desc)
if length(a.size) == 1
print(io, only(a.size))
print(io, "-element ")
else
join(io, a.size, '×')
print(io, ' ')
end
print(io, a.atype)
else
print(io, a.desc)
end
else
summary(io, a)
end
if isdefined(ex, :i)
print(io, " at index [")
if ex.i isa AbstractRange
Expand Down
7 changes: 0 additions & 7 deletions src/codegen.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -812,12 +812,6 @@ static const auto jlhasnofield_func = new JuliaFunction<>{
PointerType::get(JuliaType::get_jlvalue_ty(C), AddressSpace::CalleeRooted)}, false); },
get_attrs_noreturn,
};
static const auto jlboundserrorv_func = new JuliaFunction<TypeFnContextAndSizeT>{
XSTR(jl_bounds_error_ints),
[](LLVMContext &C, Type *T_size) { return FunctionType::get(getVoidTy(C),
{PointerType::get(JuliaType::get_jlvalue_ty(C), AddressSpace::CalleeRooted), PointerType::getUnqual(T_size->getContext()), T_size}, false); },
get_attrs_noreturn,
};
static const auto jlboundserror_func = new JuliaFunction<TypeFnContextAndSizeT>{
XSTR(jl_bounds_error_int),
[](LLVMContext &C, Type *T_size) { return FunctionType::get(getVoidTy(C),
Expand Down Expand Up @@ -9973,7 +9967,6 @@ static void init_jit_functions(void)
add_named_global(jlthrow_func, &jl_throw);
add_named_global(jlundefvarerror_func, &jl_undefined_var_error);
add_named_global(jlhasnofield_func, &jl_has_no_field_error);
add_named_global(jlboundserrorv_func, &jl_bounds_error_ints);
add_named_global(jlboundserror_func, &jl_bounds_error_int);
add_named_global(jlvboundserror_func, &jl_bounds_error_tuple_int);
add_named_global(jluboundserror_func, &jl_bounds_error_unboxed_int);
Expand Down
1 change: 0 additions & 1 deletion src/jl_exported_funcs.inc
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,6 @@
XX(jl_boundp) \
XX(jl_bounds_error) \
XX(jl_bounds_error_int) \
XX(jl_bounds_error_ints) \
XX(jl_bounds_error_tuple_int) \
XX(jl_bounds_error_unboxed_int) \
XX(jl_bounds_error_v) \
Expand Down
2 changes: 0 additions & 2 deletions src/julia.h
Original file line number Diff line number Diff line change
Expand Up @@ -2173,8 +2173,6 @@ JL_DLLEXPORT void JL_NORETURN jl_bounds_error_int(jl_value_t *v JL_MAYBE_UNROOTE
JL_DLLEXPORT void JL_NORETURN jl_bounds_error_tuple_int(jl_value_t **v,
size_t nv, size_t i);
JL_DLLEXPORT void JL_NORETURN jl_bounds_error_unboxed_int(void *v, jl_value_t *vt, size_t i);
JL_DLLEXPORT void JL_NORETURN jl_bounds_error_ints(jl_value_t *v JL_MAYBE_UNROOTED,
size_t *idxs, size_t nidxs);

#define JL_NARGS(fname, min, max) \
if (nargs < min) jl_too_few_args(#fname, min); \
Expand Down
14 changes: 0 additions & 14 deletions src/rtutils.c
Original file line number Diff line number Diff line change
Expand Up @@ -216,20 +216,6 @@ JL_DLLEXPORT void JL_NORETURN jl_bounds_error_int(jl_value_t *v JL_MAYBE_UNROOTE
jl_throw(jl_new_struct((jl_datatype_t*)jl_boundserror_type, v, t));
}

JL_DLLEXPORT void JL_NORETURN jl_bounds_error_ints(jl_value_t *v JL_MAYBE_UNROOTED,
size_t *idxs, size_t nidxs)
{
size_t i;
jl_value_t *t = NULL;
JL_GC_PUSH2(&v, &t); // root arguments so the caller doesn't need to
t = (jl_value_t*)jl_alloc_svec(nidxs);
for (i = 0; i < nidxs; i++) {
jl_svecset(t, i, jl_box_long(idxs[i]));
}
t = jl_f_tuple(NULL, jl_svec_data(t), nidxs);
jl_throw(jl_new_struct((jl_datatype_t*)jl_boundserror_type, v, t));
}

JL_DLLEXPORT void jl_typeassert(jl_value_t *x, jl_value_t *t)
{
if (!jl_isa(x,t))
Expand Down
3 changes: 2 additions & 1 deletion test/boundscheck_exec.jl
Original file line number Diff line number Diff line change
Expand Up @@ -261,7 +261,8 @@ end
getindex_40281(v, a, b, c) = @inbounds getindex(v, a, b, c)
llvm_40281 = sprint((io, args...) -> code_llvm(io, args...; optimize=true), getindex_40281, Tuple{Array{Float64, 3}, Int, UInt8, Int})
if bc_opt == bc_default || bc_opt == bc_off
@test !occursin("call void @ijl_bounds_error_ints", llvm_40281)
@test !occursin("call void @ijl_bounds_error_int", llvm_40281)
@test !occursin("call void @j_throw_boundserror", llvm_40281)
end

# Given this is a sub-processed test file, not using @testsets avoids
Expand Down
Loading