Skip to content
Open
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
18 changes: 15 additions & 3 deletions base/mpfr.jl
Original file line number Diff line number Diff line change
Expand Up @@ -104,15 +104,23 @@ mutable struct BigFloat <: AbstractFloat
#NAN_KIND = Cint(0)
#ccall((:mpfr_custom_init_set,:libmpfr), Cvoid, (Ref{BigFloat}, Cint, Clong, Ptr{Limb}), z, NAN_KIND, prec, d)
#return z
return new(prec, sign, exp, pointer(d), d)
p = pointer(d)
if UInt(p) & 1 == 1
p += (sizeof(Int) - 1)
end
return new(prec, sign, exp, p, d)
end

function BigFloat(; precision::Integer=DEFAULT_PRECISION[])
precision < 1 && throw(DomainError(precision, "`precision` cannot be less than 1."))
nb = ccall((:mpfr_custom_get_size,:libmpfr), Csize_t, (Clong,), precision)
nb = (nb + Core.sizeof(Limb) - 1) ÷ Core.sizeof(Limb) # align to number of Limb allocations required for this
#d = Vector{Limb}(undef, nb)
d = _string_n(nb * Core.sizeof(Limb))
sz = nb * Core.sizeof(Limb)
if sz < 128
sz = min(sz+sizeof(Int)-1, 128)
end
d = _string_n(sz)
EXP_NAN = Clong(1) - Clong(typemax(Culong) >> 1)
return _BigFloat(Clong(precision), one(Cint), EXP_NAN, d) # +NAN
end
Expand All @@ -131,7 +139,11 @@ Base.unsafe_convert(::Type{Ref{BigFloat}}, x::Ptr{BigFloat}) = x
@inline function Base.unsafe_convert(::Type{Ref{BigFloat}}, x::Ref{BigFloat})
x = x[]
if x.d == C_NULL
x.d = pointer(x._d)
p = pointer(x._d)
if UInt(p) & 1 == 1
p += (sizeof(Int) - 1)
end
x.d = p
end
return convert(Ptr{BigFloat}, Base.pointer_from_objref(x))
end
Expand Down
2 changes: 1 addition & 1 deletion base/summarysize.jl
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@ end
function (ss::SummarySize)(obj::String)
key = ccall(:jl_value_ptr, Ptr{Cvoid}, (Any,), obj)
haskey(ss.seen, key) ? (return 0) : (ss.seen[key] = true)
return Core.sizeof(Int) + Core.sizeof(obj)
return Int(pointer(obj) - key) + Core.sizeof(obj)
end

function (ss::SummarySize)(obj::DataType)
Expand Down
36 changes: 19 additions & 17 deletions src/array.c
Original file line number Diff line number Diff line change
Expand Up @@ -495,7 +495,13 @@ JL_DLLEXPORT jl_value_t *jl_array_to_string(jl_array_t *a)
jl_value_t *o = jl_array_data_owner(a);
if (jl_is_string(o)) {
a->flags.isshared = 1;
*(size_t*)o = len;
if (*(size_t*)o & 0x1) {
*(size_t*)o = (len << 1) | 0x1;
}
else {
assert(len < 128);
*(int8_t*)o = len << 1;
}
a->nrows = 0;
#ifdef STORE_ARRAY_LEN
a->length = 0;
Expand All @@ -512,30 +518,26 @@ JL_DLLEXPORT jl_value_t *jl_array_to_string(jl_array_t *a)
return jl_pchar_to_string((const char*)jl_array_data(a), len);
}

JL_DLLEXPORT jl_value_t *jl_pchar_to_string(const char *str, size_t len)
JL_DLLEXPORT jl_value_t *jl_alloc_string(size_t len)
{
size_t sz = sizeof(size_t) + len + 1; // add space for trailing \nul protector and size
if (sz < len) // overflow
jl_throw(jl_memory_exception);
if (len == 0)
return jl_an_empty_string;
// add space for trailing \nul protector and size
size_t sz = len + 1 + (len < 128 ? 1 : sizeof(size_t));
if (sz < len) // overflow
jl_throw(jl_memory_exception);
jl_value_t *s = jl_gc_alloc_(jl_get_ptls_states(), sz, jl_string_type); // force inlining
*(size_t*)s = len;
memcpy((char*)s + sizeof(size_t), str, len);
((char*)s + sizeof(size_t))[len] = 0;
// store `len >= 128` in the low bit so we know how big the length field is
*(size_t*)s = (len << 1) | (len >= 128);
jl_string_data(s)[len] = 0;
return s;
}

JL_DLLEXPORT jl_value_t *jl_alloc_string(size_t len)
JL_DLLEXPORT jl_value_t *jl_pchar_to_string(const char *str, size_t len)
{
size_t sz = sizeof(size_t) + len + 1; // add space for trailing \nul protector and size
if (sz < len) // overflow
jl_throw(jl_memory_exception);
if (len == 0)
return jl_an_empty_string;
jl_value_t *s = jl_gc_alloc_(jl_get_ptls_states(), sz, jl_string_type); // force inlining
*(size_t*)s = len;
((char*)s + sizeof(size_t))[len] = 0;
jl_value_t *s = jl_alloc_string(len);
if (len > 0)
memcpy(jl_string_data(s), str, len);
return s;
}

Expand Down
5 changes: 5 additions & 0 deletions src/ccall.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1692,6 +1692,11 @@ static jl_cgval_t emit_ccall(jl_codectx_t &ctx, jl_value_t **args, size_t nargs)
// The inbounds gep makes it more clear to LLVM that the resulting value is not
// a null pointer.
auto strp = ctx.builder.CreateConstInBoundsGEP1_32(T_prjlvalue, obj, 1);
auto bptr = emit_bitcast(ctx, obj, T_pint8);
Value *len = tbaa_decorate(tbaa_const, ctx.builder.CreateAlignedLoad(T_int8, bptr, Align(sizeof(size_t))));
Value *lowbit = ctx.builder.CreateTrunc(len, T_int1);
Value *bytegep = ctx.builder.CreateConstInBoundsGEP1_32(T_int8, bptr, 1);
strp = ctx.builder.CreateSelect(lowbit, emit_bitcast(ctx, strp, T_pint8), bytegep);
strp = ctx.builder.CreatePtrToInt(strp, T_size);
JL_GC_POP();
return mark_or_box_ccall_result(ctx, strp, retboxed, rt, unionall, static_rt);
Expand Down
44 changes: 26 additions & 18 deletions src/codegen.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3150,33 +3150,41 @@ static bool emit_builtin_call(jl_codectx_t &ctx, jl_cgval_t *ret, jl_value_t *f,
const jl_cgval_t &obj = argv[1];
jl_datatype_t *sty = (jl_datatype_t*)jl_unwrap_unionall(obj.typ);
assert(jl_string_type->mutabl);
if (sty == jl_string_type || sty == jl_simplevector_type) {
if (sty == jl_string_type) {
if (obj.constant) {
size_t sz;
if (sty == jl_string_type) {
sz = jl_string_len(obj.constant);
}
else {
sz = (1 + jl_svec_len(obj.constant)) * sizeof(void*);
}
sz = jl_string_len(obj.constant);
*ret = mark_julia_type(ctx, ConstantInt::get(T_size, sz), false, jl_long_type);
return true;
}
// String and SimpleVector's length fields have the same layout
auto ptr = emit_bitcast(ctx, boxed(ctx, obj), T_psize);
Value *len = tbaa_decorate(tbaa_const, ctx.builder.CreateAlignedLoad(T_size, ptr, Align(sizeof(size_t))));
MDBuilder MDB(jl_LLVMContext);
if (sty == jl_simplevector_type) {
auto rng = MDB.createRange(
V_size0, ConstantInt::get(T_size, INTPTR_MAX / sizeof(void*) - 1));
cast<LoadInst>(len)->setMetadata(LLVMContext::MD_range, rng);
len = ctx.builder.CreateMul(len, ConstantInt::get(T_size, sizeof(void*)));
len = ctx.builder.CreateAdd(len, ConstantInt::get(T_size, sizeof(void*)));
}
else {
auto rng = MDB.createRange(V_size0, ConstantInt::get(T_size, INTPTR_MAX));
cast<LoadInst>(len)->setMetadata(LLVMContext::MD_range, rng);
auto rng = MDB.createRange(V_size0, ConstantInt::get(T_size, INTPTR_MAX));
cast<LoadInst>(len)->setMetadata(LLVMContext::MD_range, rng);
Value *lowbit = ctx.builder.CreateTrunc(len, T_int1);
Value *shifted = ctx.builder.CreateLShr(len, ConstantInt::get(T_size, 1));
len = ctx.builder.CreateSelect(lowbit, shifted,
ctx.builder.CreateLShr(ctx.builder.CreateAnd(len, ConstantInt::get(T_size, 0xff)),
ConstantInt::get(T_size, 1)));
*ret = mark_julia_type(ctx, len, false, jl_long_type);
return true;
}
else if (sty == jl_simplevector_type) {
if (obj.constant) {
size_t sz;
sz = (1 + jl_svec_len(obj.constant)) * sizeof(void*);
*ret = mark_julia_type(ctx, ConstantInt::get(T_size, sz), false, jl_long_type);
return true;
}
auto ptr = emit_bitcast(ctx, boxed(ctx, obj), T_psize);
Value *len = tbaa_decorate(tbaa_const, ctx.builder.CreateAlignedLoad(T_size, ptr, Align(sizeof(size_t))));
MDBuilder MDB(jl_LLVMContext);
auto rng = MDB.createRange(
V_size0, ConstantInt::get(T_size, INTPTR_MAX / sizeof(void*) - 1));
cast<LoadInst>(len)->setMetadata(LLVMContext::MD_range, rng);
len = ctx.builder.CreateMul(len, ConstantInt::get(T_size, sizeof(void*)));
len = ctx.builder.CreateAdd(len, ConstantInt::get(T_size, sizeof(void*)));
*ret = mark_julia_type(ctx, len, false, jl_long_type);
return true;
}
Expand Down
7 changes: 4 additions & 3 deletions src/gc.c
Original file line number Diff line number Diff line change
Expand Up @@ -2700,7 +2700,7 @@ mark: {
goto obj8_loaded;
}
else if (vt == jl_string_type) {
size_t dtsz = jl_string_len(new_obj) + sizeof(size_t) + 1;
size_t dtsz = jl_string_obj_size(new_obj);
if (update_meta)
gc_setmark(ptls, o, bits, dtsz);
else if (foreign_alloc)
Expand Down Expand Up @@ -3530,7 +3530,7 @@ jl_value_t *jl_gc_realloc_string(jl_value_t *s, size_t sz)
size_t len = jl_string_len(s);
if (sz <= len) return s;
jl_taggedvalue_t *v = jl_astaggedvalue(s);
size_t strsz = len + sizeof(size_t) + 1;
size_t strsz = jl_string_obj_size(s);
if (strsz <= GC_MAX_SZCLASS ||
// TODO: because of issue #17971 we can't resize old objects
gc_marked(v->bits.gc)) {
Expand Down Expand Up @@ -3558,7 +3558,8 @@ jl_value_t *jl_gc_realloc_string(jl_value_t *s, size_t sz)
newbig->age = 0;
gc_big_object_link(newbig, &ptls->heap.big_objects);
jl_value_t *snew = jl_valueof(&newbig->header);
*(size_t*)snew = sz;
assert(sz >= 128);
*(size_t*)snew = (sz << 1) | 0x1;
return snew;
}

Expand Down
19 changes: 17 additions & 2 deletions src/julia.h
Original file line number Diff line number Diff line change
Expand Up @@ -1013,8 +1013,23 @@ STATIC_INLINE void jl_array_uint8_set(void *a, size_t i, uint8_t x) JL_NOTSAFEPO
// get a pointer to the data in a datatype
#define jl_data_ptr(v) ((jl_value_t**)v)

#define jl_string_data(s) ((char*)s + sizeof(void*))
#define jl_string_len(s) (*(size_t*)s)
STATIC_INLINE char *jl_string_data(jl_value_t *s) JL_NOTSAFEPOINT
{
int8_t b = *(int8_t*)s;
if (b & 0x1)
return (char*)s + sizeof(void*);
else
return (char*)s + 1;
}
STATIC_INLINE size_t jl_string_len(jl_value_t *s) JL_NOTSAFEPOINT
{
size_t sz = *(size_t*)s;
if (sz & 0x1)
return sz >> 1;
else
return (sz & 0xff) >> 1;
}
#define jl_string_obj_size(s) (jl_string_len(s) + ((*(int8_t*)s & 0x1) ? sizeof(size_t) : 1) + 1)

#define jl_gf_mtable(f) (((jl_datatype_t*)jl_typeof(f))->name->mt)
#define jl_gf_name(f) (jl_gf_mtable(f)->name)
Expand Down
1 change: 0 additions & 1 deletion test/ccall.jl
Original file line number Diff line number Diff line change
Expand Up @@ -1352,7 +1352,6 @@ let r = Ref{Any}("123456789")
@test Ptr{Cvoid}(pa) != pv
@test unsafe_load(pa) === r[]
@test unsafe_load(Ptr{Ptr{Cvoid}}(pa)) === pv
@test unsafe_load(Ptr{Int}(pv)) === length(r[])
end
end

Expand Down
2 changes: 1 addition & 1 deletion test/compiler/codegen.jl
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@ if opt_level > 0
@test !occursin(" call ", get_llvm(jl_string_ptr, Tuple{String}))
# Make sure `Core.sizeof` call is inlined
s = "aaa"
@test jl_string_ptr(s) == pointer_from_objref(s) + sizeof(Int)
@test jl_string_ptr(s) == pointer_from_objref(s) + 1
# String
test_loads_no_call(get_llvm(core_sizeof, Tuple{String}), [Iptr])
# String
Expand Down