📄 utils.c
字号:
Uint i = 0; Uint n = BIG_SIZE(ptr); Uint32 con = BIG_SIGN(ptr) ? HCONST_10 : HCONST_11; do { Uint x, y; ASSERT(sizeof(digit_t) <= 4); ASSERT(D_EXP < 8*sizeof(Uint)); x = i < n ? BIG_DIGIT(ptr, i++) : 0; if (sizeof(digit_t) == 2) x += (Uint)(i < n ? BIG_DIGIT(ptr, i++) : 0) << D_EXP; y = i < n ? BIG_DIGIT(ptr, i++) : 0; if (sizeof(digit_t) == 2) y += (Uint)(i < n ? BIG_DIGIT(ptr, i++) : 0) << D_EXP; UINT32_HASH_2((Uint32)x, (Uint32)y, con); } while (i < n); goto hash2_common; } break; case REF_SUBTAG: UINT32_HASH(internal_ref_numbers(term)[0], HCONST_7); goto hash2_common; break; case EXTERNAL_REF_SUBTAG: UINT32_HASH(external_ref_numbers(term)[0], HCONST_7); goto hash2_common; break; case EXTERNAL_PID_SUBTAG: UINT32_HASH(external_pid_number(term), HCONST_5); goto hash2_common; case EXTERNAL_PORT_SUBTAG: UINT32_HASH(external_port_number(term), HCONST_6); goto hash2_common; case FLOAT_SUBTAG: { FloatDef ff; GET_DOUBLE(term, ff);#if defined(WORDS_BIGENDIAN) UINT32_HASH_2(ff.fw[0], ff.fw[1], HCONST_12);#else UINT32_HASH_2(ff.fw[1], ff.fw[0], HCONST_12);#endif goto hash2_common; } break; default: erl_exit(1, "Invalid tag in make_hash2(0x%X)\n", term); } } break; case TAG_PRIMARY_IMMED1: switch (term & _TAG_IMMED1_MASK) { case _TAG_IMMED1_PID: UINT32_HASH(internal_pid_number(term), HCONST_5); goto hash2_common; case _TAG_IMMED1_PORT: UINT32_HASH(internal_port_number(term), HCONST_6); goto hash2_common; case _TAG_IMMED1_IMMED2: switch (term & _TAG_IMMED2_MASK) { case _TAG_IMMED2_ATOM: if (hash == 0) hash = atom_tab(atom_val(term))->slot.bucket.hvalue; else UINT32_HASH(atom_tab(atom_val(term))->slot.bucket.hvalue, HCONST_3); goto hash2_common; case _TAG_IMMED2_NIL: if (hash == 0) hash = 3468870702UL; else UINT32_HASH(NIL_DEF, HCONST_2); goto hash2_common; default: erl_exit(1, "Invalid tag in make_hash2(0x%X)\n", term); } case _TAG_IMMED1_SMALL: { Sint x = signed_val(term); if (SMALL_BITS > 28 && !IS_SSMALL28(x)) { term = small_to_big(x, tmp_big); break; } SINT32_HASH(x, HCONST); goto hash2_common; } } break; default: erl_exit(1, "Invalid tag in make_hash2(0x%X)\n", term); hash2_common: if (ESTACK_ISEMPTY(s)) { DESTROY_ESTACK(s); return hash; } term = ESTACK_POP(s); } } }#undef UINT32_HASH_2#undef UINT32_HASH#undef SINT32_HASH}#undef HCONST#undef MIX#ifdef ARCH_64Uint32make_broken_hash(Eterm term, Uint32 hash)#elseUintmake_broken_hash(Eterm term, Uint hash)#endif{ switch (tag_val_def(term)) { case NIL_DEF: return hash*FUNNY_NUMBER3 + 1; case ATOM_DEF: return hash*FUNNY_NUMBER1 + (atom_tab(atom_val(term))->slot.bucket.hvalue); case SMALL_DEF:#ifdef ARCH_64 { Sint y1 = signed_val(term); Uint y2 = y1 < 0 ? -(Uint)y1 : y1; Uint32 y3 = (Uint32) (y2 >> 32); int arity = 1;#if defined(WORDS_BIGENDIAN) if (!IS_SSMALL28(y1)) { /* like a bignum */ Uint32 y4 = (Uint32) y2; hash = hash*FUNNY_NUMBER2 + ((y4 << 16) | (y4 >> 16)); if (y3) { hash = hash*FUNNY_NUMBER2 + ((y3 << 16) | (y3 >> 16)); arity++; } return hash * (y1 < 0 ? FUNNY_NUMBER3 : FUNNY_NUMBER2) + arity; } return hash*FUNNY_NUMBER2 + (((Uint) y1) & 0xfffffff);#else if (!IS_SSMALL28(y1)) { /* like a bignum */ hash = hash*FUNNY_NUMBER2 + ((Uint32) y2); if (y3) { hash = hash*FUNNY_NUMBER2 + y3; arity++; } return hash * (y1 < 0 ? FUNNY_NUMBER3 : FUNNY_NUMBER2) + arity; } return hash*FUNNY_NUMBER2 + (((Uint) y1) & 0xfffffff);#endif }#else return hash*FUNNY_NUMBER2 + unsigned_val(term);#endif case BINARY_DEF: { size_t sz = binary_size(term); size_t i = (sz < 15) ? sz : 15; hash = hash_binary_bytes(term, i, hash); return hash*FUNNY_NUMBER4 + sz; } case EXPORT_DEF: { Export* ep = (Export *) (export_val(term))[1]; hash = hash * FUNNY_NUMBER11 + ep->code[2]; hash = hash*FUNNY_NUMBER1 + (atom_tab(atom_val(ep->code[0]))->slot.bucket.hvalue); hash = hash*FUNNY_NUMBER1 + (atom_tab(atom_val(ep->code[1]))->slot.bucket.hvalue); return hash; } case FUN_DEF: { ErlFunThing* funp = (ErlFunThing *) fun_val(term); Uint num_free = funp->num_free; Uint i; hash = hash * FUNNY_NUMBER10 + num_free; hash = hash*FUNNY_NUMBER1 + (atom_tab(atom_val(funp->fe->module))->slot.bucket.hvalue); hash = hash*FUNNY_NUMBER2 + funp->fe->old_index; hash = hash*FUNNY_NUMBER2 + funp->fe->old_uniq; for (i = 0; i < num_free; i++) { hash = make_broken_hash(funp->env[i], hash); } return hash; } case PID_DEF: return hash*FUNNY_NUMBER5 + internal_pid_number(term); case EXTERNAL_PID_DEF: return hash*FUNNY_NUMBER5 + external_pid_number(term); case PORT_DEF: return hash*FUNNY_NUMBER9 + internal_port_number(term); case EXTERNAL_PORT_DEF: return hash*FUNNY_NUMBER9 + external_port_number(term); case REF_DEF: return hash*FUNNY_NUMBER9 + internal_ref_numbers(term)[0]; case EXTERNAL_REF_DEF: return hash*FUNNY_NUMBER9 + external_ref_numbers(term)[0]; case FLOAT_DEF: { FloatDef ff; GET_DOUBLE(term, ff); return hash*FUNNY_NUMBER6 + (ff.fw[0] ^ ff.fw[1]); } break; case LIST_DEF: { Eterm* list = list_val(term); while(1) { hash = make_broken_hash(*list, hash); if (is_not_list(CDR(list))) return make_broken_hash(CDR(list),hash)*FUNNY_NUMBER8; list = list_val(CDR(list)); } } break; case BIG_DEF: { Eterm* ptr = big_val(term); int is_neg = BIG_SIGN(ptr); Uint arity = BIG_ARITY(ptr); #ifdef ARCH_64 Uint i = 0; Uint n = BIG_SIZE(ptr); arity = n; for (i = 0; i < n; i++) { digit_t d = BIG_DIGIT(ptr, i);#if defined(WORDS_BIGENDIAN) hash = hash*FUNNY_NUMBER2 + ((d << 16) | (d >> 16));#else hash = hash*FUNNY_NUMBER2 + d;#endif }#else int i = arity; ptr++; while (i--) { hash = hash*FUNNY_NUMBER2 + *ptr++; }#endif if (is_neg) return hash*FUNNY_NUMBER3 + arity; else return hash*FUNNY_NUMBER2 + arity; } break; case TUPLE_DEF: { Eterm* ptr = tuple_val(term); Uint arity = arityval(*ptr); int i = arity; ptr++; while(i--) hash = make_broken_hash(*ptr++, hash); return hash*FUNNY_NUMBER9 + arity; } break; default: erl_exit(1, "Invalid tag in make_broken_hash\n"); return 0; }}static int do_send_to_logger(Eterm tag, Eterm gleader, char *buf, int len){ /* error_logger ! {notify,{info_msg,gleader,{emulator,"~s~n",[<message as list>]}}} | {notify,{error,gleader,{emulator,"~s~n",[<message as list>]}}} | {notify,{warning_msg,gleader,{emulator,"~s~n",[<message as list>}]}} */ Eterm* hp; Uint sz; Uint gl_sz; Eterm gl; Eterm list,plist,format,tuple1,tuple2,tuple3; ErlOffHeap *ohp;#ifdef ERTS_SMP ErlHeapFragment *bp;#else Process *p;#endif ASSERT(is_atom(tag)); if (len <= 0) { return -1; }#ifndef ERTS_SMP if (#ifdef USE_THREADS !erts_get_scheduler_data() || /* Must be scheduler thread */#endif (p = erts_whereis_process(NULL, 0, am_error_logger, 0, 0)) == NULL || p->status == P_RUNNING) { /* buf *always* points to a null terminated string */ erts_fprintf(stderr, "(no error logger present) %T: \"%s\"\n", tag, buf); return 0; } /* So we have an error logger, lets build the message */#endif gl_sz = IS_CONST(gleader) ? 0 : size_object(gleader); sz = len * 2 /* message list */+ 2 /* cons surrounding message list */ + gl_sz + 3 /*outher 2-tuple*/ + 4 /* middle 3-tuple */ + 4 /*inner 3-tuple */ + 8 /* "~s~n" */;#ifdef ERTS_SMP bp = new_message_buffer(sz); ohp = &bp->off_heap; hp = bp->mem;#else ohp = &MSO(p); hp = HAlloc(p, sz);#endif gl = (is_nil(gleader) ? am_noproc : (IS_CONST(gleader) ? gleader : copy_struct(gleader,gl_sz,&hp,ohp))); list = buf_to_intlist(&hp, buf, len, NIL); plist = CONS(hp,list,NIL); hp += 2; format = buf_to_intlist(&hp, "~s~n", 4, NIL); tuple1 = TUPLE3(hp, am_emulator, format, plist); hp += 4; tuple2 = TUPLE3(hp, tag, gl, tuple1); hp += 4; tuple3 = TUPLE2(hp, am_notify, tuple2);#ifdef HARDDEBUG erts_fprintf(stderr, "%T\n", tuple3);#endif#ifdef ERTS_SMP { Eterm from = erts_get_current_pid(); if (is_not_internal_pid(from)) from = NIL; erts_queue_error_logger_message(from, tuple3, bp); }#else erts_queue_message(p, 0/* only used for smp build */, NULL, tuple3, NIL);#endif return 0;}static ERTS_INLINE intsend_info_to_logger(Eterm gleader, char *buf, int len) { return do_send_to_logger(am_info_msg, gleader, buf, len);}static ERTS_INLINE intsend_warning_to_logger(Eterm gleader, char *buf, int len) { Eterm tag; switch (erts_error_logger_warnings) { case am_info: tag = am_info_msg; break; case am_warning: tag = am_warning_msg; break; default: tag = am_error; break; } return do_send_to_logger(tag, gleader, buf, len);}static ERTS_INLINE intsend_error_to_logger(Eterm gleader, char *buf, int len) { return do_send_to_logger(am_error, gleader, buf, len);}#define LOGGER_DSBUF_INC_SZ 256static erts_dsprintf_buf_t *grow_logger_dsbuf(erts_dsprintf_buf_t *dsbufp, size_t need){ size_t size; size_t free_size = dsbufp->size - dsbufp->str_len; ASSERT(dsbufp && dsbufp->str); if (need <= free_size) return dsbufp; size = need - free_size + LOGGER_DSBUF_INC_SZ; size = (((size + LOGGER_DSBUF_INC_SZ - 1) / LOGGER_DSBUF_INC_SZ) * LOGGER_DSBUF_INC_SZ); size += dsbufp->size; ASSERT(dsbufp->str_len + need <= size); dsbufp->str = (char *) erts_realloc(ERTS_ALC_T_LOGGER_DSBUF, (void *) dsbufp->str, size); dsbufp->size = size; return dsbufp;}erts_dsprintf_buf_t *erts_create_logger_dsbuf(void){ erts_dsprintf_buf_t init = ERTS_DSPRINTF_BUF_INITER(grow_logger_dsbuf); erts_dsprintf_buf_t *dsbufp = erts_alloc(ERTS_ALC_T_LOGGER_DSBUF, sizeof(erts_dsprintf_buf_t)); sys_memcpy((void *) dsbufp, (void *) &init, sizeof(erts_dsprintf_buf_t)); dsbufp->str = (char *) erts_alloc(ERTS_ALC_T_LOGGER_DSBUF, LOGGER_DSBUF_INC_SZ); dsbufp->str[0] = '\0'; dsbufp->size = LOGGER_DSBUF_INC_SZ; return dsbufp;}static ERTS_INLINE voiddestroy_logger_dsbuf(erts_dsprintf_buf_t *dsbufp){ ASSERT(dsbufp && dsbufp->str); erts_free(ERTS_ALC_T_LOGGER_DSBUF, (void *) dsbufp->str); erts_free(ERTS_ALC_T_LOGGER_DSBUF, (void *) dsbufp);}interts_send_info_to_logger(Eterm gleader, erts_dsprintf_buf_t *dsbufp){ int res; res = send_info_to_logger(gleader, dsbufp->str, dsbufp->str_len); destroy_logger_dsbuf(dsbufp); return res;}interts_send_warning_to_logger(Eterm gleader, erts_dsprintf_buf_t *dsbufp){ int res; res = send_warning_to_logger(gleader, dsbufp->str, dsbufp->str_len); destroy_logger_dsbuf(dsbufp); return res;}interts_send_error_to_logger(Eterm gleader, erts_dsprintf_buf_t *dsbufp){ int res; res = send_error_to_logger(gleader, dsbufp->str, dsbufp->str_len); destroy_logger_dsbuf(dsbufp); return res;}interts_send_info_to_logger_str(Eterm gleader, char *str){ return send_info_to_logger(gleader, str, sys_strlen(str));}interts_send_warning_to_logger_str(Eterm gleader, char *str){ return send_warning_to_logger(gleader, str, sys_strlen(str));}interts_send_error_to_logger_str(Eterm gleader, char *str){ return send_error_to_logger(gleader, str, sys_strlen(str));}interts_send_info_to_logger_nogl(erts_dsprintf_buf_t *dsbuf){ return erts_send_info_to_logger(NIL, dsbuf);}interts_send_warning_to_logger_nogl(erts_dsprintf_buf_t *dsbuf){ return erts_send_warning_to_logger(NIL, dsbuf);}interts_send_error_to_logger_nogl(erts_dsprintf_buf_t *dsbuf){ return erts_send_error_to_logger(NIL, dsbuf);}interts_send_info_to_logger_str_nogl(char *str){ return erts_send_info_to_logger_str(NIL, str);}interts_send_warning_to_logger_str_nogl(char *str){ return erts_send_warning_to_logger_str(NIL, str);}interts_send_error_to_logger_str_nogl(char *str){ return erts_send_error_to_logger_str(NIL, str);}#define TMP_DSBUF_INC_SZ 256static erts_dsprintf_buf_t *grow_tmp_dsbuf(erts_dsprintf_buf_t *dsbufp, size_t need){ size_t size; size_t free_size = dsbufp->size - dsbufp->str_len; ASSERT(dsbufp); if (need <= free_size) return dsbufp; size = need - free_size + TMP_DSBUF_INC_SZ; size = ((size + TMP_DSBUF_INC_SZ - 1)/TMP_DSBUF_INC_SZ)*TMP_DSBUF_INC_SZ; size += dsbufp->size; ASSERT(dsbufp->str_len + need <= size); dsbufp->str = (char *) erts_realloc(ERTS_ALC_T_TMP_DSBUF, (void *) dsbufp->str, size); dsbufp->size = size; return dsbufp;}erts_dsprintf_buf_t *erts_create_tmp_dsbuf(Uint size){ Uint init_size = size ? size : TMP_DSBUF_INC_SZ; erts_dsprintf_buf_t init = ERTS_DSPRINTF_BUF_INITER(grow_tmp_dsbuf); erts_dsprintf_buf_t *dsbufp = erts_alloc(ERTS_ALC_T_TMP_DSBUF, sizeof(erts_dsprintf_buf_t)); sys_memcpy((void *) dsbufp, (void *) &init, sizeof(erts_dsprintf_buf_t));
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -