PageRenderTime 57ms CodeModel.GetById 12ms RepoModel.GetById 0ms app.codeStats 1ms

/erts/emulator/beam/utils.c

https://github.com/Bwooce/otp
C | 4112 lines | 3365 code | 447 blank | 300 comment | 646 complexity | e2f376dbbe07ec1f0ef6a6eb059cc676 MD5 | raw file
Possible License(s): LGPL-2.1, MPL-2.0-no-copyleft-exception, BSD-2-Clause

Large files files are truncated, but you can click here to view the full file

  1. /*
  2. * %CopyrightBegin%
  3. *
  4. * Copyright Ericsson AB 1996-2011. All Rights Reserved.
  5. *
  6. * The contents of this file are subject to the Erlang Public License,
  7. * Version 1.1, (the "License"); you may not use this file except in
  8. * compliance with the License. You should have received a copy of the
  9. * Erlang Public License along with this software. If not, it can be
  10. * retrieved online at http://www.erlang.org/.
  11. *
  12. * Software distributed under the License is distributed on an "AS IS"
  13. * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
  14. * the License for the specific language governing rights and limitations
  15. * under the License.
  16. *
  17. * %CopyrightEnd%
  18. */
  19. #ifdef HAVE_CONFIG_H
  20. # include "config.h"
  21. #endif
  22. #define ERTS_DO_INCL_GLB_INLINE_FUNC_DEF
  23. #include "sys.h"
  24. #include "erl_vm.h"
  25. #include "global.h"
  26. #include "erl_process.h"
  27. #include "big.h"
  28. #include "bif.h"
  29. #include "erl_binary.h"
  30. #include "erl_bits.h"
  31. #include "packet_parser.h"
  32. #include "erl_gc.h"
  33. #define ERTS_WANT_DB_INTERNAL__
  34. #include "erl_db.h"
  35. #include "erl_threads.h"
  36. #include "register.h"
  37. #include "dist.h"
  38. #include "erl_printf.h"
  39. #include "erl_threads.h"
  40. #include "erl_smp.h"
  41. #include "erl_time.h"
  42. #undef M_TRIM_THRESHOLD
  43. #undef M_TOP_PAD
  44. #undef M_MMAP_THRESHOLD
  45. #undef M_MMAP_MAX
  46. #if defined(__GLIBC__) && defined(HAVE_MALLOC_H)
  47. #include <malloc.h>
  48. #endif
  49. #if !defined(HAVE_MALLOPT)
  50. #undef HAVE_MALLOPT
  51. #define HAVE_MALLOPT 0
  52. #endif
  53. /* profile_scheduler mini message queue */
  54. typedef struct {
  55. Uint scheduler_id;
  56. Uint no_schedulers;
  57. Uint Ms;
  58. Uint s;
  59. Uint us;
  60. Eterm state;
  61. } profile_sched_msg;
  62. typedef struct {
  63. profile_sched_msg msg[2];
  64. Uint n;
  65. } profile_sched_msg_q;
  66. #ifdef ERTS_SMP
  67. static void
  68. dispatch_profile_msg_q(profile_sched_msg_q *psmq)
  69. {
  70. int i = 0;
  71. profile_sched_msg *msg = NULL;
  72. ASSERT(psmq != NULL);
  73. for (i = 0; i < psmq->n; i++) {
  74. msg = &(psmq->msg[i]);
  75. profile_scheduler_q(make_small(msg->scheduler_id), msg->state, am_undefined, msg->Ms, msg->s, msg->us);
  76. }
  77. }
  78. #endif
  79. Eterm*
  80. erts_heap_alloc(Process* p, Uint need, Uint xtra)
  81. {
  82. ErlHeapFragment* bp;
  83. Eterm* htop;
  84. Uint n;
  85. #if defined(DEBUG) || defined(CHECK_FOR_HOLES)
  86. Uint i;
  87. #endif
  88. #ifdef FORCE_HEAP_FRAGS
  89. if (p->space_verified && p->space_verified_from!=NULL
  90. && HEAP_TOP(p) >= p->space_verified_from
  91. && HEAP_TOP(p) + need <= p->space_verified_from + p->space_verified
  92. && HEAP_LIMIT(p) - HEAP_TOP(p) >= need) {
  93. Uint consumed = need + (HEAP_TOP(p) - p->space_verified_from);
  94. ASSERT(consumed <= p->space_verified);
  95. p->space_verified -= consumed;
  96. p->space_verified_from += consumed;
  97. HEAP_TOP(p) = p->space_verified_from;
  98. return HEAP_TOP(p) - need;
  99. }
  100. p->space_verified = 0;
  101. p->space_verified_from = NULL;
  102. #endif /* FORCE_HEAP_FRAGS */
  103. n = need + xtra;
  104. bp = MBUF(p);
  105. if (bp != NULL && need <= (bp->alloc_size - bp->used_size)) {
  106. Eterm* ret = bp->mem + bp->used_size;
  107. bp->used_size += need;
  108. return ret;
  109. }
  110. #ifdef DEBUG
  111. n++;
  112. #endif
  113. bp = (ErlHeapFragment*)
  114. ERTS_HEAP_ALLOC(ERTS_ALC_T_HEAP_FRAG, ERTS_HEAP_FRAG_SIZE(n));
  115. #if defined(DEBUG) || defined(CHECK_FOR_HOLES)
  116. for (i = 0; i < n; i++) {
  117. bp->mem[i] = ERTS_HOLE_MARKER;
  118. }
  119. #endif
  120. #ifdef DEBUG
  121. n--;
  122. #endif
  123. /*
  124. * When we have created a heap fragment, we are no longer allowed
  125. * to store anything more on the heap.
  126. */
  127. htop = HEAP_TOP(p);
  128. if (htop < HEAP_LIMIT(p)) {
  129. *htop = make_pos_bignum_header(HEAP_LIMIT(p)-htop-1);
  130. HEAP_TOP(p) = HEAP_LIMIT(p);
  131. }
  132. bp->next = MBUF(p);
  133. MBUF(p) = bp;
  134. bp->alloc_size = n;
  135. bp->used_size = need;
  136. MBUF_SIZE(p) += n;
  137. bp->off_heap.first = NULL;
  138. bp->off_heap.overhead = 0;
  139. return bp->mem;
  140. }
  141. #ifdef CHECK_FOR_HOLES
  142. Eterm*
  143. erts_set_hole_marker(Eterm* ptr, Uint sz)
  144. {
  145. Eterm* p = ptr;
  146. int i;
  147. for (i = 0; i < sz; i++) {
  148. *p++ = ERTS_HOLE_MARKER;
  149. }
  150. return ptr;
  151. }
  152. #endif
  153. /*
  154. * Helper function for the ESTACK macros defined in global.h.
  155. */
  156. void
  157. erl_grow_stack(Eterm** start, Eterm** sp, Eterm** end)
  158. {
  159. Uint old_size = (*end - *start);
  160. Uint new_size = old_size * 2;
  161. Uint sp_offs = *sp - *start;
  162. if (new_size > 2 * DEF_ESTACK_SIZE) {
  163. *start = erts_realloc(ERTS_ALC_T_ESTACK, (void *) *start, new_size*sizeof(Eterm));
  164. } else {
  165. Eterm* new_ptr = erts_alloc(ERTS_ALC_T_ESTACK, new_size*sizeof(Eterm));
  166. sys_memcpy(new_ptr, *start, old_size*sizeof(Eterm));
  167. *start = new_ptr;
  168. }
  169. *end = *start + new_size;
  170. *sp = *start + sp_offs;
  171. }
  172. /*
  173. * Helper function for the ESTACK macros defined in global.h.
  174. */
  175. void
  176. erl_grow_wstack(UWord** start, UWord** sp, UWord** end)
  177. {
  178. Uint old_size = (*end - *start);
  179. Uint new_size = old_size * 2;
  180. Uint sp_offs = *sp - *start;
  181. if (new_size > 2 * DEF_ESTACK_SIZE) {
  182. *start = erts_realloc(ERTS_ALC_T_ESTACK, (void *) *start, new_size*sizeof(UWord));
  183. } else {
  184. UWord* new_ptr = erts_alloc(ERTS_ALC_T_ESTACK, new_size*sizeof(UWord));
  185. sys_memcpy(new_ptr, *start, old_size*sizeof(UWord));
  186. *start = new_ptr;
  187. }
  188. *end = *start + new_size;
  189. *sp = *start + sp_offs;
  190. }
  191. /* CTYPE macros */
  192. #define LATIN1
  193. #define IS_DIGIT(c) ((c) >= '0' && (c) <= '9')
  194. #ifdef LATIN1
  195. #define IS_LOWER(c) (((c) >= 'a' && (c) <= 'z') \
  196. || ((c) >= 128+95 && (c) <= 255 && (c) != 247))
  197. #define IS_UPPER(c) (((c) >= 'A' && (c) <= 'Z') \
  198. || ((c) >= 128+64 && (c) <= 128+94 && (c) != 247-32))
  199. #else
  200. #define IS_LOWER(c) ((c) >= 'a' && (c) <= 'z')
  201. #define IS_UPPER(c) ((c) >= 'A' && (c) <= 'Z')
  202. #endif
  203. #define IS_ALNUM(c) (IS_DIGIT(c) || IS_LOWER(c) || IS_UPPER(c))
  204. /* We don't include 160 (non-breaking space). */
  205. #define IS_SPACE(c) (c == ' ' || c == '\n' || c == '\t' || c == '\r')
  206. #ifdef LATIN1
  207. #define IS_CNTRL(c) ((c) < ' ' || (c) == 127 \
  208. || ((c) >= 128 && (c) < 128+32))
  209. #else
  210. /* Treat all non-ASCII as control characters */
  211. #define IS_CNTRL(c) ((c) < ' ' || (c) >= 127)
  212. #endif
  213. #define IS_PRINT(c) (!IS_CNTRL(c))
  214. /*
  215. * Calculate length of a list.
  216. * Returns -1 if not a proper list (i.e. not terminated with NIL)
  217. */
  218. int
  219. list_length(Eterm list)
  220. {
  221. int i = 0;
  222. while(is_list(list)) {
  223. i++;
  224. list = CDR(list_val(list));
  225. }
  226. if (is_not_nil(list)) {
  227. return -1;
  228. }
  229. return i;
  230. }
  231. Uint erts_fit_in_bits(Uint n)
  232. {
  233. Uint i;
  234. i = 0;
  235. while (n > 0) {
  236. i++;
  237. n >>= 1;
  238. }
  239. return i;
  240. }
  241. int
  242. erts_print(int to, void *arg, char *format, ...)
  243. {
  244. int res;
  245. va_list arg_list;
  246. va_start(arg_list, format);
  247. if (to < ERTS_PRINT_MIN)
  248. res = -EINVAL;
  249. else {
  250. switch (to) {
  251. case ERTS_PRINT_STDOUT:
  252. res = erts_vprintf(format, arg_list);
  253. break;
  254. case ERTS_PRINT_STDERR:
  255. res = erts_vfprintf(stderr, format, arg_list);
  256. break;
  257. case ERTS_PRINT_FILE:
  258. res = erts_vfprintf((FILE *) arg, format, arg_list);
  259. break;
  260. case ERTS_PRINT_SBUF:
  261. res = erts_vsprintf((char *) arg, format, arg_list);
  262. break;
  263. case ERTS_PRINT_SNBUF:
  264. res = erts_vsnprintf(((erts_print_sn_buf *) arg)->buf,
  265. ((erts_print_sn_buf *) arg)->size,
  266. format,
  267. arg_list);
  268. break;
  269. case ERTS_PRINT_DSBUF:
  270. res = erts_vdsprintf((erts_dsprintf_buf_t *) arg, format, arg_list);
  271. break;
  272. case ERTS_PRINT_INVALID:
  273. res = -EINVAL;
  274. break;
  275. default:
  276. res = erts_vfdprintf((int) to, format, arg_list);
  277. break;
  278. }
  279. }
  280. va_end(arg_list);
  281. return res;
  282. }
  283. int
  284. erts_putc(int to, void *arg, char c)
  285. {
  286. return erts_print(to, arg, "%c", c);
  287. }
  288. /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *\
  289. * Some Erlang term building utility functions (to be used when performance *
  290. * isn't critical). *
  291. * *
  292. * Add more functions like these here (and function prototypes in global.h) *
  293. * when needed. *
  294. * *
  295. \* */
  296. Eterm
  297. erts_bld_atom(Uint **hpp, Uint *szp, char *str)
  298. {
  299. if (hpp)
  300. return am_atom_put(str, sys_strlen(str));
  301. else
  302. return THE_NON_VALUE;
  303. }
  304. Eterm
  305. erts_bld_uint(Uint **hpp, Uint *szp, Uint ui)
  306. {
  307. Eterm res = THE_NON_VALUE;
  308. if (IS_USMALL(0, ui)) {
  309. if (hpp)
  310. res = make_small(ui);
  311. }
  312. else {
  313. if (szp)
  314. *szp += BIG_UINT_HEAP_SIZE;
  315. if (hpp) {
  316. res = uint_to_big(ui, *hpp);
  317. *hpp += BIG_UINT_HEAP_SIZE;
  318. }
  319. }
  320. return res;
  321. }
  322. /*
  323. * Erts_bld_uword is more or less similar to erts_bld_uint, but a pointer
  324. * can safely be passed.
  325. */
  326. Eterm
  327. erts_bld_uword(Uint **hpp, Uint *szp, UWord uw)
  328. {
  329. Eterm res = THE_NON_VALUE;
  330. if (IS_USMALL(0, uw)) {
  331. if (hpp)
  332. res = make_small((Uint) uw);
  333. }
  334. else {
  335. if (szp)
  336. *szp += BIG_UWORD_HEAP_SIZE(uw);
  337. if (hpp) {
  338. res = uword_to_big(uw, *hpp);
  339. *hpp += BIG_UWORD_HEAP_SIZE(uw);
  340. }
  341. }
  342. return res;
  343. }
  344. Eterm
  345. erts_bld_uint64(Uint **hpp, Uint *szp, Uint64 ui64)
  346. {
  347. Eterm res = THE_NON_VALUE;
  348. if (IS_USMALL(0, ui64)) {
  349. if (hpp)
  350. res = make_small((Uint) ui64);
  351. }
  352. else {
  353. if (szp)
  354. *szp += ERTS_UINT64_HEAP_SIZE(ui64);
  355. if (hpp)
  356. res = erts_uint64_to_big(ui64, hpp);
  357. }
  358. return res;
  359. }
  360. Eterm
  361. erts_bld_sint64(Uint **hpp, Uint *szp, Sint64 si64)
  362. {
  363. Eterm res = THE_NON_VALUE;
  364. if (IS_SSMALL(si64)) {
  365. if (hpp)
  366. res = make_small((Sint) si64);
  367. }
  368. else {
  369. if (szp)
  370. *szp += ERTS_SINT64_HEAP_SIZE(si64);
  371. if (hpp)
  372. res = erts_sint64_to_big(si64, hpp);
  373. }
  374. return res;
  375. }
  376. Eterm
  377. erts_bld_cons(Uint **hpp, Uint *szp, Eterm car, Eterm cdr)
  378. {
  379. Eterm res = THE_NON_VALUE;
  380. if (szp)
  381. *szp += 2;
  382. if (hpp) {
  383. res = CONS(*hpp, car, cdr);
  384. *hpp += 2;
  385. }
  386. return res;
  387. }
  388. Eterm
  389. erts_bld_tuple(Uint **hpp, Uint *szp, Uint arity, ...)
  390. {
  391. Eterm res = THE_NON_VALUE;
  392. ASSERT(arity < (((Uint)1) << (sizeof(Uint)*8 - _HEADER_ARITY_OFFS)));
  393. if (szp)
  394. *szp += arity + 1;
  395. if (hpp) {
  396. res = make_tuple(*hpp);
  397. *((*hpp)++) = make_arityval(arity);
  398. if (arity > 0) {
  399. Uint i;
  400. va_list argp;
  401. va_start(argp, arity);
  402. for (i = 0; i < arity; i++) {
  403. *((*hpp)++) = va_arg(argp, Eterm);
  404. }
  405. va_end(argp);
  406. }
  407. }
  408. return res;
  409. }
  410. Eterm erts_bld_tuplev(Uint **hpp, Uint *szp, Uint arity, Eterm terms[])
  411. {
  412. Eterm res = THE_NON_VALUE;
  413. /*
  414. * Note callers expect that 'terms' is *not* accessed if hpp == NULL.
  415. */
  416. ASSERT(arity < (((Uint)1) << (sizeof(Uint)*8 - _HEADER_ARITY_OFFS)));
  417. if (szp)
  418. *szp += arity + 1;
  419. if (hpp) {
  420. res = make_tuple(*hpp);
  421. *((*hpp)++) = make_arityval(arity);
  422. if (arity > 0) {
  423. Uint i;
  424. for (i = 0; i < arity; i++)
  425. *((*hpp)++) = terms[i];
  426. }
  427. }
  428. return res;
  429. }
  430. Eterm
  431. erts_bld_string_n(Uint **hpp, Uint *szp, const char *str, Sint len)
  432. {
  433. Eterm res = THE_NON_VALUE;
  434. Sint i = len;
  435. if (szp)
  436. *szp += len*2;
  437. if (hpp) {
  438. res = NIL;
  439. while (--i >= 0) {
  440. res = CONS(*hpp, make_small((byte) str[i]), res);
  441. *hpp += 2;
  442. }
  443. }
  444. return res;
  445. }
  446. Eterm
  447. erts_bld_list(Uint **hpp, Uint *szp, Sint length, Eterm terms[])
  448. {
  449. Eterm list = THE_NON_VALUE;
  450. if (szp)
  451. *szp += 2*length;
  452. if (hpp) {
  453. Sint i = length;
  454. list = NIL;
  455. while (--i >= 0) {
  456. list = CONS(*hpp, terms[i], list);
  457. *hpp += 2;
  458. }
  459. }
  460. return list;
  461. }
  462. Eterm
  463. erts_bld_2tup_list(Uint **hpp, Uint *szp,
  464. Sint length, Eterm terms1[], Uint terms2[])
  465. {
  466. Eterm res = THE_NON_VALUE;
  467. if (szp)
  468. *szp += 5*length;
  469. if (hpp) {
  470. Sint i = length;
  471. res = NIL;
  472. while (--i >= 0) {
  473. res = CONS(*hpp+3, TUPLE2(*hpp, terms1[i], terms2[i]), res);
  474. *hpp += 5;
  475. }
  476. }
  477. return res;
  478. }
  479. Eterm
  480. erts_bld_atom_uint_2tup_list(Uint **hpp, Uint *szp,
  481. Sint length, Eterm atoms[], Uint uints[])
  482. {
  483. Sint i;
  484. Eterm res = THE_NON_VALUE;
  485. if (szp) {
  486. *szp += 5*length;
  487. i = length;
  488. while (--i >= 0) {
  489. if (!IS_USMALL(0, uints[i]))
  490. *szp += BIG_UINT_HEAP_SIZE;
  491. }
  492. }
  493. if (hpp) {
  494. i = length;
  495. res = NIL;
  496. while (--i >= 0) {
  497. Eterm ui;
  498. if (IS_USMALL(0, uints[i]))
  499. ui = make_small(uints[i]);
  500. else {
  501. ui = uint_to_big(uints[i], *hpp);
  502. *hpp += BIG_UINT_HEAP_SIZE;
  503. }
  504. res = CONS(*hpp+3, TUPLE2(*hpp, atoms[i], ui), res);
  505. *hpp += 5;
  506. }
  507. }
  508. return res;
  509. }
  510. Eterm
  511. erts_bld_atom_2uint_3tup_list(Uint **hpp, Uint *szp, Sint length,
  512. Eterm atoms[], Uint uints1[], Uint uints2[])
  513. {
  514. Sint i;
  515. Eterm res = THE_NON_VALUE;
  516. if (szp) {
  517. *szp += 6*length;
  518. i = length;
  519. while (--i >= 0) {
  520. if (!IS_USMALL(0, uints1[i]))
  521. *szp += BIG_UINT_HEAP_SIZE;
  522. if (!IS_USMALL(0, uints2[i]))
  523. *szp += BIG_UINT_HEAP_SIZE;
  524. }
  525. }
  526. if (hpp) {
  527. i = length;
  528. res = NIL;
  529. while (--i >= 0) {
  530. Eterm ui1;
  531. Eterm ui2;
  532. if (IS_USMALL(0, uints1[i]))
  533. ui1 = make_small(uints1[i]);
  534. else {
  535. ui1 = uint_to_big(uints1[i], *hpp);
  536. *hpp += BIG_UINT_HEAP_SIZE;
  537. }
  538. if (IS_USMALL(0, uints2[i]))
  539. ui2 = make_small(uints2[i]);
  540. else {
  541. ui2 = uint_to_big(uints2[i], *hpp);
  542. *hpp += BIG_UINT_HEAP_SIZE;
  543. }
  544. res = CONS(*hpp+4, TUPLE3(*hpp, atoms[i], ui1, ui2), res);
  545. *hpp += 6;
  546. }
  547. }
  548. return res;
  549. }
  550. /* *\
  551. * *
  552. \* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
  553. /* make a hash index from an erlang term */
  554. /*
  555. ** There are three hash functions.
  556. ** make_broken_hash: the one used for backward compatibility
  557. ** is called from the bif erlang:hash/2. Should never be used
  558. ** as it a) hashes only a part of binaries, b) hashes bignums really poorly,
  559. ** c) hashes bignums differently on different endian processors and d) hashes
  560. ** small integers with different weights on different bytes.
  561. **
  562. ** make_hash: A hash function that will give the same values for the same
  563. ** terms regardless of the internal representation. Small integers are
  564. ** hashed using the same algorithm as bignums and bignums are hashed
  565. ** independent of the CPU endianess.
  566. ** Make_hash also hashes pids, ports and references like 32 bit numbers
  567. ** (but with different constants).
  568. ** make_hash() is called from the bif erlang:phash/2
  569. **
  570. ** The idea behind the hash algorithm is to produce values suitable for
  571. ** linear dynamic hashing. We cannot choose the range at all while hashing
  572. ** (it's not even supplied to the hashing functions). The good old algorithm
  573. ** [H = H*C+X mod M, where H is the hash value, C is a "random" constant(or M),
  574. ** M is the range, preferably a prime, and X is each byte value] is therefore
  575. ** modified to:
  576. ** H = H*C+X mod 2^32, where C is a large prime. This gives acceptable
  577. ** "spreading" of the hashes, so that later modulo calculations also will give
  578. ** acceptable "spreading" in the range.
  579. ** We really need to hash on bytes, otherwise the
  580. ** upper bytes of a word will be less significant than the lower ones. That's
  581. ** not acceptable at all. For internal use one could maybe optimize by using
  582. ** another hash function, that is less strict but faster. That is, however, not
  583. ** implemented.
  584. **
  585. ** Short semi-formal description of make_hash:
  586. **
  587. ** In make_hash, the number N is treated like this:
  588. ** Abs(N) is hashed bytewise with the least significant byte, B(0), first.
  589. ** The number of bytes (J) to calculate hash on in N is
  590. ** (the number of _32_ bit words needed to store the unsigned
  591. ** value of abs(N)) * 4.
  592. ** X = FUNNY_NUMBER2
  593. ** If N < 0, Y = FUNNY_NUMBER4 else Y = FUNNY_NUMBER3.
  594. ** The hash value is Y*h(J) mod 2^32 where h(J) is calculated like
  595. ** h(0) = <initial hash>
  596. ** h(i) = h(i-i)*X + B(i-1)
  597. ** The above should hold regardless of internal representation.
  598. ** Pids are hashed like small numbers but with differrent constants, as are
  599. ** ports.
  600. ** References are hashed like ports but only on the least significant byte.
  601. ** Binaries are hashed on all bytes (not on the 15 first as in
  602. ** make_broken_hash()).
  603. ** Bytes in lists (possibly text strings) use a simpler multiplication inlined
  604. ** in the handling of lists, that is an optimization.
  605. ** Everything else is like in the old hash (make_broken_hash()).
  606. **
  607. ** make_hash2() is faster than make_hash, in particular for bignums
  608. ** and binaries, and produces better hash values.
  609. */
  610. /* some prime numbers just above 2 ^ 28 */
  611. #define FUNNY_NUMBER1 268440163
  612. #define FUNNY_NUMBER2 268439161
  613. #define FUNNY_NUMBER3 268435459
  614. #define FUNNY_NUMBER4 268436141
  615. #define FUNNY_NUMBER5 268438633
  616. #define FUNNY_NUMBER6 268437017
  617. #define FUNNY_NUMBER7 268438039
  618. #define FUNNY_NUMBER8 268437511
  619. #define FUNNY_NUMBER9 268439627
  620. #define FUNNY_NUMBER10 268440479
  621. #define FUNNY_NUMBER11 268440577
  622. #define FUNNY_NUMBER12 268440581
  623. static Uint32
  624. hash_binary_bytes(Eterm bin, Uint sz, Uint32 hash)
  625. {
  626. byte* ptr;
  627. Uint bitoffs;
  628. Uint bitsize;
  629. ERTS_GET_BINARY_BYTES(bin, ptr, bitoffs, bitsize);
  630. if (bitoffs == 0) {
  631. while (sz--) {
  632. hash = hash*FUNNY_NUMBER1 + *ptr++;
  633. }
  634. if (bitsize > 0) {
  635. byte b = *ptr;
  636. b >>= 8 - bitsize;
  637. hash = (hash*FUNNY_NUMBER1 + b) * FUNNY_NUMBER12 + bitsize;
  638. }
  639. } else {
  640. Uint previous = *ptr++;
  641. Uint b;
  642. Uint lshift = bitoffs;
  643. Uint rshift = 8 - lshift;
  644. while (sz--) {
  645. b = (previous << lshift) & 0xFF;
  646. previous = *ptr++;
  647. b |= previous >> rshift;
  648. hash = hash*FUNNY_NUMBER1 + b;
  649. }
  650. if (bitsize > 0) {
  651. b = (previous << lshift) & 0xFF;
  652. previous = *ptr++;
  653. b |= previous >> rshift;
  654. b >>= 8 - bitsize;
  655. hash = (hash*FUNNY_NUMBER1 + b) * FUNNY_NUMBER12 + bitsize;
  656. }
  657. }
  658. return hash;
  659. }
  660. Uint32 make_hash(Eterm term_arg)
  661. {
  662. DECLARE_WSTACK(stack);
  663. Eterm term = term_arg;
  664. Eterm hash = 0;
  665. unsigned op;
  666. /* Must not collide with the real tag_val_def's: */
  667. #define MAKE_HASH_TUPLE_OP 0x10
  668. #define MAKE_HASH_FUN_OP 0x11
  669. #define MAKE_HASH_CDR_PRE_OP 0x12
  670. #define MAKE_HASH_CDR_POST_OP 0x13
  671. /*
  672. ** Convenience macro for calculating a bytewise hash on an unsigned 32 bit
  673. ** integer.
  674. ** If the endianess is known, we could be smarter here,
  675. ** but that gives no significant speedup (on a sparc at least)
  676. */
  677. #define UINT32_HASH_STEP(Expr, Prime1) \
  678. do { \
  679. Uint32 x = (Uint32) (Expr); \
  680. hash = \
  681. (((((hash)*(Prime1) + (x & 0xFF)) * (Prime1) + \
  682. ((x >> 8) & 0xFF)) * (Prime1) + \
  683. ((x >> 16) & 0xFF)) * (Prime1) + \
  684. (x >> 24)); \
  685. } while(0)
  686. #define UINT32_HASH_RET(Expr, Prime1, Prime2) \
  687. UINT32_HASH_STEP(Expr, Prime1); \
  688. hash = hash * (Prime2); \
  689. break
  690. /*
  691. * Significant additions needed for real 64 bit port with larger fixnums.
  692. */
  693. /*
  694. * Note, for the simple 64bit port, not utilizing the
  695. * larger word size this function will work without modification.
  696. */
  697. tail_recur:
  698. op = tag_val_def(term);
  699. for (;;) {
  700. switch (op) {
  701. case NIL_DEF:
  702. hash = hash*FUNNY_NUMBER3 + 1;
  703. break;
  704. case ATOM_DEF:
  705. hash = hash*FUNNY_NUMBER1 +
  706. (atom_tab(atom_val(term))->slot.bucket.hvalue);
  707. break;
  708. case SMALL_DEF:
  709. {
  710. Sint y1 = signed_val(term);
  711. Uint y2 = y1 < 0 ? -(Uint)y1 : y1;
  712. UINT32_HASH_STEP(y2, FUNNY_NUMBER2);
  713. #if defined(ARCH_64) && !HALFWORD_HEAP
  714. if (y2 >> 32)
  715. UINT32_HASH_STEP(y2 >> 32, FUNNY_NUMBER2);
  716. #endif
  717. hash *= (y1 < 0 ? FUNNY_NUMBER4 : FUNNY_NUMBER3);
  718. break;
  719. }
  720. case BINARY_DEF:
  721. {
  722. Uint sz = binary_size(term);
  723. hash = hash_binary_bytes(term, sz, hash);
  724. hash = hash*FUNNY_NUMBER4 + sz;
  725. break;
  726. }
  727. case EXPORT_DEF:
  728. {
  729. Export* ep = *((Export **) (export_val(term) + 1));
  730. hash = hash * FUNNY_NUMBER11 + ep->code[2];
  731. hash = hash*FUNNY_NUMBER1 +
  732. (atom_tab(atom_val(ep->code[0]))->slot.bucket.hvalue);
  733. hash = hash*FUNNY_NUMBER1 +
  734. (atom_tab(atom_val(ep->code[1]))->slot.bucket.hvalue);
  735. break;
  736. }
  737. case FUN_DEF:
  738. {
  739. ErlFunThing* funp = (ErlFunThing *) fun_val(term);
  740. Uint num_free = funp->num_free;
  741. hash = hash * FUNNY_NUMBER10 + num_free;
  742. hash = hash*FUNNY_NUMBER1 +
  743. (atom_tab(atom_val(funp->fe->module))->slot.bucket.hvalue);
  744. hash = hash*FUNNY_NUMBER2 + funp->fe->old_index;
  745. hash = hash*FUNNY_NUMBER2 + funp->fe->old_uniq;
  746. if (num_free > 0) {
  747. if (num_free > 1) {
  748. WSTACK_PUSH3(stack, (UWord) &funp->env[1], (num_free-1), MAKE_HASH_FUN_OP);
  749. }
  750. term = funp->env[0];
  751. goto tail_recur;
  752. }
  753. break;
  754. }
  755. case PID_DEF:
  756. UINT32_HASH_RET(internal_pid_number(term),FUNNY_NUMBER5,FUNNY_NUMBER6);
  757. case EXTERNAL_PID_DEF:
  758. UINT32_HASH_RET(external_pid_number(term),FUNNY_NUMBER5,FUNNY_NUMBER6);
  759. case PORT_DEF:
  760. UINT32_HASH_RET(internal_port_number(term),FUNNY_NUMBER9,FUNNY_NUMBER10);
  761. case EXTERNAL_PORT_DEF:
  762. UINT32_HASH_RET(external_port_number(term),FUNNY_NUMBER9,FUNNY_NUMBER10);
  763. case REF_DEF:
  764. UINT32_HASH_RET(internal_ref_numbers(term)[0],FUNNY_NUMBER9,FUNNY_NUMBER10);
  765. case EXTERNAL_REF_DEF:
  766. UINT32_HASH_RET(external_ref_numbers(term)[0],FUNNY_NUMBER9,FUNNY_NUMBER10);
  767. case FLOAT_DEF:
  768. {
  769. FloatDef ff;
  770. GET_DOUBLE(term, ff);
  771. hash = hash*FUNNY_NUMBER6 + (ff.fw[0] ^ ff.fw[1]);
  772. break;
  773. }
  774. case MAKE_HASH_CDR_PRE_OP:
  775. term = (Eterm) WSTACK_POP(stack);
  776. if (is_not_list(term)) {
  777. WSTACK_PUSH(stack, (UWord) MAKE_HASH_CDR_POST_OP);
  778. goto tail_recur;
  779. }
  780. /* fall through */
  781. case LIST_DEF:
  782. {
  783. Eterm* list = list_val(term);
  784. while(is_byte(*list)) {
  785. /* Optimization for strings.
  786. ** Note that this hash is different from a 'small' hash,
  787. ** as multiplications on a Sparc is so slow.
  788. */
  789. hash = hash*FUNNY_NUMBER2 + unsigned_val(*list);
  790. if (is_not_list(CDR(list))) {
  791. WSTACK_PUSH(stack, MAKE_HASH_CDR_POST_OP);
  792. term = CDR(list);
  793. goto tail_recur;
  794. }
  795. list = list_val(CDR(list));
  796. }
  797. WSTACK_PUSH2(stack, CDR(list), MAKE_HASH_CDR_PRE_OP);
  798. term = CAR(list);
  799. goto tail_recur;
  800. }
  801. case MAKE_HASH_CDR_POST_OP:
  802. hash *= FUNNY_NUMBER8;
  803. break;
  804. case BIG_DEF:
  805. /* Note that this is the exact same thing as the hashing of smalls.*/
  806. {
  807. Eterm* ptr = big_val(term);
  808. Uint n = BIG_SIZE(ptr);
  809. Uint k = n-1;
  810. ErtsDigit d;
  811. int is_neg = BIG_SIGN(ptr);
  812. Uint i;
  813. int j;
  814. for (i = 0; i < k; i++) {
  815. d = BIG_DIGIT(ptr, i);
  816. for(j = 0; j < sizeof(ErtsDigit); ++j) {
  817. hash = (hash*FUNNY_NUMBER2) + (d & 0xff);
  818. d >>= 8;
  819. }
  820. }
  821. d = BIG_DIGIT(ptr, k);
  822. k = sizeof(ErtsDigit);
  823. #if defined(ARCH_64) && !HALFWORD_HEAP
  824. if (!(d >> 32))
  825. k /= 2;
  826. #endif
  827. for(j = 0; j < (int)k; ++j) {
  828. hash = (hash*FUNNY_NUMBER2) + (d & 0xff);
  829. d >>= 8;
  830. }
  831. hash *= is_neg ? FUNNY_NUMBER4 : FUNNY_NUMBER3;
  832. break;
  833. }
  834. case TUPLE_DEF:
  835. {
  836. Eterm* ptr = tuple_val(term);
  837. Uint arity = arityval(*ptr);
  838. WSTACK_PUSH3(stack, (UWord) arity, (UWord)(ptr+1), (UWord) arity);
  839. op = MAKE_HASH_TUPLE_OP;
  840. }/*fall through*/
  841. case MAKE_HASH_TUPLE_OP:
  842. case MAKE_HASH_FUN_OP:
  843. {
  844. Uint i = (Uint) WSTACK_POP(stack);
  845. Eterm* ptr = (Eterm*) WSTACK_POP(stack);
  846. if (i != 0) {
  847. term = *ptr;
  848. WSTACK_PUSH3(stack, (UWord)(ptr+1), (UWord) i-1, (UWord) op);
  849. goto tail_recur;
  850. }
  851. if (op == MAKE_HASH_TUPLE_OP) {
  852. Uint32 arity = (Uint32) WSTACK_POP(stack);
  853. hash = hash*FUNNY_NUMBER9 + arity;
  854. }
  855. break;
  856. }
  857. default:
  858. erl_exit(1, "Invalid tag in make_hash(0x%X,0x%X)\n", term, op);
  859. return 0;
  860. }
  861. if (WSTACK_ISEMPTY(stack)) break;
  862. op = WSTACK_POP(stack);
  863. }
  864. DESTROY_WSTACK(stack);
  865. return hash;
  866. #undef UINT32_HASH_STEP
  867. #undef UINT32_HASH_RET
  868. }
  869. /* Hash function suggested by Bob Jenkins. */
  870. #define MIX(a,b,c) \
  871. do { \
  872. a -= b; a -= c; a ^= (c>>13); \
  873. b -= c; b -= a; b ^= (a<<8); \
  874. c -= a; c -= b; c ^= (b>>13); \
  875. a -= b; a -= c; a ^= (c>>12); \
  876. b -= c; b -= a; b ^= (a<<16); \
  877. c -= a; c -= b; c ^= (b>>5); \
  878. a -= b; a -= c; a ^= (c>>3); \
  879. b -= c; b -= a; b ^= (a<<10); \
  880. c -= a; c -= b; c ^= (b>>15); \
  881. } while(0)
  882. #define HCONST 0x9e3779b9UL /* the golden ratio; an arbitrary value */
  883. Uint32
  884. block_hash(byte *k, unsigned length, Uint32 initval)
  885. {
  886. Uint32 a,b,c;
  887. unsigned len;
  888. /* Set up the internal state */
  889. len = length;
  890. a = b = HCONST;
  891. c = initval; /* the previous hash value */
  892. while (len >= 12)
  893. {
  894. a += (k[0] +((Uint32)k[1]<<8) +((Uint32)k[2]<<16) +((Uint32)k[3]<<24));
  895. b += (k[4] +((Uint32)k[5]<<8) +((Uint32)k[6]<<16) +((Uint32)k[7]<<24));
  896. c += (k[8] +((Uint32)k[9]<<8) +((Uint32)k[10]<<16)+((Uint32)k[11]<<24));
  897. MIX(a,b,c);
  898. k += 12; len -= 12;
  899. }
  900. c += length;
  901. switch(len) /* all the case statements fall through */
  902. {
  903. case 11: c+=((Uint32)k[10]<<24);
  904. case 10: c+=((Uint32)k[9]<<16);
  905. case 9 : c+=((Uint32)k[8]<<8);
  906. /* the first byte of c is reserved for the length */
  907. case 8 : b+=((Uint32)k[7]<<24);
  908. case 7 : b+=((Uint32)k[6]<<16);
  909. case 6 : b+=((Uint32)k[5]<<8);
  910. case 5 : b+=k[4];
  911. case 4 : a+=((Uint32)k[3]<<24);
  912. case 3 : a+=((Uint32)k[2]<<16);
  913. case 2 : a+=((Uint32)k[1]<<8);
  914. case 1 : a+=k[0];
  915. /* case 0: nothing left to add */
  916. }
  917. MIX(a,b,c);
  918. return c;
  919. }
  920. Uint32
  921. make_hash2(Eterm term)
  922. {
  923. Uint32 hash;
  924. DeclareTmpHeapNoproc(tmp_big,2);
  925. /* (HCONST * {2, ..., 14}) mod 2^32 */
  926. #define HCONST_2 0x3c6ef372UL
  927. #define HCONST_3 0xdaa66d2bUL
  928. #define HCONST_4 0x78dde6e4UL
  929. #define HCONST_5 0x1715609dUL
  930. #define HCONST_6 0xb54cda56UL
  931. #define HCONST_7 0x5384540fUL
  932. #define HCONST_8 0xf1bbcdc8UL
  933. #define HCONST_9 0x8ff34781UL
  934. #define HCONST_10 0x2e2ac13aUL
  935. #define HCONST_11 0xcc623af3UL
  936. #define HCONST_12 0x6a99b4acUL
  937. #define HCONST_13 0x08d12e65UL
  938. #define HCONST_14 0xa708a81eUL
  939. #define HCONST_15 0x454021d7UL
  940. #define UINT32_HASH_2(Expr1, Expr2, AConst) \
  941. do { \
  942. Uint32 a,b; \
  943. a = AConst + (Uint32) (Expr1); \
  944. b = AConst + (Uint32) (Expr2); \
  945. MIX(a,b,hash); \
  946. } while(0)
  947. #define UINT32_HASH(Expr, AConst) UINT32_HASH_2(Expr, 0, AConst)
  948. #define SINT32_HASH(Expr, AConst) \
  949. do { \
  950. Sint32 y = (Sint32) (Expr); \
  951. if (y < 0) { \
  952. UINT32_HASH(-y, AConst); \
  953. /* Negative numbers are unnecessarily mixed twice. */ \
  954. } \
  955. UINT32_HASH(y, AConst); \
  956. } while(0)
  957. #define IS_SSMALL28(x) (((Uint) (((x) >> (28-1)) + 1)) < 2)
  958. /* Optimization. Simple cases before declaration of estack. */
  959. if (primary_tag(term) == TAG_PRIMARY_IMMED1) {
  960. switch (term & _TAG_IMMED1_MASK) {
  961. case _TAG_IMMED1_IMMED2:
  962. switch (term & _TAG_IMMED2_MASK) {
  963. case _TAG_IMMED2_ATOM:
  964. /* Fast, but the poor hash value should be mixed. */
  965. return atom_tab(atom_val(term))->slot.bucket.hvalue;
  966. }
  967. break;
  968. case _TAG_IMMED1_SMALL:
  969. {
  970. Sint x = signed_val(term);
  971. if (SMALL_BITS > 28 && !IS_SSMALL28(x)) {
  972. term = small_to_big(x, tmp_big);
  973. break;
  974. }
  975. hash = 0;
  976. SINT32_HASH(x, HCONST);
  977. return hash;
  978. }
  979. }
  980. };
  981. {
  982. Eterm tmp;
  983. DECLARE_ESTACK(s);
  984. UseTmpHeapNoproc(2);
  985. hash = 0;
  986. for (;;) {
  987. switch (primary_tag(term)) {
  988. case TAG_PRIMARY_LIST:
  989. {
  990. int c = 0;
  991. Uint32 sh = 0;
  992. Eterm* ptr = list_val(term);
  993. while (is_byte(*ptr)) {
  994. /* Optimization for strings. */
  995. sh = (sh << 8) + unsigned_val(*ptr);
  996. if (c == 3) {
  997. UINT32_HASH(sh, HCONST_4);
  998. c = sh = 0;
  999. } else {
  1000. c++;
  1001. }
  1002. term = CDR(ptr);
  1003. if (is_not_list(term))
  1004. break;
  1005. ptr = list_val(term);
  1006. }
  1007. if (c > 0)
  1008. UINT32_HASH(sh, HCONST_4);
  1009. if (is_list(term)) {
  1010. term = *ptr;
  1011. tmp = *++ptr;
  1012. ESTACK_PUSH(s, tmp);
  1013. }
  1014. }
  1015. break;
  1016. case TAG_PRIMARY_BOXED:
  1017. {
  1018. Eterm hdr = *boxed_val(term);
  1019. ASSERT(is_header(hdr));
  1020. switch (hdr & _TAG_HEADER_MASK) {
  1021. case ARITYVAL_SUBTAG:
  1022. {
  1023. int i;
  1024. int arity = header_arity(hdr);
  1025. Eterm* elem = tuple_val(term);
  1026. UINT32_HASH(arity, HCONST_9);
  1027. if (arity == 0) /* Empty tuple */
  1028. goto hash2_common;
  1029. for (i = arity; i >= 2; i--) {
  1030. tmp = elem[i];
  1031. ESTACK_PUSH(s, tmp);
  1032. }
  1033. term = elem[1];
  1034. }
  1035. break;
  1036. case EXPORT_SUBTAG:
  1037. {
  1038. Export* ep = *((Export **) (export_val(term) + 1));
  1039. UINT32_HASH_2
  1040. (ep->code[2],
  1041. atom_tab(atom_val(ep->code[0]))->slot.bucket.hvalue,
  1042. HCONST);
  1043. UINT32_HASH
  1044. (atom_tab(atom_val(ep->code[1]))->slot.bucket.hvalue,
  1045. HCONST_14);
  1046. goto hash2_common;
  1047. }
  1048. case FUN_SUBTAG:
  1049. {
  1050. ErlFunThing* funp = (ErlFunThing *) fun_val(term);
  1051. Uint num_free = funp->num_free;
  1052. UINT32_HASH_2
  1053. (num_free,
  1054. atom_tab(atom_val(funp->fe->module))->slot.bucket.hvalue,
  1055. HCONST);
  1056. UINT32_HASH_2
  1057. (funp->fe->old_index, funp->fe->old_uniq, HCONST);
  1058. if (num_free == 0) {
  1059. goto hash2_common;
  1060. } else {
  1061. Eterm* bptr = funp->env + num_free - 1;
  1062. while (num_free-- > 1) {
  1063. term = *bptr--;
  1064. ESTACK_PUSH(s, term);
  1065. }
  1066. term = *bptr;
  1067. }
  1068. }
  1069. break;
  1070. case REFC_BINARY_SUBTAG:
  1071. case HEAP_BINARY_SUBTAG:
  1072. case SUB_BINARY_SUBTAG:
  1073. {
  1074. byte* bptr;
  1075. unsigned sz = binary_size(term);
  1076. Uint32 con = HCONST_13 + hash;
  1077. Uint bitoffs;
  1078. Uint bitsize;
  1079. ERTS_GET_BINARY_BYTES(term, bptr, bitoffs, bitsize);
  1080. if (sz == 0 && bitsize == 0) {
  1081. hash = con;
  1082. } else {
  1083. if (bitoffs == 0) {
  1084. hash = block_hash(bptr, sz, con);
  1085. if (bitsize > 0) {
  1086. UINT32_HASH_2(bitsize, (bptr[sz] >> (8 - bitsize)),
  1087. HCONST_15);
  1088. }
  1089. } else {
  1090. byte* buf = (byte *) erts_alloc(ERTS_ALC_T_TMP,
  1091. sz + (bitsize != 0));
  1092. erts_copy_bits(bptr, bitoffs, 1, buf, 0, 1, sz*8+bitsize);
  1093. hash = block_hash(buf, sz, con);
  1094. if (bitsize > 0) {
  1095. UINT32_HASH_2(bitsize, (buf[sz] >> (8 - bitsize)),
  1096. HCONST_15);
  1097. }
  1098. erts_free(ERTS_ALC_T_TMP, (void *) buf);
  1099. }
  1100. }
  1101. goto hash2_common;
  1102. }
  1103. break;
  1104. case POS_BIG_SUBTAG:
  1105. case NEG_BIG_SUBTAG:
  1106. {
  1107. Eterm* ptr = big_val(term);
  1108. Uint i = 0;
  1109. Uint n = BIG_SIZE(ptr);
  1110. Uint32 con = BIG_SIGN(ptr) ? HCONST_10 : HCONST_11;
  1111. #if D_EXP == 16
  1112. do {
  1113. Uint32 x, y;
  1114. x = i < n ? BIG_DIGIT(ptr, i++) : 0;
  1115. x += (Uint32)(i < n ? BIG_DIGIT(ptr, i++) : 0) << 16;
  1116. y = i < n ? BIG_DIGIT(ptr, i++) : 0;
  1117. y += (Uint32)(i < n ? BIG_DIGIT(ptr, i++) : 0) << 16;
  1118. UINT32_HASH_2(x, y, con);
  1119. } while (i < n);
  1120. #elif D_EXP == 32
  1121. do {
  1122. Uint32 x, y;
  1123. x = i < n ? BIG_DIGIT(ptr, i++) : 0;
  1124. y = i < n ? BIG_DIGIT(ptr, i++) : 0;
  1125. UINT32_HASH_2(x, y, con);
  1126. } while (i < n);
  1127. #elif D_EXP == 64
  1128. do {
  1129. Uint t;
  1130. Uint32 x, y;
  1131. t = i < n ? BIG_DIGIT(ptr, i++) : 0;
  1132. x = t & 0xffffffff;
  1133. y = t >> 32;
  1134. UINT32_HASH_2(x, y, con);
  1135. } while (i < n);
  1136. #else
  1137. #error "unsupported D_EXP size"
  1138. #endif
  1139. goto hash2_common;
  1140. }
  1141. break;
  1142. case REF_SUBTAG:
  1143. /* All parts of the ref should be hashed. */
  1144. UINT32_HASH(internal_ref_numbers(term)[0], HCONST_7);
  1145. goto hash2_common;
  1146. break;
  1147. case EXTERNAL_REF_SUBTAG:
  1148. /* All parts of the ref should be hashed. */
  1149. UINT32_HASH(external_ref_numbers(term)[0], HCONST_7);
  1150. goto hash2_common;
  1151. break;
  1152. case EXTERNAL_PID_SUBTAG:
  1153. /* Only 15 bits are hashed. */
  1154. UINT32_HASH(external_pid_number(term), HCONST_5);
  1155. goto hash2_common;
  1156. case EXTERNAL_PORT_SUBTAG:
  1157. /* Only 15 bits are hashed. */
  1158. UINT32_HASH(external_port_number(term), HCONST_6);
  1159. goto hash2_common;
  1160. case FLOAT_SUBTAG:
  1161. {
  1162. FloatDef ff;
  1163. GET_DOUBLE(term, ff);
  1164. #if defined(WORDS_BIGENDIAN)
  1165. UINT32_HASH_2(ff.fw[0], ff.fw[1], HCONST_12);
  1166. #else
  1167. UINT32_HASH_2(ff.fw[1], ff.fw[0], HCONST_12);
  1168. #endif
  1169. goto hash2_common;
  1170. }
  1171. break;
  1172. default:
  1173. erl_exit(1, "Invalid tag in make_hash2(0x%X)\n", term);
  1174. }
  1175. }
  1176. break;
  1177. case TAG_PRIMARY_IMMED1:
  1178. switch (term & _TAG_IMMED1_MASK) {
  1179. case _TAG_IMMED1_PID:
  1180. /* Only 15 bits are hashed. */
  1181. UINT32_HASH(internal_pid_number(term), HCONST_5);
  1182. goto hash2_common;
  1183. case _TAG_IMMED1_PORT:
  1184. /* Only 15 bits are hashed. */
  1185. UINT32_HASH(internal_port_number(term), HCONST_6);
  1186. goto hash2_common;
  1187. case _TAG_IMMED1_IMMED2:
  1188. switch (term & _TAG_IMMED2_MASK) {
  1189. case _TAG_IMMED2_ATOM:
  1190. if (hash == 0)
  1191. /* Fast, but the poor hash value should be mixed. */
  1192. hash = atom_tab(atom_val(term))->slot.bucket.hvalue;
  1193. else
  1194. UINT32_HASH(atom_tab(atom_val(term))->slot.bucket.hvalue,
  1195. HCONST_3);
  1196. goto hash2_common;
  1197. case _TAG_IMMED2_NIL:
  1198. if (hash == 0)
  1199. hash = 3468870702UL;
  1200. else
  1201. UINT32_HASH(NIL_DEF, HCONST_2);
  1202. goto hash2_common;
  1203. default:
  1204. erl_exit(1, "Invalid tag in make_hash2(0x%X)\n", term);
  1205. }
  1206. case _TAG_IMMED1_SMALL:
  1207. {
  1208. Sint x = signed_val(term);
  1209. if (SMALL_BITS > 28 && !IS_SSMALL28(x)) {
  1210. term = small_to_big(x, tmp_big);
  1211. break;
  1212. }
  1213. SINT32_HASH(x, HCONST);
  1214. goto hash2_common;
  1215. }
  1216. }
  1217. break;
  1218. default:
  1219. erl_exit(1, "Invalid tag in make_hash2(0x%X)\n", term);
  1220. hash2_common:
  1221. if (ESTACK_ISEMPTY(s)) {
  1222. DESTROY_ESTACK(s);
  1223. UnUseTmpHeapNoproc(2);
  1224. return hash;
  1225. }
  1226. term = ESTACK_POP(s);
  1227. }
  1228. }
  1229. }
  1230. #undef UINT32_HASH_2
  1231. #undef UINT32_HASH
  1232. #undef SINT32_HASH
  1233. }
  1234. #undef HCONST
  1235. #undef MIX
  1236. Uint32 make_broken_hash(Eterm term)
  1237. {
  1238. Uint32 hash = 0;
  1239. DECLARE_WSTACK(stack);
  1240. unsigned op;
  1241. tail_recur:
  1242. op = tag_val_def(term);
  1243. for (;;) {
  1244. switch (op) {
  1245. case NIL_DEF:
  1246. hash = hash*FUNNY_NUMBER3 + 1;
  1247. break;
  1248. case ATOM_DEF:
  1249. hash = hash*FUNNY_NUMBER1 +
  1250. (atom_tab(atom_val(term))->slot.bucket.hvalue);
  1251. break;
  1252. case SMALL_DEF:
  1253. #if defined(ARCH_64) && !HALFWORD_HEAP
  1254. {
  1255. Sint y1 = signed_val(term);
  1256. Uint y2 = y1 < 0 ? -(Uint)y1 : y1;
  1257. Uint32 y3 = (Uint32) (y2 >> 32);
  1258. int arity = 1;
  1259. #if defined(WORDS_BIGENDIAN)
  1260. if (!IS_SSMALL28(y1))
  1261. { /* like a bignum */
  1262. Uint32 y4 = (Uint32) y2;
  1263. hash = hash*FUNNY_NUMBER2 + ((y4 << 16) | (y4 >> 16));
  1264. if (y3)
  1265. {
  1266. hash = hash*FUNNY_NUMBER2 + ((y3 << 16) | (y3 >> 16));
  1267. arity++;
  1268. }
  1269. hash = hash * (y1 < 0 ? FUNNY_NUMBER3 : FUNNY_NUMBER2) + arity;
  1270. } else {
  1271. hash = hash*FUNNY_NUMBER2 + (((Uint) y1) & 0xfffffff);
  1272. }
  1273. #else
  1274. if (!IS_SSMALL28(y1))
  1275. { /* like a bignum */
  1276. hash = hash*FUNNY_NUMBER2 + ((Uint32) y2);
  1277. if (y3)
  1278. {
  1279. hash = hash*FUNNY_NUMBER2 + y3;
  1280. arity++;
  1281. }
  1282. hash = hash * (y1 < 0 ? FUNNY_NUMBER3 : FUNNY_NUMBER2) + arity;
  1283. } else {
  1284. hash = hash*FUNNY_NUMBER2 + (((Uint) y1) & 0xfffffff);
  1285. }
  1286. #endif
  1287. }
  1288. #else
  1289. hash = hash*FUNNY_NUMBER2 + unsigned_val(term);
  1290. #endif
  1291. break;
  1292. case BINARY_DEF:
  1293. {
  1294. size_t sz = binary_size(term);
  1295. size_t i = (sz < 15) ? sz : 15;
  1296. hash = hash_binary_bytes(term, i, hash);
  1297. hash = hash*FUNNY_NUMBER4 + sz;
  1298. break;
  1299. }
  1300. case EXPORT_DEF:
  1301. {
  1302. Export* ep = *((Export **) (export_val(term) + 1));
  1303. hash = hash * FUNNY_NUMBER11 + ep->code[2];
  1304. hash = hash*FUNNY_NUMBER1 +
  1305. (atom_tab(atom_val(ep->code[0]))->slot.bucket.hvalue);
  1306. hash = hash*FUNNY_NUMBER1 +
  1307. (atom_tab(atom_val(ep->code[1]))->slot.bucket.hvalue);
  1308. break;
  1309. }
  1310. case FUN_DEF:
  1311. {
  1312. ErlFunThing* funp = (ErlFunThing *) fun_val(term);
  1313. Uint num_free = funp->num_free;
  1314. hash = hash * FUNNY_NUMBER10 + num_free;
  1315. hash = hash*FUNNY_NUMBER1 +
  1316. (atom_tab(atom_val(funp->fe->module))->slot.bucket.hvalue);
  1317. hash = hash*FUNNY_NUMBER2 + funp->fe->old_index;
  1318. hash = hash*FUNNY_NUMBER2 + funp->fe->old_uniq;
  1319. if (num_free > 0) {
  1320. if (num_free > 1) {
  1321. WSTACK_PUSH3(stack, (UWord) &funp->env[1], (num_free-1), MAKE_HASH_FUN_OP);
  1322. }
  1323. term = funp->env[0];
  1324. goto tail_recur;
  1325. }
  1326. break;
  1327. }
  1328. case PID_DEF:
  1329. hash = hash*FUNNY_NUMBER5 + internal_pid_number(term);
  1330. break;
  1331. case EXTERNAL_PID_DEF:
  1332. hash = hash*FUNNY_NUMBER5 + external_pid_number(term);
  1333. break;
  1334. case PORT_DEF:
  1335. hash = hash*FUNNY_NUMBER9 + internal_port_number(term);
  1336. break;
  1337. case EXTERNAL_PORT_DEF:
  1338. hash = hash*FUNNY_NUMBER9 + external_port_number(term);
  1339. break;
  1340. case REF_DEF:
  1341. hash = hash*FUNNY_NUMBER9 + internal_ref_numbers(term)[0];
  1342. break;
  1343. case EXTERNAL_REF_DEF:
  1344. hash = hash*FUNNY_NUMBER9 + external_ref_numbers(term)[0];
  1345. break;
  1346. case FLOAT_DEF:
  1347. {
  1348. FloatDef ff;
  1349. GET_DOUBLE(term, ff);
  1350. hash = hash*FUNNY_NUMBER6 + (ff.fw[0] ^ ff.fw[1]);
  1351. }
  1352. break;
  1353. case MAKE_HASH_CDR_PRE_OP:
  1354. term = (Eterm) WSTACK_POP(stack);
  1355. if (is_not_list(term)) {
  1356. WSTACK_PUSH(stack, (UWord) MAKE_HASH_CDR_POST_OP);
  1357. goto tail_recur;
  1358. }
  1359. /*fall through*/
  1360. case LIST_DEF:
  1361. {
  1362. Eterm* list = list_val(term);
  1363. WSTACK_PUSH2(stack, (UWord) CDR(list),
  1364. (UWord) MAKE_HASH_CDR_PRE_OP);
  1365. term = CAR(list);
  1366. goto tail_recur;
  1367. }
  1368. case MAKE_HASH_CDR_POST_OP:
  1369. hash *= FUNNY_NUMBER8;
  1370. break;
  1371. case BIG_DEF:
  1372. {
  1373. Eterm* ptr = big_val(term);
  1374. int is_neg = BIG_SIGN(ptr);
  1375. Uint arity = BIG_ARITY(ptr);
  1376. Uint i = arity;
  1377. ptr++;
  1378. #if D_EXP == 16
  1379. /* hash over 32 bit LE */
  1380. while(i--) {
  1381. hash = hash*FUNNY_NUMBER2 + *ptr++;
  1382. }
  1383. #elif D_EXP == 32
  1384. #if defined(WORDS_BIGENDIAN)
  1385. while(i--) {
  1386. Uint d = *ptr++;
  1387. hash = hash*FUNNY_NUMBER2 + ((d << 16) | (d >> 16));
  1388. }
  1389. #else
  1390. while(i--) {
  1391. hash = hash*FUNNY_NUMBER2 + *ptr++;
  1392. }
  1393. #endif
  1394. #elif D_EXP == 64
  1395. {
  1396. Uint32 h = 0, l;
  1397. #if defined(WORDS_BIGENDIAN)
  1398. while(i--) {
  1399. Uint d = *ptr++;
  1400. l = d & 0xffffffff;
  1401. h = d >> 32;
  1402. hash = hash*FUNNY_NUMBER2 + ((l << 16) | (l >> 16));
  1403. if (h || i)
  1404. hash = hash*FUNNY_NUMBER2 + ((h << 16) | (h >> 16));
  1405. }
  1406. #else
  1407. while(i--) {
  1408. Uint d = *ptr++;
  1409. l = d & 0xffffffff;
  1410. h = d >> 32;
  1411. hash = hash*FUNNY_NUMBER2 + l;
  1412. if (h || i)
  1413. hash = hash*FUNNY_NUMBER2 + h;
  1414. }
  1415. #endif
  1416. /* adjust arity to match 32 bit mode */
  1417. arity = (arity << 1) - (h == 0);
  1418. }
  1419. #else
  1420. #error "unsupported D_EXP size"
  1421. #endif
  1422. hash = hash * (is_neg ? FUNNY_NUMBER3 : FUNNY_NUMBER2) + arity;
  1423. }
  1424. break;
  1425. case TUPLE_DEF:
  1426. {
  1427. Eterm* ptr = tuple_val(term);
  1428. Uint arity = arityval(*ptr);
  1429. WSTACK_PUSH3(stack, (UWord) arity, (UWord) (ptr+1), (UWord) arity);
  1430. op = MAKE_HASH_TUPLE_OP;
  1431. }/*fall through*/
  1432. case MAKE_HASH_TUPLE_OP:
  1433. case MAKE_HASH_FUN_OP:
  1434. {
  1435. Uint i = (Uint) WSTACK_POP(stack);
  1436. Eterm* ptr = (Eterm*) WSTACK_POP(stack);
  1437. if (i != 0) {
  1438. term = *ptr;
  1439. WSTACK_PUSH3(stack, (UWord)(ptr+1), (UWord) i-1, (UWord) op);
  1440. goto tail_recur;
  1441. }
  1442. if (op == MAKE_HASH_TUPLE_OP) {
  1443. Uint32 arity = (UWord) WSTACK_POP(stack);
  1444. hash = hash*FUNNY_NUMBER9 + arity;
  1445. }
  1446. break;
  1447. }
  1448. default:
  1449. erl_exit(1, "Invalid tag in make_broken_hash\n");
  1450. return 0;
  1451. }
  1452. if (WSTACK_ISEMPTY(stack)) break;
  1453. op = (Uint) WSTACK_POP(stack);
  1454. }
  1455. DESTROY_WSTACK(stack);
  1456. return hash;
  1457. #undef MAKE_HASH_TUPLE_OP
  1458. #undef MAKE_HASH_FUN_OP
  1459. #undef MAKE_HASH_CDR_PRE_OP
  1460. #undef MAKE_HASH_CDR_POST_OP
  1461. }
  1462. static int do_send_to_logger(Eterm tag, Eterm gleader, char *buf, int len)
  1463. {
  1464. /* error_logger !
  1465. {notify,{info_msg,gleader,{emulator,"~s~n",[<message as list>]}}} |
  1466. {notify,{error,gleader,{emulator,"~s~n",[<message as list>]}}} |
  1467. {notify,{warning_msg,gleader,{emulator,"~s~n",[<message as list>}]}} */
  1468. Eterm* hp;
  1469. Uint sz;
  1470. Uint gl_sz;
  1471. Eterm gl;
  1472. Eterm list,plist,format,tuple1,tuple2,tuple3;
  1473. ErlOffHeap *ohp;
  1474. ErlHeapFragment *bp = NULL;
  1475. #if !defined(ERTS_SMP)
  1476. Process *p;
  1477. #endif
  1478. ASSERT(is_atom(tag));
  1479. if (len <= 0) {
  1480. return -1;
  1481. }
  1482. #ifndef ERTS_SMP
  1483. if (
  1484. #ifdef USE_THREADS
  1485. !erts_get_scheduler_data() || /* Must be scheduler thread */
  1486. #endif
  1487. (p = erts_whereis_process(NULL, 0, am_error_logger, 0, 0)) == NULL
  1488. || p->status == P_RUNNING) {
  1489. /* buf *always* points to a null terminated string */
  1490. erts_fprintf(stderr, "(no error logger present) %T: \"%s\"\n",
  1491. tag, buf);
  1492. return 0;
  1493. }
  1494. /* So we have an error logger, lets build the message */
  1495. #endif
  1496. gl_sz = IS_CONST(gleader) ? 0 : size_object(gleader);
  1497. sz = len * 2 /* message list */+ 2 /* cons surrounding message list */
  1498. + gl_sz +
  1499. 3 /*outer 2-tuple*/ + 4 /* middle 3-tuple */ + 4 /*inner 3-tuple */ +
  1500. 8 /* "~s~n" */;
  1501. #ifndef ERTS_SMP
  1502. if (sz <= HeapWordsLeft(p)) {
  1503. ohp = &MSO(p);
  1504. hp = HEAP_TOP(p);
  1505. HEAP_TOP(p) += sz;
  1506. } else {
  1507. #endif
  1508. bp = new_message_buffer(sz);
  1509. ohp = &bp->off_heap;
  1510. hp = bp->mem;
  1511. #ifndef ERTS_SMP
  1512. }
  1513. #endif
  1514. gl = (is_nil(gleader)
  1515. ? am_noproc
  1516. : (IS_CONST(gleader)
  1517. ? gleader
  1518. : copy_struct(gleader,gl_sz,&hp,ohp)));
  1519. list = buf_to_intlist(&hp, buf, len, NIL);
  1520. plist = CONS(hp,list,NIL);
  1521. hp += 2;
  1522. format = buf_to_intlist(&hp, "~s~n", 4, NIL);
  1523. tuple1 = TUPLE3(hp, am_emulator, format, plist);
  1524. hp += 4;
  1525. tuple2 = TUPLE3(hp, tag, gl, tuple1);
  1526. hp += 4;
  1527. tuple3 = TUPLE2(hp, am_notify, tuple2);
  1528. #ifdef HARDDEBUG
  1529. erts_fprintf(stderr, "%T\n", tuple3);
  1530. #endif
  1531. #ifdef ERTS_SMP
  1532. {
  1533. Eterm from = erts_get_current_pid();
  1534. if (is_not_internal_pid(from))
  1535. from = NIL;
  1536. erts_queue_error_logger_message(from, tuple3, bp);
  1537. }
  1538. #else
  1539. erts_queue_message(p, NULL /* only used for smp build */, bp, tuple3, NIL);
  1540. #endif
  1541. return 0;
  1542. }
  1543. static ERTS_INLINE int
  1544. send_info_to_logger(Eterm gleader, char *buf, int len)
  1545. {
  1546. return do_send_to_logger(am_info_msg, gleader, buf, len);
  1547. }
  1548. static ERTS_INLINE int
  1549. send_warning_to_logger(Eterm gleader, char *buf, int len)
  1550. {
  1551. Eterm tag;
  1552. switch (erts_error_logger_warnings) {
  1553. case am_info: tag = am_info_msg; break;
  1554. case am_warning: tag = am_warning_msg; break;
  1555. default: tag = am_error; break;
  1556. }
  1557. return do_send_to_logger(tag, gleader, buf, len);
  1558. }
  1559. static ERTS_INLINE int
  1560. send_error_to_logger(Eterm gleader, char *buf, int len)
  1561. {
  1562. return do_send_to_logger(am_error, gleader, buf, len);
  1563. }
  1564. #define LOGGER_DSBUF_INC_SZ 256
  1565. static erts_dsprintf_buf_t *
  1566. grow_logger_dsbuf(erts_dsprintf_buf_t *dsbufp, size_t need)
  1567. {
  1568. size_t size;
  1569. size_t free_size = dsbufp->size - dsbufp->str_len;
  1570. ASSERT(dsbufp && dsbufp->str);
  1571. if (need <= free_size)
  1572. return dsbufp;
  1573. size = need - free_size + LOGGER_DSBUF_INC_SZ;
  1574. size = (((size + LOGGER_DSBUF_INC_SZ - 1) / LOGGER_DSBUF_INC_SZ)
  1575. * LOGGER_DSBUF_INC_SZ);
  1576. size += dsbufp->size;
  1577. ASSERT(dsbufp->str_len + need <= size);
  1578. dsbufp->str = (char *) erts_realloc(ERTS_ALC_T_LOGGER_DSBUF,
  1579. (void *) dsbufp->str,
  1580. size);
  1581. dsbufp->size = size;
  1582. return dsbufp;
  1583. }
  1584. erts_dsprintf_buf_t *
  1585. erts_create_logger_dsbuf(void)
  1586. {
  1587. erts_dsprintf_buf_t init = ERTS_DSPRINTF_BUF_INITER(grow_logger_dsbuf);
  1588. erts_dsprintf_buf_t *dsbufp = erts_alloc(ERTS_ALC_T_LOGGER_DSBUF,
  1589. sizeof(erts_dsprintf_buf_t));
  1590. sys_memcpy((void *) dsbufp, (void *) &init, sizeof(erts_dsprintf_buf_t));
  1591. dsbufp->str = (char *) erts_alloc(ERTS_ALC_T_LOGGER_DSBUF,
  1592. LOGGER_DSBUF_INC_SZ);
  1593. dsbufp->str[0] = '\0';
  1594. dsbufp->size = LOGGER_DSBUF_INC_SZ;
  1595. return dsbufp;
  1596. }
  1597. static ERTS_INLINE void
  1598. destroy_logger_dsbuf(erts_dsprintf_buf_t *dsbufp)
  1599. {
  1600. ASSERT(dsbufp && dsbufp->str);
  1601. erts_free(ERTS_ALC_T_LOGGER_DSBUF, (void *) dsbufp->str);
  1602. erts_free(ERTS_ALC_T_LOGGER_DSBUF, (void *) dsbufp);
  1603. }
  1604. int
  1605. erts_send_info_to_logger(Eterm gleader, erts_dsprintf_buf_t *dsbufp)
  1606. {
  1607. int res;
  1608. res = send_info_to_logger(gleader, dsbufp->str, dsbufp->str_len);
  1609. destroy_logger_dsbuf(dsbufp);
  1610. return res;
  1611. }
  1612. int
  1613. erts_send_warning_to_logger(Eterm gleader, erts_dsprintf_buf_t *dsbufp)
  1614. {
  1615. int res;
  1616. res = send_warning_to_logger(gleader, dsbufp->str, dsbufp->str_len);
  1617. destroy_logger_dsbuf(dsbufp);
  1618. return res;
  1619. }
  1620. int
  1621. erts_send_error_to_logger(Eterm gleader, erts_dsprintf_buf_t *dsbufp)
  1622. {
  1623. int res;
  1624. res = send_error_to_logger(gleader, dsbufp->str, dsbufp->str_len);
  1625. destroy_logger_dsbuf(dsbufp);
  1626. return res;
  1627. }
  1628. int
  1629. erts_send_info_to_logger_str(Eterm gleader, char *str)
  1630. {
  1631. return send_info_to_logger(gleader, str, sys_strlen(str));
  1632. }
  1633. int
  1634. erts_send_warning_to_logger_str(Eterm gleader, char *str)
  1635. {
  1636. return send_warning_to_logger(gleader, str, sys_strlen(str));
  1637. }
  1638. int
  1639. erts_send_error_to_logger_str(Eterm gleader, char *str)
  1640. {
  1641. return send_error_to_logger(gleader, str, sys_strlen(str));
  1642. }
  1643. int
  1644. erts_send_info_to_logger_nogl(erts_dsprintf_buf_t *dsbuf)
  1645. {
  1646. return erts_send_info_to_logger(NIL, dsbuf);
  1647. }
  1648. int
  1649. erts_send_warning_to_logger_nogl(erts_dsprintf_buf_t *dsbuf)
  1650. {
  1651. return erts_send_warning_to_logger(NIL, dsbuf);
  1652. }
  1653. int
  1654. erts_send_error_to_logger_nogl(erts_dsprintf_buf_t *dsbuf)
  1655. {
  1656. return erts_send_error_to_logger(NIL, dsbuf);
  1657. }
  1658. int
  1659. erts_send_info_to_logger_str_nogl(char *str)
  1660. {
  1661. return erts_send_info_to_logger_str(NIL, str);
  1662. }
  1663. int
  1664. erts_send_warning_to_logger_str_nogl(char *str)
  1665. {
  1666. return erts_send_warning_to_logger_str(NIL, str);
  1667. }
  1668. int
  1669. erts_send_error_to_logger_str_nogl(char *str)
  1670. {
  1671. return erts_send_error_to_logger_str(NIL, str);
  1672. }
  1673. #define TMP_DSBUF_INC_SZ 256
  1674. static erts_dsprintf_buf_t *
  1675. grow_tmp_dsbuf(erts_dsprintf_buf_t *dsbufp, size_t need)
  1676. {
  1677. size_t size;
  1678. size_t free_size = dsbufp->size - dsbufp->str_len;
  1679. ASSERT(dsbufp);
  1680. if (need <= free_size)
  1681. return dsbufp;
  1682. size = need - free_size + TMP_DSBUF_INC_SZ;
  1683. size = ((size + TMP_DSBUF_INC_SZ - 1)/TMP_DSBUF_INC_SZ)*TMP_DSBUF_INC_SZ;
  1684. size += dsbufp->size;
  1685. ASSERT(dsbufp->str_len + need <= size);
  1686. dsbufp->str = (char *) erts_realloc(ERTS_ALC_T_TMP_DSBUF,
  1687. (void *) dsbufp->str,
  1688. size);
  1689. dsbufp->size = size;
  1690. return dsbufp;
  1691. }
  1692. erts_dsprintf_buf_t *
  1693. erts_create_tmp_dsbuf(Uint size)
  1694. {
  1695. Uint init_size = size ? size : TMP_DSBUF_INC_SZ;
  1696. erts_dsprintf_buf_t init = ERTS_DSPRINTF_BUF_INITER(grow_tmp_dsbuf);
  1697. erts_dsprintf_buf_t *dsbufp = erts_alloc(ERTS_ALC_T_TMP_DSBUF,
  1698. sizeof(erts_dsprintf_buf_t));
  1699. sys_memcpy((void *) dsbufp, (void *) &init, sizeof(erts_dsprintf_buf_t));
  1700. dsbufp->str = (char *) erts_alloc(ERTS_ALC_T_TMP_DSBUF, init_size);
  1701. dsbufp->str[0] = '\0';
  1702. dsbufp->size = init_size;
  1703. return dsbufp;
  1704. }
  1705. void
  1706. erts_destroy_tmp_dsbuf(erts_dsprintf_buf_t *dsbufp)
  1707. {
  1708. if (dsbufp->str)
  1709. erts_free(ERTS_ALC_T_TMP_DSBUF, (void *) dsbufp->str);
  1710. erts_free(ERTS_ALC_T_TMP_DSBUF, (void *) dsbufp);
  1711. }
  1712. /* eq and cmp are written as separate functions a eq is a little faster */
  1713. /*
  1714. * Test for equality of two terms.
  1715. * Returns 0 if not equal, or a non-zero value otherwise.
  1716. */
  1717. #if HALFWORD_HEAP
  1718. int eq_rel(Eterm a, Eterm* a_base, Eterm b, Eterm* b_base)
  1719. #else
  1720. int eq(Eterm a, Eterm b)
  1721. #endif
  1722. {
  1723. DECLARE_WSTACK(stack);
  1724. Sint sz;
  1725. Eterm* aa;
  1726. Eterm* bb;
  1727. tailrecur:
  1728. if (is_same(a, a_base, b, b_base)) goto pop_next;
  1729. tailrecur_ne:
  1730. switch (primary_tag(a)) {
  1731. case TAG_PRIMARY_LIST:
  1732. if (is_list(b)) {
  1733. Eterm* aval = list_val_rel(a, a_base);
  1734. Eterm* bval = list_val_rel(b, b_base);
  1735. while (1) {
  1736. Eterm atmp = CAR(aval);
  1737. Eterm btmp = CAR(bval);
  1738. if (!is_same(atmp,a_base,btmp,b_base)) {
  1739. WSTACK_PUSH2(stack,(UWord) CDR(bval),(UWord) CDR(aval));
  1740. a = atmp;
  1741. b = btmp;
  1742. goto tailrecur_ne;
  1743. }
  1744. atmp = CDR(aval);
  1745. btmp = CDR(bval);
  1746. if (is_same(atmp,a_base,btmp,b_base)) {
  1747. goto pop_next;
  1748. }
  1749. if (is_not_list(atmp) || is_not_list(btmp)) {
  1750. a = atmp;
  1751. b = btmp;
  1752. goto tailrecur_ne;
  1753. }
  1754. aval = list_val_rel(atmp, a_base);
  1755. bval = list_val_rel(btmp, b_base);
  1756. }
  1757. }
  1758. break; /* not equal */
  1759. case TAG_PRIMARY_BOXED:
  1760. {
  1761. Eterm hdr = *boxed_val_rel(a,a_base);
  1762. switch (hdr & _TAG_HEADER_MASK) {
  1763. case ARITYVAL_SUBTAG:
  1764. {
  1765. aa = tuple_val_rel(a, a_base);
  1766. if (!is_boxed(b) || *boxed_val_rel(b,b_base) != *aa)
  1767. goto not_equal;
  1768. bb = tuple_val_rel(b,b_base);
  1769. if ((sz = arityval(*aa)) == 0) goto pop_next;
  1770. ++aa;
  1771. ++bb;
  1772. goto term_array;
  1773. }
  1774. case REFC_BINARY_SUBTAG:
  1775. case HEAP_BINARY_SUBTAG:
  1776. case SUB_BINARY_SUBTAG:
  1777. {
  1778. byte* a_ptr;
  1779. byte* b_ptr;
  1780. size_t a_size;
  1781. size_t b_size;
  1782. Uint a_bitsize;
  1783. Uint b_bitsize;
  1784. Uint a_bitoffs;
  1785. Uint b_bitoffs;
  1786. if (!is_binary_rel(b,b_base)) {
  1787. goto not_equal;
  1788. }
  1789. a_size = binary_size_rel(a,a_base);
  1790. b_size = binary_size_rel(b,b_base);
  1791. if (a_size != b_size) {
  1792. goto not_equal;
  1793. }
  1794. ERTS_GET_BINARY_BYTES_REL(a, a_ptr, a_bitoffs, a_bitsize, a_base);
  1795. ERTS_GET_BINARY_BYTES_REL(b, b_ptr, b_bitoffs, b_bitsize, b_base);
  1796. if ((a_bitsize | b_bitsize | a_bitoffs | b_bitoffs) == 0) {
  1797. if (sys_memcmp(a_ptr, b_ptr, a_size) == 0) goto pop_next;
  1798. } else if (a_bitsize == b_bitsize) {
  1799. if (erts_cmp_bits(a_ptr, a_bitoffs, b_ptr, b_bitoffs,
  1800. (a_size << 3) + a_bitsize) == 0) goto pop_next;
  1801. }
  1802. break; /* not equal */
  1803. }
  1804. case EXPORT_SUBTAG:
  1805. {
  1806. if (is_export_rel(b,b_base)) {
  1807. Export* a_exp = *((Export **) (export_val_rel(a,a_base) + 1));
  1808. Export* b_exp = *((Export **) (export_val_rel(b,b_base) + 1));
  1809. if (a_exp == b_exp) goto pop_next;
  1810. }
  1811. break; /* not equal */
  1812. }
  1813. case FUN_SUBTAG:
  1814. {
  1815. ErlFunThing* f1;
  1816. ErlFunThing* f2;
  1817. if (!is_fun_rel(b,b_base))
  1818. goto not_equal;
  1819. f1 = (ErlFunThing *) fun_val_rel(a,a_base);
  1820. f2 = (ErlFunThing *) fun_val_rel(b,b_base);
  1821. if (f1->fe->module != f2->fe->module ||
  1822. f1->fe->old_index != f2->fe->old_index ||
  1823. f1->fe->old_uniq != f2->fe->old_uniq ||
  1824. f1->num_free != f2->num_free) {
  1825. goto not_equal;
  1826. }
  1827. if ((sz = f1->num_free) == 0) goto pop_next;
  1828. aa = f1->env;
  1829. bb = f2->env;
  1830. goto term_array;
  1831. }
  1832. case EXTERNAL_PID_SUBTAG:
  1833. case EXTE

Large files files are truncated, but you can click here to view the full file