コード例 #1
0
ファイル: typemap.c プロジェクト: antonblanchard/julia
static jl_typemap_entry_t *jl_typemap_node_assoc_exact(jl_typemap_entry_t *ml, jl_value_t **args, size_t n)
{
    while (ml != (void*)jl_nothing) {
        size_t lensig = jl_datatype_nfields(ml->sig);
        if (lensig == n || (ml->va && lensig <= n+1)) {
            int ismatch;
            if (ml->simplesig != (void*)jl_nothing &&
                    !sig_match_simple(args, n, jl_svec_data(ml->simplesig->parameters), 0,
                        jl_datatype_nfields(ml->simplesig)))
                ismatch = 0;
            else if (ml->isleafsig)
                ismatch = sig_match_leaf(args, jl_svec_data(ml->sig->parameters), n);
            else if (ml->issimplesig)
                ismatch = sig_match_simple(args, n, jl_svec_data(ml->sig->parameters), ml->va, lensig);
            else
                ismatch = jl_tuple_subtype(args, n, ml->sig, 1);

            if (ismatch) {
                size_t i, l;
                for (i = 0, l = jl_svec_len(ml->guardsigs); i < l; i++) {
                    // checking guard entries require a more
                    // expensive subtype check, since guard entries added for ANY might be
                    // abstract. this fixed issue #12967.
                    if (jl_tuple_subtype(args, n, (jl_tupletype_t*)jl_svecref(ml->guardsigs, i), 1)) {
                        break;
                    }
                }
                if (i == l)
                    return ml;
            }
        }
        ml = ml->next;
    }
    return NULL;
}
コード例 #2
0
ファイル: builtins.c プロジェクト: giordano/julia
// See comment above for an explanation of NOINLINE.
static int NOINLINE compare_fields(jl_value_t *a, jl_value_t *b, jl_datatype_t *dt)
{
    size_t nf = jl_datatype_nfields(dt);
    for (size_t f=0; f < nf; f++) {
        size_t offs = jl_field_offset(dt, f);
        char *ao = (char*)jl_data_ptr(a) + offs;
        char *bo = (char*)jl_data_ptr(b) + offs;
        int eq;
        if (jl_field_isptr(dt, f)) {
            jl_value_t *af = *(jl_value_t**)ao;
            jl_value_t *bf = *(jl_value_t**)bo;
            if (af == bf) eq = 1;
            else if (af==NULL || bf==NULL) eq = 0;
            else eq = jl_egal(af, bf);
        }
        else {
            jl_datatype_t *ft = (jl_datatype_t*)jl_field_type(dt, f);
            if (!ft->layout->haspadding) {
                eq = bits_equal(ao, bo, jl_field_size(dt, f));
            }
            else {
                assert(jl_datatype_nfields(ft) > 0);
                eq = compare_fields((jl_value_t*)ao, (jl_value_t*)bo, ft);
            }
        }
        if (!eq) return 0;
    }
    return 1;
}
コード例 #3
0
ファイル: typemap.c プロジェクト: antonblanchard/julia
jl_typemap_entry_t *jl_typemap_assoc_exact(union jl_typemap_t ml_or_cache, jl_value_t **args, size_t n, int8_t offs)
{
    // NOTE: This function is a huge performance hot spot!!
    if (jl_typeof(ml_or_cache.unknown) == (jl_value_t*)jl_typemap_level_type) {
        jl_typemap_level_t *cache = ml_or_cache.node;
        if (n > offs) {
            jl_value_t *a1 = args[offs];
            jl_value_t *ty = (jl_value_t*)jl_typeof(a1);
            assert(jl_is_datatype(ty));
            if (ty == (jl_value_t*)jl_datatype_type && cache->targ != (void*)jl_nothing) {
                ml_or_cache = mtcache_hash_lookup(cache->targ, a1, 1, offs);
                jl_typemap_entry_t *ml = jl_typemap_assoc_exact(ml_or_cache, args, n, offs+1);
                if (ml) return ml;
            }
            if (cache->arg1 != (void*)jl_nothing) {
                ml_or_cache = mtcache_hash_lookup(cache->arg1, ty, 0, offs);
                if (jl_typeof(ml_or_cache.unknown) == (jl_value_t*)jl_typemap_entry_type &&
                        ml_or_cache.leaf->simplesig == (void*)jl_nothing && offs < 2 && n > 1) {
                    jl_value_t *a0 = args[1-offs];
                    jl_value_t *t0 = (jl_value_t*)jl_typeof(a0);
                    if (ml_or_cache.leaf->next==(void*)jl_nothing && n==2 && jl_datatype_nfields(ml_or_cache.leaf->sig)==2 &&
                        jl_tparam(ml_or_cache.leaf->sig, 1 - offs) == t0)
                        return ml_or_cache.leaf;
                    if (n==3) {
                        // some manually-unrolled common special cases
                        jl_value_t *a2 = args[2];
                        if (!jl_is_tuple(a2)) {  // issue #6426
                            jl_typemap_entry_t *mn = ml_or_cache.leaf;
                            if (jl_datatype_nfields(mn->sig)==3 &&
                                jl_tparam(mn->sig,1-offs)==t0 &&
                                jl_tparam(mn->sig,2)==(jl_value_t*)jl_typeof(a2))
                                return mn;
                            mn = mn->next;
                            if (mn!=(void*)jl_nothing && jl_datatype_nfields(mn->sig)==3 &&
                                jl_tparam(mn->sig,1-offs)==t0 &&
                                jl_tparam(mn->sig,2)==(jl_value_t*)jl_typeof(a2))
                                return mn;
                        }
                    }
                }
                jl_typemap_entry_t *ml = jl_typemap_assoc_exact(ml_or_cache, args, n, offs+1);
                if (ml) return ml;
            }
        }
        jl_typemap_entry_t *ml = jl_typemap_node_assoc_exact(cache->linear, args, n);
        if (ml) return ml;
        return jl_typemap_assoc_exact(cache->any, args, n, offs+1);
    }
    else {
        return jl_typemap_node_assoc_exact(ml_or_cache.leaf, args, n);
    }
}
コード例 #4
0
ファイル: datatype.c プロジェクト: helgee/julia
JL_DLLEXPORT jl_value_t *jl_new_structv(jl_datatype_t *type, jl_value_t **args,
                                        uint32_t na)
{
    jl_ptls_t ptls = jl_get_ptls_states();
    if (type->instance != NULL) return type->instance;
    size_t nf = jl_datatype_nfields(type);
    jl_value_t *jv = jl_gc_alloc(ptls, jl_datatype_size(type), type);
    JL_GC_PUSH1(&jv);
    for (size_t i = 0; i < na; i++) {
        jl_value_t *ft = jl_field_type(type, i);
        if (!jl_isa(args[i], ft))
            jl_type_error("new", ft, args[i]);
        jl_set_nth_field(jv, i, args[i]);
    }
    for(size_t i=na; i < nf; i++) {
        if (jl_field_isptr(type, i)) {
            *(jl_value_t**)((char*)jl_data_ptr(jv)+jl_field_offset(type,i)) = NULL;

        } else {
            jl_value_t *ft = jl_field_type(type, i);
            if (jl_is_uniontype(ft)) {
                uint8_t *psel = &((uint8_t *)jv)[jl_field_offset(type, i) + jl_field_size(type, i) - 1];
                *psel = 0;
            }
        }
    }
    JL_GC_POP();
    return jv;
}
コード例 #5
0
ファイル: alloc.c プロジェクト: pallmagnusson/julia
void jl_compute_field_offsets(jl_datatype_t *st)
{
    size_t sz = 0, alignm = 1;
    int ptrfree = 1;

    for(size_t i=0; i < jl_datatype_nfields(st); i++) {
        jl_value_t *ty = jl_field_type(st, i);
        size_t fsz, al;
        if (jl_isbits(ty) && jl_is_leaf_type(ty)) {
            fsz = jl_datatype_size(ty);
            al = ((jl_datatype_t*)ty)->alignment;
            st->fields[i].isptr = 0;
        }
        else {
            fsz = sizeof(void*);
            if (fsz > MAX_ALIGN)
                fsz = MAX_ALIGN;
            al = fsz;
            st->fields[i].isptr = 1;
            ptrfree = 0;
        }
        if (al != 0) {
            sz = LLT_ALIGN(sz, al);
            if (al > alignm)
                alignm = al;
        }
        st->fields[i].offset = sz;
        st->fields[i].size = fsz;
        sz += fsz;
    }
    st->alignment = alignm;
    st->size = LLT_ALIGN(sz, alignm);
    st->pointerfree = ptrfree && !st->abstract;
}
コード例 #6
0
ファイル: alloc.c プロジェクト: StefanKarpinski/julia
// Determine if homogeneous tuple with fields of type t will have
// a special alignment beyond normal Julia rules.
// Return special alignment if one exists, 0 if normal alignment rules hold.
// A non-zero result *must* match the LLVM rules for a vector type <nfields x t>.
// For sake of Ahead-Of-Time (AOT) compilation, this routine has to work
// without LLVM being available.
unsigned jl_special_vector_alignment(size_t nfields, jl_value_t *t) {
    if (!jl_is_vecelement_type(t))
        return 0;
    // LLVM 3.7 and 3.8 either crash or generate wrong code for many
    // SIMD vector sizes N. It seems the rule is that N can have at
    // most 2 non-zero bits. (This is true at least for N<=100.) See
    // also <https://llvm.org/bugs/show_bug.cgi?id=27708>.
    size_t mask = nfields;
    // See e.g.
    // <https://graphics.stanford.edu/%7Eseander/bithacks.html> for an
    // explanation of this bit-counting algorithm.
    mask &= mask-1;             // clear least-significant 1 if present
    mask &= mask-1;             // clear another 1
    if (mask)
        return 0;               // nfields has more than two 1s
    assert(jl_datatype_nfields(t)==1);
    jl_value_t *ty = jl_field_type(t, 0);
    if (!jl_is_bitstype(ty))
        // LLVM requires that a vector element be a primitive type.
        // LLVM allows pointer types as vector elements, but until a
        // motivating use case comes up for Julia, we reject pointers.
        return 0;
    size_t elsz = jl_datatype_size(ty);
    if (elsz>8 || (1<<elsz & 0x116) == 0)
        // Element size is not 1, 2, 4, or 8.
        return 0;
    size_t size = nfields*elsz;
    // LLVM's alignment rule for vectors seems to be to round up to
    // a power of two, even if that's overkill for the target hardware.
    size_t alignment=1;
    for( ; size>alignment; alignment*=2 )
        continue;
    return alignment;
}
コード例 #7
0
ファイル: builtins.c プロジェクト: Evizero/julia
JL_DLLEXPORT int jl_egal(jl_value_t *a, jl_value_t *b)
{
    // warning: a,b may NOT have been gc-rooted by the caller
    if (a == b)
        return 1;
    jl_datatype_t *dt = (jl_datatype_t*)jl_typeof(a);
    if (dt != (jl_datatype_t*)jl_typeof(b))
        return 0;
    if (dt == jl_simplevector_type)
        return compare_svec((jl_svec_t*)a, (jl_svec_t*)b);
    if (dt == jl_datatype_type) {
        jl_datatype_t *dta = (jl_datatype_t*)a;
        jl_datatype_t *dtb = (jl_datatype_t*)b;
        return dta->name == dtb->name && compare_svec(dta->parameters, dtb->parameters);
    }
    if (dt == jl_string_type) {
        size_t l = jl_string_len(a);
        if (jl_string_len(b) != l)
            return 0;
        return !memcmp(jl_string_data(a), jl_string_data(b), l);
    }
    if (dt->mutabl)
        return 0;
    size_t sz = jl_datatype_size(dt);
    if (sz == 0)
        return 1;
    size_t nf = jl_datatype_nfields(dt);
    if (nf == 0)
        return bits_equal(jl_data_ptr(a), jl_data_ptr(b), sz);
    if (dt == jl_unionall_type)
        return egal_types(a, b, NULL);
    return compare_fields(a, b, dt);
}
コード例 #8
0
ファイル: alloc.c プロジェクト: davidamaro/julia
// Determine if homogeneous tuple with fields of type t will have
// a special alignment beyond normal Julia rules.
// Return special alignment if one exists, 0 if normal alignment rules hold.
// A non-zero result *must* match the LLVM rules for a vector type <nfields x t>.
// For sake of Ahead-Of-Time (AOT) compilation, this routine has to work
// without LLVM being available.
unsigned jl_special_vector_alignment(size_t nfields, jl_value_t *t) {
    if (!is_vecelement_type(t))
        return 0;
    if (nfields>16 || (1<<nfields & 0x1157C) == 0)
        // Number of fields is not 2, 3, 4, 5, 6, 8, 10, 12, or 16.
        return 0;
    assert(jl_datatype_nfields(t)==1);
    jl_value_t *ty = jl_field_type(t, 0);
    if( !jl_is_bitstype(ty) )
        // LLVM requires that a vector element be a primitive type.
        // LLVM allows pointer types as vector elements, but until a
        // motivating use case comes up for Julia, we reject pointers.
        return 0;
    size_t elsz = jl_datatype_size(ty);
    if (elsz>8 || (1<<elsz & 0x116) == 0)
        // Element size is not 1, 2, 4, or 8.
        return 0;
    size_t size = nfields*elsz;
    // LLVM's alignment rule for vectors seems to be to round up to
    // a power of two, even if that's overkill for the target hardware.
    size_t alignment=1;
    for( ; size>alignment; alignment*=2 )
        continue;
    return alignment;
}
コード例 #9
0
ファイル: typemap.c プロジェクト: mathcg/julia
// this is the general entry point for looking up a type in the cache
// (as a subtype, or with typeseq)
jl_typemap_entry_t *jl_typemap_assoc_by_type(union jl_typemap_t ml_or_cache, jl_tupletype_t *types, jl_svec_t **penv,
        int8_t subtype_inexact__sigseq_useenv, int8_t subtype, int8_t offs)
{
    if (jl_typeof(ml_or_cache.unknown) == (jl_value_t*)jl_typemap_level_type) {
        jl_typemap_level_t *cache = ml_or_cache.node;
        // called object is the primary key for constructors, otherwise first argument
        jl_value_t *ty = NULL;
        size_t l = jl_datatype_nfields(types);
        // compute the type at offset `offs` into `types`, which may be a Vararg
        if (l <= offs + 1) {
            ty = jl_tparam(types, l - 1);
            if (jl_is_vararg_type(ty))
                ty = jl_tparam0(ty);
            else if (l <= offs)
                ty = NULL;
        }
        else if (l > offs) {
            ty = jl_tparam(types, offs);
        }
        // If there is a type at offs, look in the optimized caches
        if (ty) {
            if (!subtype && jl_is_any(ty))
                return jl_typemap_assoc_by_type(cache->any, types, penv, subtype_inexact__sigseq_useenv, subtype, offs+1);
            if (cache->targ != (void*)jl_nothing && jl_is_type_type(ty)) {
                jl_value_t *a0 = jl_tparam0(ty);
                if (jl_is_datatype(a0)) {
                    union jl_typemap_t ml = mtcache_hash_lookup(cache->targ, a0, 1, offs);
                    if (ml.unknown != jl_nothing) {
                        jl_typemap_entry_t *li = jl_typemap_assoc_by_type(ml, types, penv,
                                subtype_inexact__sigseq_useenv, subtype, offs+1);
                        if (li) return li;
                    }
                }
            }
            if (cache->arg1 != (void*)jl_nothing && jl_is_datatype(ty)) {
                union jl_typemap_t ml = mtcache_hash_lookup(cache->arg1, ty, 0, offs);
                if (ml.unknown != jl_nothing) {
                    jl_typemap_entry_t *li = jl_typemap_assoc_by_type(ml, types, penv,
                            subtype_inexact__sigseq_useenv, subtype, offs+1);
                    if (li) return li;
                }
            }
        }
        // Always check the list (since offs doesn't always start at 0)
        if (subtype) {
            jl_typemap_entry_t *li = jl_typemap_assoc_by_type_(cache->linear, types, subtype_inexact__sigseq_useenv, penv);
            if (li) return li;
            return jl_typemap_assoc_by_type(cache->any, types, penv, subtype_inexact__sigseq_useenv, subtype, offs+1);
        }
        else {
            return jl_typemap_lookup_by_type_(cache->linear, types, subtype_inexact__sigseq_useenv);
        }
    }
    else {
        return subtype ?
            jl_typemap_assoc_by_type_(ml_or_cache.leaf, types, subtype_inexact__sigseq_useenv, penv) :
            jl_typemap_lookup_by_type_(ml_or_cache.leaf, types, subtype_inexact__sigseq_useenv);
    }
}
コード例 #10
0
ファイル: builtins.c プロジェクト: mschauer/julia
static uintptr_t jl_object_id_(jl_value_t *tv, jl_value_t *v)
{
    if (tv == (jl_value_t*)jl_sym_type)
        return ((jl_sym_t*)v)->hash;
    if (tv == (jl_value_t*)jl_simplevector_type)
        return hash_svec((jl_svec_t*)v);
    jl_datatype_t *dt = (jl_datatype_t*)tv;
    if (dt == jl_datatype_type) {
        jl_datatype_t *dtv = (jl_datatype_t*)v;
        // `name->wrapper` is cacheable even though it contains TypeVars
        // that don't have stable IDs.
        //if (jl_egal(dtv->name->wrapper, v))
        //    return bitmix(~dtv->name->hash, 0xaa5566aa);
        return bitmix(~dtv->name->hash, hash_svec(dtv->parameters));
    }
    if (dt == jl_typename_type)
        return ((jl_typename_t*)v)->hash;
#ifdef _P64
    if (v == jl_ANY_flag) return 0x31c472f68ee30bddULL;
#else
    if (v == jl_ANY_flag) return 0x8ee30bdd;
#endif
    if (dt == jl_string_type) {
#ifdef _P64
        return memhash_seed(jl_string_data(v), jl_string_len(v), 0xedc3b677);
#else
        return memhash32_seed(jl_string_data(v), jl_string_len(v), 0xedc3b677);
#endif
    }
    if (dt->mutabl) return inthash((uintptr_t)v);
    size_t sz = jl_datatype_size(tv);
    uintptr_t h = jl_object_id(tv);
    if (sz == 0) return ~h;
    size_t nf = jl_datatype_nfields(dt);
    if (nf == 0) {
        return bits_hash(jl_data_ptr(v), sz) ^ h;
    }
    for (size_t f=0; f < nf; f++) {
        size_t offs = jl_field_offset(dt, f);
        char *vo = (char*)jl_data_ptr(v) + offs;
        uintptr_t u;
        if (jl_field_isptr(dt, f)) {
            jl_value_t *f = *(jl_value_t**)vo;
            u = f==NULL ? 0 : jl_object_id(f);
        }
        else {
            jl_datatype_t *fieldtype = (jl_datatype_t*)jl_field_type(dt, f);
            assert(jl_is_datatype(fieldtype) && !fieldtype->abstract && !fieldtype->mutabl);
            if (fieldtype->layout->haspadding)
                u = jl_object_id_((jl_value_t*)fieldtype, (jl_value_t*)vo);
            else
                u = bits_hash(vo, jl_field_size(dt, f));
        }
        h = bitmix(h, u);
    }
    return h;
}
コード例 #11
0
ファイル: typemap.c プロジェクト: mathcg/julia
int jl_typemap_intersection_visitor(union jl_typemap_t map, int offs,
        struct typemap_intersection_env *closure)
{
    if (jl_typeof(map.unknown) == (jl_value_t*)jl_typemap_level_type) {
        jl_typemap_level_t *cache = map.node;
        jl_value_t *ty = NULL;
        size_t l = jl_datatype_nfields(closure->type);
        if (closure->va && l <= offs + 1) {
            ty = closure->va;
        }
        else if (l > offs) {
            ty = jl_tparam(closure->type, offs);
        }
        if (ty) {
            if (cache->targ != (void*)jl_nothing) {
                jl_value_t *typetype = jl_is_type_type(ty) ? jl_tparam0(ty) : NULL;
                if (typetype && !jl_has_typevars(typetype)) {
                    if (is_cache_leaf(typetype)) {
                        // direct lookup of leaf types
                        union jl_typemap_t ml = mtcache_hash_lookup(cache->targ, typetype, 1, offs);
                        if (ml.unknown != jl_nothing) {
                            if (!jl_typemap_intersection_visitor(ml, offs+1, closure)) return 0;
                        }
                    }
                }
                else {
                    // else an array scan is required to check subtypes
                    // first, fast-path: optimized pre-intersection test to see if `ty` could intersect with any Type
                    if (typetype || jl_type_intersection((jl_value_t*)jl_type_type, ty) != jl_bottom_type)
                        if (!jl_typemap_intersection_array_visitor(cache->targ, ty, 1, offs, closure)) return 0;
                }
            }
            if (cache->arg1 != (void*)jl_nothing) {
                if (is_cache_leaf(ty)) {
                    // direct lookup of leaf types
                    union jl_typemap_t ml = mtcache_hash_lookup(cache->arg1, ty, 0, offs);
                    if (ml.unknown != jl_nothing) {
                        if (!jl_typemap_intersection_visitor(ml, offs+1, closure)) return 0;
                    }
                }
                else {
                    // else an array scan is required to check subtypes
                    if (!jl_typemap_intersection_array_visitor(cache->arg1, ty, 0, offs, closure)) return 0;
                }
            }
        }
        if (!jl_typemap_intersection_node_visitor(map.node->linear, closure))
            return 0;
        if (ty)
            return jl_typemap_intersection_visitor(map.node->any, offs+1, closure);
        return 1;
    }
    else {
        return jl_typemap_intersection_node_visitor(map.leaf, closure);
    }
}
コード例 #12
0
ファイル: alloc.c プロジェクト: StefanKarpinski/julia
JL_DLLEXPORT jl_value_t *jl_get_nth_field(jl_value_t *v, size_t i)
{
    jl_datatype_t *st = (jl_datatype_t*)jl_typeof(v);
    assert(i < jl_datatype_nfields(st));
    size_t offs = jl_field_offset(st,i);
    if (jl_field_isptr(st,i)) {
        return *(jl_value_t**)((char*)v + offs);
    }
    return jl_new_bits(jl_field_type(st,i), (char*)v + offs);
}
コード例 #13
0
ファイル: abi_ppc64le.cpp プロジェクト: IntelLabs/julia
Type *preferred_llvm_type(jl_datatype_t *dt, bool isret) const override
{
    // Arguments are either scalar or passed by value
    size_t size = jl_datatype_size(dt);
    // don't need to change bitstypes
    if (!jl_datatype_nfields(dt))
        return NULL;
    // legalize this into [n x f32/f64]
    jl_datatype_t *ty0 = NULL;
    bool hva = false;
    int hfa = isHFA(dt, &ty0, &hva);
    if (hfa <= 8) {
        if (ty0 == jl_float32_type) {
            return ArrayType::get(T_float32, hfa);
        }
        else if (ty0 == jl_float64_type) {
            return ArrayType::get(T_float64, hfa);
        }
        else {
            jl_datatype_t *vecty = (jl_datatype_t*)jl_field_type(ty0, 0);
            assert(jl_is_datatype(vecty) && vecty->name == jl_vecelement_typename);
            jl_value_t *elemty = jl_tparam0(vecty);
            assert(jl_is_primitivetype(elemty));

            Type *ety = julia_type_to_llvm(elemty);
            Type *vty = VectorType::get(ety, jl_datatype_nfields(ty0));
            return ArrayType::get(vty, hfa);
        }
    }
    // rewrite integer-sized (non-HFA) struct to an array
    // the bitsize of the integer gives the desired alignment
    if (size > 8) {
        if (jl_datatype_align(dt) <= 8) {
            return ArrayType::get(T_int64, (size + 7) / 8);
        }
        else {
            Type *T_int128 = Type::getIntNTy(jl_LLVMContext, 128);
            return ArrayType::get(T_int128, (size + 15) / 16);
        }
    }
    return Type::getIntNTy(jl_LLVMContext, size * 8);
}
コード例 #14
0
ファイル: alloc.c プロジェクト: Blisse/julia
void jl_compute_field_offsets(jl_datatype_t *st)
{
    size_t sz = 0, alignm = 1;
    int ptrfree = 1;

    assert(0 <= st->fielddesc_type && st->fielddesc_type <= 2);

    uint64_t max_offset = (((uint64_t)1) <<
                           (1 << (3 + st->fielddesc_type))) - 1;
    uint64_t max_size = max_offset >> 1;

    for(size_t i=0; i < jl_datatype_nfields(st); i++) {
        jl_value_t *ty = jl_field_type(st, i);
        size_t fsz, al;
        if (jl_isbits(ty) && jl_is_leaf_type(ty)) {
            fsz = jl_datatype_size(ty);
            // Should never happen
            if (__unlikely(fsz > max_size))
                jl_throw(jl_overflow_exception);
            al = ((jl_datatype_t*)ty)->alignment;
            jl_field_setisptr(st, i, 0);
            if (((jl_datatype_t*)ty)->haspadding)
                st->haspadding = 1;
        }
        else {
            fsz = sizeof(void*);
            if (fsz > MAX_ALIGN)
                fsz = MAX_ALIGN;
            al = fsz;
            jl_field_setisptr(st, i, 1);
            ptrfree = 0;
        }
        if (al != 0) {
            size_t alsz = LLT_ALIGN(sz, al);
            if (sz & (al - 1))
                st->haspadding = 1;
            sz = alsz;
            if (al > alignm)
                alignm = al;
        }
        jl_field_setoffset(st, i, sz);
        jl_field_setsize(st, i, fsz);
        if (__unlikely(max_offset - sz < fsz))
            jl_throw(jl_overflow_exception);
        sz += fsz;
    }
    st->alignment = alignm;
    st->size = LLT_ALIGN(sz, alignm);
    if (st->size > sz)
        st->haspadding = 1;
    st->pointerfree = ptrfree && !st->abstract;
}
コード例 #15
0
ファイル: alloc.c プロジェクト: StefanKarpinski/julia
JL_DLLEXPORT jl_value_t *jl_new_struct(jl_datatype_t *type, ...)
{
    if (type->instance != NULL) return type->instance;
    va_list args;
    size_t nf = jl_datatype_nfields(type);
    va_start(args, type);
    jl_value_t *jv = newstruct(type);
    for(size_t i=0; i < nf; i++) {
        jl_set_nth_field(jv, i, va_arg(args, jl_value_t*));
    }
    va_end(args);
    return jv;
}
コード例 #16
0
ファイル: builtins.c プロジェクト: Evizero/julia
// See comment above for an explanation of NOINLINE.
static int NOINLINE compare_fields(jl_value_t *a, jl_value_t *b, jl_datatype_t *dt)
{
    size_t f, nf = jl_datatype_nfields(dt);
    for (f = 0; f < nf; f++) {
        size_t offs = jl_field_offset(dt, f);
        char *ao = (char*)jl_data_ptr(a) + offs;
        char *bo = (char*)jl_data_ptr(b) + offs;
        if (jl_field_isptr(dt, f)) {
            jl_value_t *af = *(jl_value_t**)ao;
            jl_value_t *bf = *(jl_value_t**)bo;
            if (af != bf) {
                if (af == NULL || bf == NULL)
                    return 0;
                if (!jl_egal(af, bf))
                    return 0;
            }
        }
        else {
            jl_datatype_t *ft = (jl_datatype_t*)jl_field_type(dt, f);
            if (jl_is_uniontype(ft)) {
                uint8_t asel = ((uint8_t*)ao)[jl_field_size(dt, f) - 1];
                uint8_t bsel = ((uint8_t*)bo)[jl_field_size(dt, f) - 1];
                if (asel != bsel)
                    return 0;
                ft = (jl_datatype_t*)jl_nth_union_component((jl_value_t*)ft, asel);
            }
            if (!ft->layout->haspadding) {
                if (!bits_equal(ao, bo, ft->size))
                    return 0;
            }
            else {
                assert(jl_datatype_nfields(ft) > 0);
                if (!compare_fields((jl_value_t*)ao, (jl_value_t*)bo, ft))
                    return 0;
            }
        }
    }
    return 1;
}
コード例 #17
0
ファイル: alloc.c プロジェクト: StefanKarpinski/julia
JL_DLLEXPORT jl_value_t *jl_get_nth_field_checked(jl_value_t *v, size_t i)
{
    jl_datatype_t *st = (jl_datatype_t*)jl_typeof(v);
    if (i >= jl_datatype_nfields(st))
        jl_bounds_error_int(v, i+1);
    size_t offs = jl_field_offset(st,i);
    if (jl_field_isptr(st,i)) {
        jl_value_t *fval = *(jl_value_t**)((char*)v + offs);
        if (fval == NULL)
            jl_throw(jl_undefref_exception);
        return fval;
    }
    return jl_new_bits(jl_field_type(st,i), (char*)v + offs);
}
コード例 #18
0
ファイル: alloc.c プロジェクト: pallmagnusson/julia
DLLEXPORT jl_value_t *jl_new_structv(jl_datatype_t *type, jl_value_t **args, uint32_t na)
{
    if (type->instance != NULL) return type->instance;
    size_t nf = jl_datatype_nfields(type);
    jl_value_t *jv = newstruct(type);
    for(size_t i=0; i < na; i++) {
        jl_set_nth_field(jv, i, args[i]);
    }
    for(size_t i=na; i < nf; i++) {
        if (type->fields[i].isptr)
            *(jl_value_t**)((char*)jl_data_ptr(jv)+jl_field_offset(type,i)) = NULL;
    }
    return jv;
}
コード例 #19
0
ファイル: typemap.c プロジェクト: antonblanchard/julia
// this is the general entry point for looking up a type in the cache
// (as a subtype, or with typeseq)
jl_typemap_entry_t *jl_typemap_assoc_by_type(union jl_typemap_t ml_or_cache, jl_tupletype_t *types, jl_svec_t **penv,
        int8_t subtype_inexact__sigseq_useenv, int8_t subtype, int8_t offs)
{
    if (jl_typeof(ml_or_cache.unknown) == (jl_value_t*)jl_typemap_level_type) {
        jl_typemap_level_t *cache = ml_or_cache.node;
        // called object is the primary key for constructors, otherwise first argument
        jl_value_t *ty = NULL;
        if (jl_datatype_nfields(types) > offs) {
            ty = jl_tparam(types, offs);
            if (cache->targ != (void*)jl_nothing && jl_is_type_type(ty)) {
                jl_value_t *a0 = jl_tparam0(ty);
                if (jl_is_datatype(a0)) {
                    union jl_typemap_t ml = mtcache_hash_lookup(cache->targ, a0, 1, offs);
                    if (ml.unknown != jl_nothing) {
                        jl_typemap_entry_t *li = jl_typemap_assoc_by_type(ml, types, penv,
                                subtype_inexact__sigseq_useenv, subtype, offs+1);
                        if (li) return li;
                    }
                }
            }
            if (cache->arg1 != (void*)jl_nothing && jl_is_datatype(ty)) {
                union jl_typemap_t ml = mtcache_hash_lookup(cache->arg1, ty, 0, offs);
                if (ml.unknown != jl_nothing) {
                    jl_typemap_entry_t *li = jl_typemap_assoc_by_type(ml, types, penv,
                            subtype_inexact__sigseq_useenv, subtype, offs+1);
                    if (li) return li;
                }
            }
        }
        if (subtype) {
            jl_typemap_entry_t *li = jl_typemap_assoc_by_type_(cache->linear, types, subtype_inexact__sigseq_useenv, penv);
            if (li) return li;
            return jl_typemap_assoc_by_type(cache->any, types, penv, subtype_inexact__sigseq_useenv, subtype, offs+1);
        }
        else {
            if (ty && jl_is_any(ty))
                return jl_typemap_assoc_by_type(cache->any, types, penv, subtype_inexact__sigseq_useenv, subtype, offs+1);
            else
                return jl_typemap_lookup_by_type_(cache->linear, types, subtype_inexact__sigseq_useenv);
        }
    }
    else {
        return subtype ?
            jl_typemap_assoc_by_type_(ml_or_cache.leaf, types, subtype_inexact__sigseq_useenv, penv) :
            jl_typemap_lookup_by_type_(ml_or_cache.leaf, types, subtype_inexact__sigseq_useenv);
    }
}
コード例 #20
0
ファイル: alloc.c プロジェクト: BrianSipple/julia
JL_DLLEXPORT jl_value_t *jl_new_structv(jl_datatype_t *type, jl_value_t **args,
                                        uint32_t na)
{
    jl_ptls_t ptls = jl_get_ptls_states();
    if (type->instance != NULL) return type->instance;
    size_t nf = jl_datatype_nfields(type);
    jl_value_t *jv = jl_gc_alloc(ptls, type->size, type);
    for(size_t i=0; i < na; i++) {
        jl_set_nth_field(jv, i, args[i]);
    }
    for(size_t i=na; i < nf; i++) {
        if (jl_field_isptr(type, i)) {
            *(jl_value_t**)((char*)jl_data_ptr(jv)+jl_field_offset(type,i)) = NULL;
        }
    }
    return jv;
}
コード例 #21
0
ファイル: datatype.c プロジェクト: helgee/julia
JL_DLLEXPORT jl_value_t *jl_get_nth_field(jl_value_t *v, size_t i)
{
    jl_datatype_t *st = (jl_datatype_t*)jl_typeof(v);
    assert(i < jl_datatype_nfields(st));
    size_t offs = jl_field_offset(st, i);
    if (jl_field_isptr(st, i)) {
        return *(jl_value_t**)((char*)v + offs);
    }
    jl_value_t *ty = jl_field_type(st, i);
    if (jl_is_uniontype(ty)) {
        uint8_t sel = ((uint8_t*)v)[offs + jl_field_size(st, i) - 1];
        ty = jl_nth_union_component(ty, sel);
        if (jl_is_datatype_singleton((jl_datatype_t*)ty))
            return ((jl_datatype_t*)ty)->instance;
    }
    return jl_new_bits(ty, (char*)v + offs);
}
コード例 #22
0
ファイル: typemap.c プロジェクト: DrGar/julia
static void jl_typemap_level_insert_(jl_typemap_level_t *cache, jl_typemap_entry_t *newrec, int8_t offs,
        const struct jl_typemap_info *tparams)
{
    if (jl_datatype_nfields(newrec->sig) > offs) {
        jl_value_t *t1 = jl_tparam(newrec->sig, offs);
        // if t1 != jl_typetype_type and the argument is Type{...}, this
        // method has specializations for singleton kinds and we use
        // the table indexed for that purpose.
        if (t1 != (jl_value_t*)jl_typetype_type && jl_is_type_type(t1)) {
            jl_value_t *a0 = jl_tparam0(t1);
            if (jl_typemap_array_insert_(&cache->targ, a0, newrec, (jl_value_t*)cache, 1, offs, tparams))
                return;
        }
        if (jl_typemap_array_insert_(&cache->arg1, t1, newrec, (jl_value_t*)cache, 0, offs, tparams))
            return;
    }
    jl_typemap_list_insert_(&cache->linear, (jl_value_t*)cache, newrec, tparams);
}
コード例 #23
0
ファイル: alloc.c プロジェクト: nanosoldier/julia
void jl_compute_field_offsets(jl_datatype_t *st)
{
    size_t sz = 0, alignm = 1;
    int ptrfree = 1;

    for(size_t i=0; i < jl_datatype_nfields(st); i++) {
        jl_value_t *ty = jl_field_type(st, i);
        size_t fsz, al;
        if (jl_isbits(ty) && jl_is_leaf_type(ty)) {
            fsz = jl_datatype_size(ty);
            if (__unlikely(fsz > JL_FIELD_MAX_SIZE))
                jl_throw(jl_overflow_exception);
            al = ((jl_datatype_t*)ty)->alignment;
            st->fields[i].isptr = 0;
            if (((jl_datatype_t*)ty)->haspadding)
                st->haspadding = 1;
        }
        else {
            fsz = sizeof(void*);
            if (fsz > MAX_ALIGN)
                fsz = MAX_ALIGN;
            al = fsz;
            st->fields[i].isptr = 1;
            ptrfree = 0;
        }
        if (al != 0) {
            size_t alsz = LLT_ALIGN(sz, al);
            if (alsz > sz)
                st->haspadding = 1;
            sz = alsz;
            if (al > alignm)
                alignm = al;
        }
        if (__unlikely(sz > JL_FIELD_MAX_OFFSET))
            jl_throw(jl_overflow_exception);
        st->fields[i].offset = sz;
        st->fields[i].size = fsz;
        sz += fsz;
    }
    st->alignment = alignm;
    st->size = LLT_ALIGN(sz, alignm);
    st->pointerfree = ptrfree && !st->abstract;
}
コード例 #24
0
ファイル: datatype.c プロジェクト: helgee/julia
JL_DLLEXPORT jl_value_t *jl_get_nth_field_checked(jl_value_t *v, size_t i)
{
    jl_datatype_t *st = (jl_datatype_t*)jl_typeof(v);
    if (i >= jl_datatype_nfields(st))
        jl_bounds_error_int(v, i + 1);
    size_t offs = jl_field_offset(st, i);
    if (jl_field_isptr(st, i)) {
        jl_value_t *fval = *(jl_value_t**)((char*)v + offs);
        if (fval == NULL)
            jl_throw(jl_undefref_exception);
        return fval;
    }
    jl_value_t *ty = jl_field_type(st, i);
    if (jl_is_uniontype(ty)) {
        size_t fsz = jl_field_size(st, i);
        uint8_t sel = ((uint8_t*)v)[offs + fsz - 1];
        ty = jl_nth_union_component(ty, sel);
        if (jl_is_datatype_singleton((jl_datatype_t*)ty))
            return ((jl_datatype_t*)ty)->instance;
    }
    return jl_new_bits(ty, (char*)v + offs);
}
コード例 #25
0
ファイル: typemap.c プロジェクト: mathcg/julia
static void jl_typemap_level_insert_(jl_typemap_level_t *cache, jl_typemap_entry_t *newrec, int8_t offs,
        const struct jl_typemap_info *tparams)
{
    size_t l = jl_datatype_nfields(newrec->sig);
    // compute the type at offset `offs` into `sig`, which may be a Vararg
    jl_value_t *t1 = NULL;
    int isva = 0;
    if (l <= offs + 1) {
        t1 = jl_tparam(newrec->sig, l - 1);
        if (jl_is_vararg_type(t1)) {
            isva = 1;
            t1 = jl_tparam0(t1);
        }
        else if (l <= offs) {
            t1 = NULL;
        }
    }
    else if (l > offs) {
        t1 = jl_tparam(newrec->sig, offs);
    }
    // If the type at `offs` is Any, put it in the Any list
    if (t1 && jl_is_any(t1))
        return jl_typemap_insert_generic(&cache->any, (jl_value_t*)cache, newrec, (jl_value_t*)jl_any_type, offs+1, tparams);
    // Don't put Varargs in the optimized caches (too hard to handle in lookup and bp)
    if (t1 && !isva) {
        // if t1 != jl_typetype_type and the argument is Type{...}, this
        // method has specializations for singleton kinds and we use
        // the table indexed for that purpose.
        if (t1 != (jl_value_t*)jl_typetype_type && jl_is_type_type(t1)) {
            jl_value_t *a0 = jl_tparam0(t1);
            if (jl_typemap_array_insert_(&cache->targ, a0, newrec, (jl_value_t*)cache, 1, offs, tparams))
                return;
        }
        if (jl_typemap_array_insert_(&cache->arg1, t1, newrec, (jl_value_t*)cache, 0, offs, tparams))
            return;
    }
    jl_typemap_list_insert_(&cache->linear, (jl_value_t*)cache, newrec, tparams);
}
コード例 #26
0
ファイル: builtins.c プロジェクト: giordano/julia
JL_DLLEXPORT int jl_egal(jl_value_t *a, jl_value_t *b)
{
    // warning: a,b may NOT have been gc-rooted by the caller
    if (a == b)
        return 1;
    jl_value_t *ta = (jl_value_t*)jl_typeof(a);
    if (ta != (jl_value_t*)jl_typeof(b))
        return 0;
    if (jl_is_svec(a))
        return compare_svec((jl_svec_t*)a, (jl_svec_t*)b);
    jl_datatype_t *dt = (jl_datatype_t*)ta;
    if (dt == jl_datatype_type) {
        jl_datatype_t *dta = (jl_datatype_t*)a;
        jl_datatype_t *dtb = (jl_datatype_t*)b;
        return dta->name == dtb->name && compare_svec(dta->parameters, dtb->parameters);
    }
    if (dt->mutabl) return 0;
    size_t sz = jl_datatype_size(dt);
    if (sz == 0) return 1;
    size_t nf = jl_datatype_nfields(dt);
    if (nf == 0)
        return bits_equal(jl_data_ptr(a), jl_data_ptr(b), sz);
    return compare_fields(a, b, dt);
}
コード例 #27
0
ファイル: rtutils.c プロジェクト: MatthiasJReisinger/julia
// `v` might be pointing to a field inlined in a structure therefore
// `jl_typeof(v)` may not be the same with `vt` and only `vt` should be
// used to determine the type of the value.
// This is necessary to make sure that this function doesn't allocate any
// memory through the Julia GC
static size_t jl_static_show_x_(JL_STREAM *out, jl_value_t *v, jl_datatype_t *vt,
                                struct recur_list *depth)
{
    size_t n = 0;
    if ((uintptr_t)vt < 4096U) {
        n += jl_printf(out, "<?#%p::%p>", (void*)v, (void*)vt);
    }
    else if ((uintptr_t)v < 4096U) {
        n += jl_printf(out, "<?#%p::", (void*)v);
        n += jl_static_show_x(out, (jl_value_t*)vt, depth);
        n += jl_printf(out, ">");
    }
    else if (vt == jl_method_type) {
        jl_method_t *m = (jl_method_t*)v;
        n += jl_static_show_x(out, (jl_value_t*)m->module, depth);
        n += jl_printf(out, ".%s(...)", jl_symbol_name(m->name));
    }
    else if (vt == jl_method_instance_type) {
        jl_method_instance_t *li = (jl_method_instance_t*)v;
        if (jl_is_method(li->def.method)) {
            jl_method_t *m = li->def.method;
            n += jl_static_show_x(out, (jl_value_t*)m->module, depth);
            if (li->specTypes) {
                n += jl_printf(out, ".");
                n += jl_show_svec(out, ((jl_datatype_t*)jl_unwrap_unionall(li->specTypes))->parameters,
                                  jl_symbol_name(m->name), "(", ")");
            }
            else {
                n += jl_printf(out, ".%s(?)", jl_symbol_name(m->name));
            }
        }
        else {
            n += jl_static_show_x(out, (jl_value_t*)li->def.module, depth);
            n += jl_printf(out, ".<toplevel thunk> -> ");
            n += jl_static_show_x(out, li->inferred, depth);
        }
    }
    else if (vt == jl_simplevector_type) {
        n += jl_show_svec(out, (jl_svec_t*)v, "svec", "(", ")");
    }
    else if (vt == jl_datatype_type) {
        jl_datatype_t *dv = (jl_datatype_t*)v;
        jl_sym_t *globname = dv->name->mt != NULL ? dv->name->mt->name : NULL;
        int globfunc = 0;
        if (globname && !strchr(jl_symbol_name(globname), '#') &&
            !strchr(jl_symbol_name(globname), '@') && dv->name->module &&
            jl_binding_resolved_p(dv->name->module, globname)) {
            jl_binding_t *b = jl_get_binding(dv->name->module, globname);
            if (b && jl_typeof(b->value) == v)
                globfunc = 1;
        }
        jl_sym_t *sym = globfunc ? globname : dv->name->name;
        char *sn = jl_symbol_name(sym);
        int hidden = !globfunc && strchr(sn, '#');
        size_t i = 0;
        int quote = 0;
        if (hidden) {
            n += jl_printf(out, "getfield(");
        }
        else if (globfunc) {
            n += jl_printf(out, "typeof(");
        }
        if (dv->name->module != jl_core_module || !jl_module_exports_p(jl_core_module, sym)) {
            n += jl_static_show_x(out, (jl_value_t*)dv->name->module, depth);
            if (!hidden) {
                n += jl_printf(out, ".");
                if (globfunc && !jl_id_start_char(u8_nextchar(sn, &i))) {
                    n += jl_printf(out, ":(");
                    quote = 1;
                }
            }
        }
        if (hidden) {
            n += jl_printf(out, ", Symbol(\"");
            n += jl_printf(out, "%s", sn);
            n += jl_printf(out, "\"))");
        }
        else {
            n += jl_printf(out, "%s", sn);
            if (globfunc) {
                n += jl_printf(out, ")");
                if (quote)
                    n += jl_printf(out, ")");
            }
        }
        if (dv->parameters && (jl_value_t*)dv != dv->name->wrapper &&
            (jl_has_free_typevars(v) ||
             (jl_value_t*)dv != (jl_value_t*)jl_tuple_type)) {
            size_t j, tlen = jl_nparams(dv);
            if (tlen > 0) {
                n += jl_printf(out, "{");
                for (j = 0; j < tlen; j++) {
                    jl_value_t *p = jl_tparam(dv,j);
                    n += jl_static_show_x(out, p, depth);
                    if (j != tlen-1)
                        n += jl_printf(out, ", ");
                }
                n += jl_printf(out, "}");
            }
            else if (dv->name == jl_tuple_typename) {
                n += jl_printf(out, "{}");
            }
        }
    }
    else if (vt == jl_intrinsic_type) {
        int f = *(uint32_t*)jl_data_ptr(v);
        n += jl_printf(out, "#<intrinsic #%d %s>", f, jl_intrinsic_name(f));
    }
    else if (vt == jl_int64_type) {
        n += jl_printf(out, "%" PRId64, *(int64_t*)v);
    }
    else if (vt == jl_int32_type) {
        n += jl_printf(out, "%" PRId32, *(int32_t*)v);
    }
    else if (vt == jl_int16_type) {
        n += jl_printf(out, "%" PRId16, *(int16_t*)v);
    }
    else if (vt == jl_int8_type) {
        n += jl_printf(out, "%" PRId8, *(int8_t*)v);
    }
    else if (vt == jl_uint64_type) {
        n += jl_printf(out, "0x%016" PRIx64, *(uint64_t*)v);
    }
    else if (vt == jl_uint32_type) {
        n += jl_printf(out, "0x%08" PRIx32, *(uint32_t*)v);
    }
    else if (vt == jl_uint16_type) {
        n += jl_printf(out, "0x%04" PRIx16, *(uint16_t*)v);
    }
    else if (vt == jl_uint8_type) {
        n += jl_printf(out, "0x%02" PRIx8, *(uint8_t*)v);
    }
    else if (jl_is_cpointer_type((jl_value_t*)vt)) {
#ifdef _P64
        n += jl_printf(out, "0x%016" PRIx64, *(uint64_t*)v);
#else
        n += jl_printf(out, "0x%08" PRIx32, *(uint32_t*)v);
#endif
    }
    else if (vt == jl_float32_type) {
        n += jl_printf(out, "%gf", *(float*)v);
    }
    else if (vt == jl_float64_type) {
        n += jl_printf(out, "%g", *(double*)v);
    }
    else if (vt == jl_bool_type) {
        n += jl_printf(out, "%s", *(uint8_t*)v ? "true" : "false");
    }
    else if ((jl_value_t*)vt == jl_typeof(jl_nothing)) {
        n += jl_printf(out, "nothing");
    }
    else if (vt == jl_string_type) {
        n += jl_printf(out, "\"");
        jl_uv_puts(out, jl_string_data(v), jl_string_len(v)); n += jl_string_len(v);
        n += jl_printf(out, "\"");
    }
    else if (v == jl_bottom_type) {
        n += jl_printf(out, "Union{}");
    }
    else if (vt == jl_uniontype_type) {
        n += jl_printf(out, "Union{");
        while (jl_is_uniontype(v)) {
            // tail-recurse on b to flatten the printing of the Union structure in the common case
            n += jl_static_show_x(out, ((jl_uniontype_t*)v)->a, depth);
            n += jl_printf(out, ", ");
            v = ((jl_uniontype_t*)v)->b;
        }
        n += jl_static_show_x(out, v, depth);
        n += jl_printf(out, "}");
    }
    else if (vt == jl_unionall_type) {
        jl_unionall_t *ua = (jl_unionall_t*)v;
        n += jl_static_show_x(out, ua->body, depth);
        n += jl_printf(out, " where ");
        n += jl_static_show_x(out, (jl_value_t*)ua->var, depth->prev);
    }
    else if (vt == jl_tvar_type) {
        // show type-var bounds only if they aren't going to be printed by UnionAll later
        jl_tvar_t *var = (jl_tvar_t*)v;
        struct recur_list *p;
        int showbounds = 1;
        for (p = depth; p != NULL; p = p->prev) {
            if (jl_is_unionall(p->v) && ((jl_unionall_t*)p->v)->var == var) {
                showbounds = 0;
                break;
            }
        }
        jl_value_t *lb = var->lb, *ub = var->ub;
        if (showbounds && lb != jl_bottom_type) {
            // show type-var lower bound if it is defined
            int ua = jl_is_unionall(lb);
            if (ua)
                n += jl_printf(out, "(");
            n += jl_static_show_x(out, lb, depth);
            if (ua)
                n += jl_printf(out, ")");
            n += jl_printf(out, "<:");
        }
        n += jl_printf(out, "%s", jl_symbol_name(var->name));
        if (showbounds && (ub != (jl_value_t*)jl_any_type || lb != jl_bottom_type)) {
            // show type-var upper bound if it is defined, or if we showed the lower bound
            int ua = jl_is_unionall(ub);
            n += jl_printf(out, "<:");
            if (ua)
                n += jl_printf(out, "(");
            n += jl_static_show_x(out, ub, depth);
            if (ua)
                n += jl_printf(out, ")");
        }
    }
    else if (vt == jl_module_type) {
        jl_module_t *m = (jl_module_t*)v;
        if (m->parent != m && m->parent != jl_main_module) {
            n += jl_static_show_x(out, (jl_value_t*)m->parent, depth);
            n += jl_printf(out, ".");
        }
        n += jl_printf(out, "%s", jl_symbol_name(m->name));
    }
    else if (vt == jl_sym_type) {
        char *sn = jl_symbol_name((jl_sym_t*)v);
        int quoted = !jl_is_identifier(sn) && jl_operator_precedence(sn) == 0;
        if (quoted)
            n += jl_printf(out, "Symbol(\"");
        else
            n += jl_printf(out, ":");
        n += jl_printf(out, "%s", sn);
        if (quoted)
            n += jl_printf(out, "\")");
    }
    else if (vt == jl_ssavalue_type) {
        n += jl_printf(out, "SSAValue(%" PRIuPTR ")",
                       (uintptr_t)((jl_ssavalue_t*)v)->id);
    }
    else if (vt == jl_globalref_type) {
        n += jl_static_show_x(out, (jl_value_t*)jl_globalref_mod(v), depth);
        n += jl_printf(out, ".%s", jl_symbol_name(jl_globalref_name(v)));
    }
    else if (vt == jl_labelnode_type) {
        n += jl_printf(out, "%" PRIuPTR ":", jl_labelnode_label(v));
    }
    else if (vt == jl_gotonode_type) {
        n += jl_printf(out, "goto %" PRIuPTR, jl_gotonode_label(v));
    }
    else if (vt == jl_quotenode_type) {
        jl_value_t *qv = *(jl_value_t**)v;
        if (!jl_is_symbol(qv)) {
            n += jl_printf(out, "quote ");
        }
        else {
            n += jl_printf(out, ":(");
        }
        n += jl_static_show_x(out, qv, depth);
        if (!jl_is_symbol(qv)) {
            n += jl_printf(out, " end");
        }
        else {
            n += jl_printf(out, ")");
        }
    }
    else if (vt == jl_newvarnode_type) {
        n += jl_printf(out, "<newvar ");
        n += jl_static_show_x(out, *(jl_value_t**)v, depth);
        n += jl_printf(out, ">");
    }
    else if (vt == jl_linenumbernode_type) {
        n += jl_printf(out, "#= ");
        n += jl_static_show_x(out, jl_linenode_file(v), depth);
        n += jl_printf(out, ":%" PRIuPTR " =#", jl_linenode_line(v));
    }
    else if (vt == jl_expr_type) {
        jl_expr_t *e = (jl_expr_t*)v;
        if (e->head == assign_sym && jl_array_len(e->args) == 2) {
            n += jl_static_show_x(out, jl_exprarg(e,0), depth);
            n += jl_printf(out, " = ");
            n += jl_static_show_x(out, jl_exprarg(e,1), depth);
        }
        else {
            char sep = ' ';
            if (e->head == body_sym)
                sep = '\n';
            n += jl_printf(out, "Expr(:%s", jl_symbol_name(e->head));
            size_t i, len = jl_array_len(e->args);
            for (i = 0; i < len; i++) {
                n += jl_printf(out, ",%c", sep);
                n += jl_static_show_x(out, jl_exprarg(e,i), depth);
            }
            n += jl_printf(out, ")::");
            n += jl_static_show_x(out, e->etype, depth);
        }
    }
    else if (jl_is_array_type(vt)) {
        n += jl_static_show_x(out, (jl_value_t*)vt, depth);
        n += jl_printf(out, "[");
        size_t j, tlen = jl_array_len(v);
        jl_array_t *av = (jl_array_t*)v;
        jl_datatype_t *el_type = (jl_datatype_t*)jl_tparam0(vt);
        int nlsep = 0;
        if (av->flags.ptrarray) {
            // print arrays with newlines, unless the elements are probably small
            for (j = 0; j < tlen; j++) {
                jl_value_t *p = jl_array_ptr_ref(av, j);
                if (p != NULL && (uintptr_t)p >= 4096U) {
                    jl_value_t *p_ty = jl_typeof(p);
                    if ((uintptr_t)p_ty >= 4096U) {
                        if (!jl_isbits(p_ty)) {
                            nlsep = 1;
                            break;
                        }
                    }
                }
            }
        }
        if (nlsep && tlen > 1)
            n += jl_printf(out, "\n  ");
        for (j = 0; j < tlen; j++) {
            if (av->flags.ptrarray) {
                n += jl_static_show_x(out, jl_array_ptr_ref(v, j), depth);
            }
            else {
                char *ptr = ((char*)av->data) + j * av->elsize;
                n += jl_static_show_x_(out, (jl_value_t*)ptr, el_type, depth);
            }
            if (j != tlen - 1)
                n += jl_printf(out, nlsep ? ",\n  " : ", ");
        }
        n += jl_printf(out, "]");
    }
    else if (vt == jl_loaderror_type) {
        n += jl_printf(out, "LoadError(at ");
        n += jl_static_show_x(out, *(jl_value_t**)v, depth);
        // Access the field directly to avoid allocation
        n += jl_printf(out, " line %" PRIdPTR, ((intptr_t*)v)[1]);
        n += jl_printf(out, ": ");
        n += jl_static_show_x(out, ((jl_value_t**)v)[2], depth);
        n += jl_printf(out, ")");
    }
    else if (vt == jl_errorexception_type) {
        n += jl_printf(out, "ErrorException(");
        n += jl_static_show_x(out, *(jl_value_t**)v, depth);
        n += jl_printf(out, ")");
    }
    else if (jl_is_datatype(vt)) {
        int istuple = jl_is_tuple_type(vt);
        if (!istuple)
            n += jl_static_show_x(out, (jl_value_t*)vt, depth);
        n += jl_printf(out, "(");
        size_t nb = jl_datatype_size(vt);
        size_t tlen = jl_datatype_nfields(vt);
        if (nb > 0 && tlen == 0) {
            uint8_t *data = (uint8_t*)v;
            n += jl_printf(out, "0x");
            for(int i = nb - 1; i >= 0; --i)
                n += jl_printf(out, "%02" PRIx8, data[i]);
        }
        else {
            size_t i = 0;
            if (vt == jl_typemap_entry_type)
                i = 1;
            for (; i < tlen; i++) {
                if (!istuple) {
                    n += jl_printf(out, "%s", jl_symbol_name(jl_field_name(vt, i)));
                    n += jl_printf(out, "=");
                }
                size_t offs = jl_field_offset(vt, i);
                char *fld_ptr = (char*)v + offs;
                if (jl_field_isptr(vt, i)) {
                    n += jl_static_show_x(out, *(jl_value_t**)fld_ptr, depth);
                }
                else {
                    jl_datatype_t *ft = (jl_datatype_t*)jl_field_type(vt, i);
                    if (jl_is_uniontype(ft)) {
                        uint8_t sel = ((uint8_t*)fld_ptr)[jl_field_size(vt, i) - 1];
                        ft = (jl_datatype_t*)jl_nth_union_component((jl_value_t*)ft, sel);
                    }
                    n += jl_static_show_x_(out, (jl_value_t*)fld_ptr, ft, depth);
                }
                if (istuple && tlen == 1)
                    n += jl_printf(out, ",");
                else if (i != tlen - 1)
                    n += jl_printf(out, ", ");
            }
            if (vt == jl_typemap_entry_type) {
                n += jl_printf(out, ", next=↩︎\n  ");
                n += jl_static_show_x(out, jl_fieldref(v, 0), depth);
            }
        }
        n += jl_printf(out, ")");
    }
    else {
        n += jl_printf(out, "<?#%p::", (void*)v);
        n += jl_static_show_x(out, (jl_value_t*)vt, depth);
        n += jl_printf(out, ">");
    }
    return n;
}
コード例 #28
0
ファイル: typemap.c プロジェクト: mathcg/julia
jl_typemap_entry_t *jl_typemap_entry_assoc_exact(jl_typemap_entry_t *ml, jl_value_t **args, size_t n)
{
    // some manually-unrolled common special cases
    while (ml->simplesig == (void*)jl_nothing && ml->guardsigs == jl_emptysvec && ml->isleafsig) {
        // use a tight loop for a long as possible
        if (n == jl_datatype_nfields(ml->sig) && jl_typeof(args[0]) == jl_tparam(ml->sig, 0)) {
            if (n == 1)
                return ml;
            if (n == 2) {
                if (jl_typeof(args[1]) == jl_tparam(ml->sig, 1))
                    return ml;
            }
            else if (n == 3) {
                if (jl_typeof(args[1]) == jl_tparam(ml->sig, 1) &&
                    jl_typeof(args[2]) == jl_tparam(ml->sig, 2))
                    return ml;
            }
            else {
                if (sig_match_leaf(args, jl_svec_data(ml->sig->parameters), n))
                    return ml;
            }
        }
        ml = ml->next;
        if (ml == (void*)jl_nothing)
            return NULL;
    }

    while (ml != (void*)jl_nothing) {
        size_t lensig = jl_datatype_nfields(ml->sig);
        if (lensig == n || (ml->va && lensig <= n+1)) {
            if (ml->simplesig != (void*)jl_nothing) {
                size_t lensimplesig = jl_datatype_nfields(ml->simplesig);
                int isva = lensimplesig > 0 && jl_is_vararg_type(jl_tparam(ml->simplesig, lensimplesig - 1));
                if (lensig == n || (isva && lensimplesig <= n + 1)) {
                    if (!sig_match_simple(args, n, jl_svec_data(ml->simplesig->parameters), isva, lensimplesig))
                        goto nomatch;
                }
                else {
                    goto nomatch;
                }
            }

            if (ml->isleafsig) {
                if (!sig_match_leaf(args, jl_svec_data(ml->sig->parameters), n))
                    goto nomatch;
            }
            else if (ml->issimplesig) {
                if (!sig_match_simple(args, n, jl_svec_data(ml->sig->parameters), ml->va, lensig))
                    goto nomatch;
            }
            else {
                if (!jl_tuple_subtype(args, n, ml->sig, 1))
                    goto nomatch;
            }

            size_t i, l;
            if (ml->guardsigs != jl_emptysvec) {
                for (i = 0, l = jl_svec_len(ml->guardsigs); i < l; i++) {
                    // checking guard entries require a more
                    // expensive subtype check, since guard entries added for ANY might be
                    // abstract. this fixed issue #12967.
                    if (jl_tuple_subtype(args, n, (jl_tupletype_t*)jl_svecref(ml->guardsigs, i), 1)) {
                        goto nomatch;
                    }
                }
            }
            return ml;
        }
nomatch:
        ml = ml->next;
    }
    return NULL;
}
コード例 #29
0
ファイル: alloc.c プロジェクト: StefanKarpinski/julia
void jl_compute_field_offsets(jl_datatype_t *st)
{
    size_t sz = 0, alignm = 1;
    int ptrfree = 1;
    int homogeneous = 1;
    jl_value_t *lastty = NULL;

    assert(0 <= st->fielddesc_type && st->fielddesc_type <= 2);

    uint64_t max_offset = (((uint64_t)1) <<
                           (1 << (3 + st->fielddesc_type))) - 1;
    uint64_t max_size = max_offset >> 1;

    for(size_t i=0; i < jl_datatype_nfields(st); i++) {
        jl_value_t *ty = jl_field_type(st, i);
        size_t fsz, al;
        if (jl_isbits(ty) && jl_is_leaf_type(ty)) {
            fsz = jl_datatype_size(ty);
            // Should never happen
            if (__unlikely(fsz > max_size))
                jl_throw(jl_overflow_exception);
            al = ((jl_datatype_t*)ty)->alignment;
            jl_field_setisptr(st, i, 0);
            if (((jl_datatype_t*)ty)->haspadding)
                st->haspadding = 1;
        }
        else {
            fsz = sizeof(void*);
            if (fsz > MAX_ALIGN)
                fsz = MAX_ALIGN;
            al = fsz;
            jl_field_setisptr(st, i, 1);
            ptrfree = 0;
        }
        if (al != 0) {
            size_t alsz = LLT_ALIGN(sz, al);
            if (sz & (al - 1))
                st->haspadding = 1;
            sz = alsz;
            if (al > alignm)
                alignm = al;
        }
        homogeneous &= lastty==NULL || lastty==ty;
        lastty = ty;
        jl_field_setoffset(st, i, sz);
        jl_field_setsize(st, i, fsz);
        if (__unlikely(max_offset - sz < fsz))
            jl_throw(jl_overflow_exception);
        sz += fsz;
    }
    if (homogeneous && lastty!=NULL && jl_is_tuple_type(st)) {
        // Some tuples become LLVM vectors with stronger alignment than what was calculated above.
        unsigned al = jl_special_vector_alignment(jl_datatype_nfields(st), lastty);
        assert(al % alignm == 0);
        if (al)
            alignm = al;
    }
    st->alignment = alignm;
    st->size = LLT_ALIGN(sz, alignm);
    if (st->size > sz)
        st->haspadding = 1;
    st->pointerfree = ptrfree && !st->abstract;
}
コード例 #30
0
ファイル: typemap.c プロジェクト: mathcg/julia
jl_typemap_entry_t *jl_typemap_insert(union jl_typemap_t *cache, jl_value_t *parent,
                                      jl_tupletype_t *type, jl_svec_t *tvars,
                                      jl_tupletype_t *simpletype, jl_svec_t *guardsigs,
                                      jl_value_t *newvalue, int8_t offs,
                                      const struct jl_typemap_info *tparams,
                                      jl_value_t **overwritten)
{
    assert(jl_is_tuple_type(type));
    if (!simpletype) {
        simpletype = (jl_tupletype_t*)jl_nothing;
    }

    if ((jl_value_t*)simpletype == jl_nothing) {
        jl_typemap_entry_t *ml = jl_typemap_assoc_by_type(*cache, type, NULL, 1, 0, offs);
        if (ml && ml->simplesig == (void*)jl_nothing) {
            if (overwritten != NULL)
                *overwritten = ml->func.value;
            if (newvalue == NULL)  // don't overwrite with guard entries
                return ml;
            // sigatomic begin
            ml->sig = type;
            jl_gc_wb(ml, ml->sig);
            ml->simplesig = simpletype;
            jl_gc_wb(ml, ml->simplesig);
            ml->tvars = tvars;
            jl_gc_wb(ml, ml->tvars);
            ml->va = jl_is_va_tuple(type);
            // TODO: `l->func` or `l->func->roots` might need to be rooted
            ml->func.value = newvalue;
            if (newvalue)
                jl_gc_wb(ml, newvalue);
            // sigatomic end
            return ml;
        }
    }
    if (overwritten != NULL)
        *overwritten = NULL;

    jl_typemap_entry_t *newrec = (jl_typemap_entry_t*)jl_gc_allocobj(sizeof(jl_typemap_entry_t));
    jl_set_typeof(newrec, jl_typemap_entry_type);
    newrec->sig = type;
    newrec->simplesig = simpletype;
    newrec->tvars = tvars;
    newrec->func.value = newvalue;
    newrec->guardsigs = guardsigs;
    newrec->next = (jl_typemap_entry_t*)jl_nothing;
    // compute the complexity of this type signature
    newrec->va = jl_is_va_tuple(type);
    newrec->issimplesig = (tvars == jl_emptysvec); // a TypeVar environment needs an complex matching test
    newrec->isleafsig = newrec->issimplesig && !newrec->va; // entirely leaf types don't need to be sorted
    JL_GC_PUSH1(&newrec);
    size_t i, l;
    for (i = 0, l = jl_datatype_nfields(type); i < l && newrec->issimplesig; i++) {
        jl_value_t *decl = jl_field_type(type, i);
        if (decl == (jl_value_t*)jl_datatype_type)
            newrec->isleafsig = 0; // Type{} may have a higher priority than DataType
        else if (decl == (jl_value_t*)jl_typector_type)
            newrec->isleafsig = 0; // Type{} may have a higher priority than TypeConstructor
        else if (jl_is_type_type(decl))
            newrec->isleafsig = 0; // Type{} may need special processing to compute the match
        else if (jl_is_vararg_type(decl))
            newrec->isleafsig = 0; // makes iteration easier when the endpoints are the same
        else if (decl == (jl_value_t*)jl_any_type)
            newrec->isleafsig = 0; // Any needs to go in the general cache
        else if (!jl_is_leaf_type(decl)) // anything else can go through the general subtyping test
            newrec->isleafsig = newrec->issimplesig = 0;
    }
    // TODO: assert that guardsigs == jl_emptysvec && simplesig == jl_nothing if isleafsig and optimize with that knowledge?
    jl_typemap_insert_generic(cache, parent, newrec, NULL, offs, tparams);
    JL_GC_POP();
    return newrec;
}