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) { jl_ptls_t ptls = jl_get_ptls_states(); 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_alloc(ptls, sizeof(jl_typemap_entry_t), 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_field_count(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; }
jl_typemap_entry_t *jl_typemap_insert(union jl_typemap_t *cache, jl_value_t *parent, jl_tupletype_t *type, jl_tupletype_t *simpletype, jl_svec_t *guardsigs, jl_value_t *newvalue, int8_t offs, const struct jl_typemap_info *tparams, size_t min_world, size_t max_world, jl_value_t **overwritten) { jl_ptls_t ptls = jl_get_ptls_states(); assert(min_world > 0 && max_world > 0); if (!simpletype) simpletype = (jl_tupletype_t*)jl_nothing; jl_value_t *ttype = jl_unwrap_unionall((jl_value_t*)type); if ((jl_value_t*)simpletype == jl_nothing) { jl_typemap_entry_t *ml = jl_typemap_assoc_by_type(*cache, (jl_value_t*)type, NULL, 0, offs, min_world, 0); if (ml && ml->simplesig == (void*)jl_nothing) { if (overwritten != NULL) *overwritten = ml->func.value; if (newvalue == ml->func.value) // no change. TODO: involve world in computation! return ml; if (newvalue == NULL) // don't overwrite with guard entries return ml; ml->max_world = min_world - 1; } } jl_typemap_entry_t *newrec = (jl_typemap_entry_t*)jl_gc_alloc(ptls, sizeof(jl_typemap_entry_t), jl_typemap_entry_type); newrec->sig = type; newrec->simplesig = simpletype; newrec->func.value = newvalue; newrec->guardsigs = guardsigs; newrec->next = (jl_typemap_entry_t*)jl_nothing; newrec->min_world = min_world; newrec->max_world = max_world; // compute the complexity of this type signature newrec->va = jl_is_va_tuple((jl_datatype_t*)ttype); newrec->issimplesig = !jl_is_unionall(type); // a TypeVar environment needs a complex matching test newrec->isleafsig = newrec->issimplesig && !newrec->va; // entirely leaf types don't need to be sorted JL_GC_PUSH1(&newrec); assert(jl_is_tuple_type(ttype)); size_t i, l; for (i = 0, l = jl_field_count(ttype); i < l && newrec->issimplesig; i++) { jl_value_t *decl = jl_field_type(ttype, i); if (jl_is_kind(decl)) newrec->isleafsig = 0; // Type{} may have a higher priority than a kind 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_concrete_type(decl)) // anything else needs to 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; }