static int pid_compare(t_long_pid_t *p1, t_long_pid_t *p2) { if (is_term_smaller(p1->node, p2->node)) return -1; if (is_term_smaller(p2->node, p1->node)) return 1; uint32_t creat1 = opr_hdr_creat(p1); uint32_t creat2 = opr_hdr_creat(p2); if (creat1 < creat2) return -1; if (creat2 < creat1) return 1; uint32_t id1 = opr_hdr_id(p1); uint32_t id2 = opr_hdr_id(p2); if (id1 < id2) return -1; if (id2 < id1) return 1; if (p1->serial < p2->serial) return -1; if (p2->serial < p1->serial) return 1; return 0; }
static int ref_compare(t_long_ref_t *r1, t_long_ref_t *r2) { if (is_term_smaller(r1->node, r2->node)) return -1; if (is_term_smaller(r2->node, r1->node)) return 1; uint32_t creat1 = opr_hdr_creat(r1); uint32_t creat2 = opr_hdr_creat(r2); if (creat1 < creat2) return -1; if (creat2 < creat1) return 1; uint32_t id1 = opr_hdr_id(r1); uint32_t id2 = opr_hdr_id(r2); if (id1 < id2) return -1; if (id2 < id1) return 1; if (r1->id1 < r2->id1) return -1; if (r2->id1 < r1->id1) return 1; if (r1->id2 < r2->id2) return -1; if (r2->id2 < r1->id2) return 1; return 0; }
static int fun_compare(t_fun_t *f1, t_fun_t *f2) { if (f1->old_uniq < f2->old_uniq) return -1; if (f1->old_uniq > f2->old_uniq) return 1; if (f1->old_index < f2->old_index) return -1; if (f1->old_index > f2->old_index) return 1; int i = 0; int n1 = fun_num_free((uint32_t *)f1); int n2 = fun_num_free((uint32_t *)f2); while (i < n1 && i < n2) { if (is_term_smaller(f1->frozen[i], f2->frozen[i])) return -1; if (is_term_smaller(f2->frozen[i], f1->frozen[i])) return 1; i++; } if (n1 < n2) return -1; if (n1 > n2) return 1; return 0; }
static int export_compare(t_export_t *x1, t_export_t *x2) { if (is_term_smaller(x1->e->module, x2->e->module)) return -1; if (is_term_smaller(x2->e->module, x1->e->module)) return 1; if (is_term_smaller(x1->e->function, x2->e->function)) return -1; if (is_term_smaller(x2->e->function, x1->e->function)) return 1; if (x1->e->arity < x2->e->arity) return -1; if (x1->e->arity > x2->e->arity) return 1; return 0; }
static int is_term_smaller_1(term_t l1, term_t l2) { assert(is_cons(l1) && is_cons(l2)); do { term_t *cons1 = peel_cons(l1); term_t *cons2 = peel_cons(l2); if (is_term_smaller(cons1[0], cons2[0])) return 1; if (is_term_smaller(cons2[0], cons1[0])) return 0; l1 = cons1[1]; l2 = cons2[1]; } while (is_cons(l1) && is_cons(l2)); return is_term_smaller(l1, l2); }
static int oid_compare(t_long_oid_t *o1, t_long_oid_t *o2) { if (is_term_smaller(o1->node, o2->node)) return -1; if (is_term_smaller(o2->node, o1->node)) return 1; uint32_t creat1 = opr_hdr_creat(o1); uint32_t creat2 = opr_hdr_creat(o2); if (creat1 < creat2) return -1; if (creat2 < creat1) return 1; uint32_t id1 = opr_hdr_id(o1); uint32_t id2 = opr_hdr_id(o2); if (id1 < id2) return -1; if (id2 < id1) return 1; return 0; }
static int is_term_smaller_2(term_t t1, term_t t2) { assert(is_tuple(t1) && is_tuple(t2)); uint32_t *tdata1 = peel_tuple(t1); uint32_t *tdata2 = peel_tuple(t2); if (*tdata1 < *tdata2) return 1; if (*tdata1 > *tdata2) return 0; for (int i = 1; i <= *tdata1; i++) { if (is_term_smaller(tdata1[i], tdata2[i])) return 1; if (is_term_smaller(tdata2[i], tdata1[i])) return 0; } return 0; }
// maps:from_list/1 [26] term_t cbif_from_list1(proc_t *proc, term_t *regs) { term_t List = regs[0]; if (!is_list(List)) badarg(List); int len = list_len(List); term_t ks[len]; //XXX: imminent stack overflow term_t vs[len]; int n = 0; term_t l = List; while (is_cons(l)) { term_t *cons = peel_cons(l); if (!is_tuple(cons[0])) badarg(List); uint32_t *p = peel_tuple(cons[0]); if (*p++ != 2) badarg(List); term_t k = *p++; term_t v = *p++; if (n == 0 || is_term_smaller(k, ks[0])) { memmove(ks +1, ks, n *sizeof(term_t)); memmove(vs +1, vs, n *sizeof(term_t)); ks[0] = k; vs[0] = v; n++; } else { term_t *alpha = ks; term_t *beta = ks +n; // *alpha =< k while (beta > alpha+1) { term_t *mid = alpha + (beta -alpha +1)/2; if (is_term_smaller(k, *mid)) beta = mid; else alpha = mid; } assert(beta == alpha+1); int index = alpha -ks; if (k == *alpha || are_terms_equal(k, *alpha, 1)) vs[index] = v; else { index++; // ks[index] > k now memmove(ks +index +1, ks +index, (n -index) *sizeof(term_t)); memmove(vs +index +1, vs +index, (n -index) *sizeof(term_t)); ks[index] = k; vs[index] = v; n++; } } l = cons[1]; } if (!is_nil(l)) badarg(List); int needed = 1 +n + WSIZE(t_map_t) +n; uint32_t *htop = heap_alloc(&proc->hp, needed); term_t keys = tag_tuple(htop); *htop++ = n; memcpy(htop, ks, n *sizeof(term_t)); htop += n; term_t out = tag_boxed(htop); term_t *values = htop +WSIZE(t_map_t); box_map(htop, n, keys); heap_set_top(&proc->hp, htop); memcpy(values, vs, n *sizeof(term_t)); return out; }
// maps:merge/2 [23] term_t cbif_merge2(proc_t *proc, term_t *regs) { term_t Map1 = regs[0]; term_t Map2 = regs[1]; if (!is_boxed_map(Map1)) badarg(Map1); if (!is_boxed_map(Map2)) badarg(Map2); t_map_t *m1 = (t_map_t *)peel_boxed(Map1); uint32_t *p1 = peel_tuple(m1->keys); int size1 = *p1++; term_t *ks1 = p1; term_t *vs1 = m1->values; t_map_t *m2 = (t_map_t *)peel_boxed(Map2); uint32_t *p2 = peel_tuple(m2->keys); int size2 = *p2++; term_t *ks2 = p2; term_t *vs2 = m2->values; term_t mks[size1+size2]; //XXX: stack overflow term_t mvs[size1+size2]; term_t *ks3 = mks; term_t *vs3 = mvs; int ss1 = size1; int ss2 = size2; int size = 0; while (size1 > 0 && size2 > 0) { term_t a = *ks1; term_t b = *ks2; if (is_term_smaller(a, b)) { *ks3++ = *ks1++; *vs3++ = *vs1++; size1--; } else if (a == b || are_terms_equal(a, b, 1)) { ks1++; vs1++; size1--; *ks3++ = *ks2++; *vs3++ = *vs2++; size2--; } else { *ks3++ = *ks2++; *vs3++ = *vs2++; size2--; } size++; } while (size1-- > 0) { *ks3++ = *ks1++; *vs3++ = *vs1++; size++; } while (size2-- > 0) { *ks3++ = *ks2++; *vs3++ = *vs2++; size++; } if (size == ss1 || size == ss2) { // reuse keys term_t keys = (size == ss1) ?m1->keys :m2->keys; int needed = WSIZE(t_map_t) +size; uint32_t *p = heap_alloc(&proc->hp, needed); term_t out = tag_boxed(p); term_t *values = p +WSIZE(t_map_t); box_map(p, size, keys); heap_set_top(&proc->hp, p); memcpy(values, mvs, size *sizeof(term_t)); return out; } else { // new keys int needed = 1 +size +WSIZE(t_map_t) +size; uint32_t *p = heap_alloc(&proc->hp, needed); term_t keys = tag_tuple(p); *p++ = size; memcpy(p, mks, size *sizeof(term_t)); term_t out = tag_boxed(p); term_t *values = p +WSIZE(t_map_t); box_map(p, size, keys); heap_set_top(&proc->hp, p); memcpy(values, mvs, size *sizeof(term_t)); return out; } }