4
* Copyright Ericsson AB 1996-2009. All Rights Reserved.
4
* Copyright Ericsson AB 1996-2011. All Rights Reserved.
6
6
* The contents of this file are subject to the Erlang Public License,
7
7
* Version 1.1, (the "License"); you may not use this file except in
8
8
* compliance with the License. You should have received a copy of the
9
9
* Erlang Public License along with this software. If not, it can be
10
10
* retrieved online at http://www.erlang.org/.
12
12
* Software distributed under the License is distributed on an "AS IS"
13
13
* basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
14
14
* the License for the specific language governing rights and limitations
15
15
* under the License.
49
49
#define in_area(ptr,start,nbytes) ((Uint)((char*)(ptr) - (char*)(start)) < (nbytes))
51
51
#define MAX_STRING_LEN 0xffff
52
#define dec_set_creation(nodename,creat) \
53
(((nodename) == erts_this_node->sysname && (creat) == ORIG_CREATION) \
54
? erts_this_node->creation \
53
#define is_valid_creation(Cre) ((unsigned)(Cre) < MAX_CREATION || (Cre) == INTERNAL_CREATION)
57
55
#undef ERTS_DEBUG_USE_DIST_SEP
69
* For backward compatibility reasons, only encode integers that
70
* fit in 28 bits (signed) using INTEGER_EXT.
66
/* Does Sint fit in Sint32?
72
#define IS_SSMALL28(x) (((Uint) (((x) >> (28-1)) + 1)) < 2)
68
#define IS_SSMALL32(x) (((Uint) (((x) >> (32-1)) + 1)) < 2)
75
71
* Valid creations for nodes are 1, 2, or 3. 0 can also be sent
88
static byte* enc_term(ErtsAtomCacheMap *, Eterm, byte*, Uint32);
84
static byte* enc_term(ErtsAtomCacheMap *, Eterm, byte*, Uint32, struct erl_off_heap_header** off_heap);
89
85
static Uint is_external_string(Eterm obj, int* p_is_string);
90
86
static byte* enc_atom(ErtsAtomCacheMap *, Eterm, byte*, Uint32);
91
87
static byte* enc_pid(ErtsAtomCacheMap *, Eterm, byte*, Uint32);
92
88
static byte* dec_term(ErtsDistExternal *, Eterm**, byte*, ErlOffHeap*, Eterm*);
93
89
static byte* dec_atom(ErtsDistExternal *, byte*, Eterm*);
94
90
static byte* dec_pid(ErtsDistExternal *, Eterm**, byte*, ErlOffHeap*, Eterm*);
95
static Sint decoded_size(byte *ep, byte* endp, int only_heap_bins);
91
static Sint decoded_size(byte *ep, byte* endp, int only_heap_bins, int internal_tags);
98
94
static Uint encode_size_struct2(ErtsAtomCacheMap *, Eterm, unsigned);
272
268
byte *erts_encode_ext_dist_header_setup(byte *ctl_ext, ErtsAtomCacheMap *acmp)
275
#if ATOM_LIMIT >= (1UL << 32)
276
#error "ATOM_LIMIT too large for interal atom cache update instructions. New instructions needed."
270
/* Maximum number of atom must be less than the maximum of a 32 bits
271
unsigned integer. Check is done in erl_init.c, erl_start function. */
466
459
+ 1 /* VERSION_MAGIC */;
462
Uint erts_encode_ext_size_ets(Eterm term)
464
return encode_size_struct2(NULL, term, TERM_TO_BINARY_DFLAGS|DFLAGS_INTERNAL_TAGS);
469
468
void erts_encode_dist_ext(Eterm term, byte **ext, Uint32 flags, ErtsAtomCacheMap *acmp)
473
472
if (!(flags & DFLAG_DIST_HDR_ATOM_CACHE))
475
474
*ep++ = VERSION_MAGIC;
476
ep = enc_term(acmp, term, ep, flags);
475
ep = enc_term(acmp, term, ep, flags, NULL);
478
477
erl_exit(ERTS_ABORT_EXIT,
479
478
"%s:%d:erts_encode_dist_ext(): Internal data structure error\n",
487
486
*ep++ = VERSION_MAGIC;
488
ep = enc_term(NULL, term, ep, TERM_TO_BINARY_DFLAGS);
487
ep = enc_term(NULL, term, ep, TERM_TO_BINARY_DFLAGS, NULL);
490
489
erl_exit(ERTS_ABORT_EXIT,
491
490
"%s:%d:erts_encode_ext(): Internal data structure error\n",
495
byte* erts_encode_ext_ets(Eterm term, byte *ep, struct erl_off_heap_header** off_heap)
497
return enc_term(NULL, term, ep, TERM_TO_BINARY_DFLAGS|DFLAGS_INTERNAL_TAGS,
496
501
ErtsDistExternal *
497
502
erts_make_dist_ext_copy(ErtsDistExternal *edep, Uint xsize)
507
512
ASSERT(edep->ext_endp >= edep->extp);
508
513
ext_sz = edep->ext_endp - edep->extp;
510
align_sz = ERTS_WORD_ALIGN_PAD_SZ(dist_ext_sz + ext_sz);
515
align_sz = ERTS_EXTRA_DATA_ALIGN_SZ(dist_ext_sz + ext_sz);
512
517
new_edep = erts_alloc(ERTS_ALC_T_EXT_TERM_DATA,
513
518
dist_ext_sz + ext_sz + align_sz + xsize);
819
824
ep = edep->extp+1;
821
res = decoded_size(ep, edep->ext_endp, no_refc_bins);
826
res = decoded_size(ep, edep->ext_endp, no_refc_bins, 0);
831
836
if (size == 0 || *ext != VERSION_MAGIC)
833
return decoded_size(ext+1, ext+size, no_refc_bins);
838
return decoded_size(ext+1, ext+size, no_refc_bins, 0);
841
Sint erts_decode_ext_size_ets(byte *ext, Uint size)
843
Sint sz = decoded_size(ext, ext+size, 0, 1);
837
850
** hpp is set to either a &p->htop or
908
Eterm erts_decode_ext_ets(Eterm **hpp, ErlOffHeap *off_heap, byte *ext)
911
ext = dec_term(NULL, hpp, ext, off_heap, &obj);
897
916
/**********************************************************************/
969
988
return erts_term_to_binary(p, Term, 0, TERM_TO_BINARY_DFLAGS);
973
993
term_to_binary_2(Process* p, Eterm Term, Eterm Flags)
1013
1033
return erts_term_to_binary(p, Term, level, flags);
1036
static uLongf binary2term_uncomp_size(byte* data, Sint size)
1040
const uInt chunk_size = 64*1024; /* Ask tmp-alloc about a suitable size? */
1041
void* tmp_buf = erts_alloc(ERTS_ALC_T_TMP, chunk_size);
1042
uLongf uncomp_size = 0;
1044
stream.next_in = (Bytef*)data;
1045
stream.avail_in = (uInt)size;
1046
stream.next_out = tmp_buf;
1047
stream.avail_out = (uInt)chunk_size;
1049
erl_zlib_alloc_init(&stream);
1051
err = inflateInit(&stream);
1054
stream.next_out = tmp_buf;
1055
stream.avail_out = chunk_size;
1056
err = inflate(&stream, Z_NO_FLUSH);
1057
uncomp_size += chunk_size - stream.avail_out;
1058
}while (err == Z_OK);
1059
inflateEnd(&stream);
1061
erts_free(ERTS_ALC_T_TMP, tmp_buf);
1062
return err == Z_STREAM_END ? uncomp_size : 0;
1016
1065
static ERTS_INLINE Sint
1017
1066
binary2term_prepare(ErtsBinary2TermState *state, byte *data, Sint data_size)
1036
1085
state->extp = bytes;
1039
uLongf dest_len = get_int32(bytes+1);
1040
state->extp = erts_alloc(ERTS_ALC_T_TMP, dest_len);
1088
uLongf dest_len = (Uint32) get_int32(bytes+1);
1091
if (dest_len > 32*1024*1024
1092
|| (state->extp = erts_alloc_fnf(ERTS_ALC_T_TMP, dest_len)) == NULL) {
1093
if (dest_len != binary2term_uncomp_size(bytes, size)) {
1096
state->extp = erts_alloc(ERTS_ALC_T_TMP, dest_len);
1041
1098
state->exttmp = 1;
1042
if (erl_zlib_uncompress(state->extp, &dest_len, bytes+5, size-5) != Z_OK)
1099
if (erl_zlib_uncompress(state->extp, &dest_len, bytes, size) != Z_OK)
1044
1101
size = (Sint) dest_len;
1046
res = decoded_size(state->extp, state->extp + size, 0);
1103
res = decoded_size(state->extp, state->extp + size, 0, 0);
1061
1118
static ERTS_INLINE Eterm
1062
binary2term_create(ErtsBinary2TermState *state, Eterm **hpp, ErlOffHeap *ohp)
1119
binary2term_create(ErtsDistExternal *edep, ErtsBinary2TermState *state, Eterm **hpp, ErlOffHeap *ohp)
1065
if (!dec_term(NULL, hpp, state->extp, ohp, &res))
1122
if (!dec_term(edep, hpp, state->extp, ohp, &res))
1066
1123
res = THE_NON_VALUE;
1067
1124
if (state->exttmp) {
1068
1125
state->exttmp = 0;
1087
1144
erts_binary2term_create(ErtsBinary2TermState *state, Eterm **hpp, ErlOffHeap *ohp)
1089
return binary2term_create(state, hpp, ohp);
1146
return binary2term_create(NULL,state, hpp, ohp);
1092
1149
BIF_RETTYPE binary_to_term_1(BIF_ALIST_1)
1114
1171
hp = HAlloc(BIF_P, heap_size);
1115
1172
endp = hp + heap_size;
1117
res = binary2term_create(&b2ts, &hp, &MSO(BIF_P));
1174
res = binary2term_create(NULL, &b2ts, &hp, &MSO(BIF_P));
1176
erts_free_aligned_binary_bytes(temp_alloc);
1179
erl_exit(1, ":%s, line %d: heap overrun by %d words(s)\n",
1180
__FILE__, __LINE__, hp-endp);
1183
HRelease(BIF_P, endp, hp);
1185
if (res == THE_NON_VALUE)
1191
BIF_RETTYPE binary_to_term_2(BIF_ALIST_2)
1201
byte* temp_alloc = NULL;
1202
ErtsBinary2TermState b2ts;
1203
ErtsDistExternal fakedep;
1207
while (is_list(opts)) {
1208
opt = CAR(list_val(opts));
1209
if (opt == am_safe) {
1210
fakedep.flags |= ERTS_DIST_EXT_BTT_SAFE;
1215
opts = CDR(list_val(opts));
1218
if (is_not_nil(opts))
1221
if ((bytes = erts_get_aligned_binary_bytes(BIF_ARG_1, &temp_alloc)) == NULL) {
1223
erts_free_aligned_binary_bytes(temp_alloc);
1224
BIF_ERROR(BIF_P, BADARG);
1226
size = binary_size(BIF_ARG_1);
1228
heap_size = binary2term_prepare(&b2ts, bytes, size);
1232
hp = HAlloc(BIF_P, heap_size);
1233
endp = hp + heap_size;
1235
res = binary2term_create(&fakedep, &b2ts, &hp, &MSO(BIF_P));
1119
1237
erts_free_aligned_binary_bytes(temp_alloc);
1163
1281
bytes = erts_alloc(ERTS_ALC_T_TMP, size);
1166
if ((endp = enc_term(NULL, Term, bytes, flags))
1284
if ((endp = enc_term(NULL, Term, bytes, flags, NULL))
1168
1286
erl_exit(1, "%s, line %d: bad term: %x\n",
1169
1287
__FILE__, __LINE__, Term);
1208
1326
bin = new_binary(p, (byte *)NULL, size);
1209
1327
bytes = binary_bytes(bin);
1210
1328
bytes[0] = VERSION_MAGIC;
1211
if ((endp = enc_term(NULL, Term, bytes+1, flags))
1329
if ((endp = enc_term(NULL, Term, bytes+1, flags, NULL))
1213
1331
erl_exit(1, "%s, line %d: bad term: %x\n",
1214
1332
__FILE__, __LINE__, Term);
1239
1357
ASSERT(is_atom(atom));
1359
if (dflags & DFLAGS_INTERNAL_TAGS) {
1360
Uint aval = atom_val(atom);
1361
ASSERT(aval < (1<<24));
1362
if (aval >= (1 << 16)) {
1363
*ep++ = ATOM_INTERNAL_REF3;
1364
put_int24(aval, ep);
1368
*ep++ = ATOM_INTERNAL_REF2;
1369
put_int16(aval, ep);
1242
1375
* term_to_binary/1,2 and the initial distribution message
1243
1376
* don't use the cache.
1313
1447
len = get_int16(ep),
1315
*objp = am_atom_put((char*)ep, len);
1449
goto dec_atom_common;
1318
1450
case SMALL_ATOM_EXT:
1319
1451
len = get_int8(ep);
1321
*objp = am_atom_put((char*)ep, len);
1454
if (edep && (edep->flags & ERTS_DIST_EXT_BTT_SAFE)) {
1455
if (!erts_atom_get((char*)ep, len, objp)) {
1459
*objp = am_atom_put((char*)ep, len);
1463
case ATOM_INTERNAL_REF2:
1466
if (n >= atom_table_size()) {
1469
*objp = make_atom(n);
1471
case ATOM_INTERNAL_REF3:
1474
if (n >= atom_table_size()) {
1477
*objp = make_atom(n);
1326
1482
*objp = NIL; /* Don't leave a hole in the heap */
1488
static ERTS_INLINE ErlNode* dec_get_node(Eterm sysname, Uint creation)
1491
case INTERNAL_CREATION:
1492
return erts_this_node;
1494
if (sysname == erts_this_node->sysname) {
1495
creation = erts_this_node->creation;
1498
return erts_find_or_insert_node(sysname,creation);
1333
1502
dec_pid(ErtsDistExternal *edep, Eterm** hpp, byte* ep, ErlOffHeap* off_heap, Eterm* objp)
1353
1522
if (ser > ERTS_MAX_PID_SERIAL)
1355
if ((cre = get_int8(ep)) >= MAX_CREATION)
1527
if (!is_valid_creation(cre)) {
1530
data = make_pid_data(ser, num);
1360
1533
* We are careful to create the node entry only after all
1361
1534
* validity tests are done.
1363
cre = dec_set_creation(sysname,cre);
1364
node = erts_find_or_insert_node(sysname,cre);
1536
node = dec_get_node(sysname, cre);
1366
data = make_pid_data(ser, num);
1367
1538
if(node == erts_this_node) {
1368
1539
*objp = make_internal_pid(data);
1371
1542
*hpp += EXTERNAL_THING_HEAD_SIZE + 1;
1373
1544
etp->header = make_external_pid_header(1);
1374
etp->next = off_heap->externals;
1545
etp->next = off_heap->first;
1375
1546
etp->node = node;
1376
1547
etp->data.ui[0] = data;
1378
off_heap->externals = etp;
1549
off_heap->first = (struct erl_off_heap_header*) etp;
1379
1550
*objp = make_external_pid(etp);
1388
1559
#define ENC_LAST_ARRAY_ELEMENT ((Eterm) 3)
1391
enc_term(ErtsAtomCacheMap *acmp, Eterm obj, byte* ep, Uint32 dflags)
1562
enc_term(ErtsAtomCacheMap *acmp, Eterm obj, byte* ep, Uint32 dflags,
1563
struct erl_off_heap_header** off_heap)
1401
1577
goto L_jump_start;
1404
while (!ESTACK_ISEMPTY(s)) {
1405
obj = ESTACK_POP(s);
1406
switch (val = ESTACK_POP(s)) {
1580
while (!WSTACK_ISEMPTY(s)) {
1582
obj = (Eterm) (wobj = WSTACK_POP(s));
1584
obj = WSTACK_POP(s);
1586
switch (val = WSTACK_POP(s)) {
1409
1589
case ENC_ONE_CONS:
1415
1595
obj = CAR(cons);
1416
1596
tl = CDR(cons);
1417
ESTACK_PUSH(s, is_list(tl) ? ENC_ONE_CONS : ENC_TERM);
1597
WSTACK_PUSH(s, is_list(tl) ? ENC_ONE_CONS : ENC_TERM);
1421
1601
case ENC_PATCH_FUN_SIZE:
1604
byte* size_p = (byte *) wobj;
1423
1606
byte* size_p = (byte *) obj;
1425
1608
put_int32(ep - size_p, size_p);
1427
1610
goto outer_loop;
1428
1611
case ENC_LAST_ARRAY_ELEMENT:
1614
Eterm* ptr = (Eterm *) wobj;
1430
1616
Eterm* ptr = (Eterm *) obj;
1434
1621
default: /* ENC_LAST_ARRAY_ELEMENT+1 and upwards */
1624
Eterm* ptr = (Eterm *) wobj;
1436
1626
Eterm* ptr = (Eterm *) obj;
1438
ESTACK_PUSH(s, val-1);
1439
ESTACK_PUSH(s, (Eterm) ptr);
1629
WSTACK_PUSH(s, val-1);
1630
WSTACK_PUSH(s, (UWord) ptr);
1454
1645
case SMALL_DEF:
1647
/* From R14B we no longer restrict INTEGER_EXT to 28 bits,
1648
* as done earlier for backward compatibility reasons. */
1456
1649
Sint val = signed_val(obj);
1458
1651
if ((Uint)val < 256) {
1459
1652
*ep++ = SMALL_INTEGER_EXT;
1460
1653
put_int8(val, ep);
1462
} else if (sizeof(Sint) == 4 || IS_SSMALL28(val)) {
1655
} else if (sizeof(Sint) == 4 || IS_SSMALL32(val)) {
1463
1656
*ep++ = INTEGER_EXT;
1464
1657
put_int32(val, ep);
1468
Eterm big = small_to_big(val, tmp_big);
1660
DeclareTmpHeapNoproc(tmp_big,2);
1662
UseTmpHeapNoproc(2);
1663
big = small_to_big(val, tmp_big);
1469
1664
*ep++ = SMALL_BIG_EXT;
1470
1665
n = big_bytes(big);
1471
1666
ASSERT(n < 256);
1474
1669
*ep++ = big_sign(big);
1475
1670
ep = big_to_bytes(big, ep);
1671
UnUseTmpHeapNoproc(2);
1481
if ((n = big_bytes(obj)) < 256) {
1482
*ep++ = SMALL_BIG_EXT;
1487
*ep++ = LARGE_BIG_EXT;
1491
*ep++ = big_sign(obj);
1492
ep = big_to_bytes(obj, ep);
1678
int sign = big_sign(obj);
1680
if (sizeof(Sint)==4 && n<=4) {
1681
Uint dig = big_digit(obj,0);
1682
Sint val = sign ? -dig : dig;
1683
if ((val<0) == sign) {
1684
*ep++ = INTEGER_EXT;
1691
*ep++ = SMALL_BIG_EXT;
1696
*ep++ = LARGE_BIG_EXT;
1701
ep = big_to_bytes(obj, ep);
1502
1712
Uint32 *ref_num;
1504
1714
ASSERT(dflags & DFLAG_EXTENDED_REFERENCES);
1505
1716
*ep++ = NEW_REFERENCE_EXT;
1506
1717
i = ref_no_of_numbers(obj);
1507
1718
put_int16(i, ep);
1509
1720
ep = enc_atom(acmp,ref_node_name(obj),ep,dflags);
1510
*ep++ = ref_creation(obj);
1721
*ep++ = ((dflags & DFLAGS_INTERNAL_TAGS) && is_internal_ref(obj)) ?
1722
INTERNAL_CREATION : ref_creation(obj);
1511
1723
ref_num = ref_numbers(obj);
1512
1724
for (j = 0; j < i; j++) {
1513
1725
put_int32(ref_num[j], ep);
1566
ESTACK_PUSH(s, ENC_LAST_ARRAY_ELEMENT+i-1);
1567
ESTACK_PUSH(s, (Eterm) ptr);
1779
WSTACK_PUSH(s, ENC_LAST_ARRAY_ELEMENT+i-1);
1780
WSTACK_PUSH(s, (UWord) ptr);
1605
1818
ERTS_GET_BINARY_BYTES(obj, bytes, bitoffs, bitsize);
1819
if (dflags & DFLAGS_INTERNAL_TAGS) {
1820
ProcBin* pb = (ProcBin*) binary_val(obj);
1821
Uint bytesize = pb->size;
1822
if (pb->thing_word == HEADER_SUB_BIN) {
1823
ErlSubBin* sub = (ErlSubBin*)pb;
1824
pb = (ProcBin*) binary_val(sub->orig);
1825
ASSERT(bytesize == sub->size);
1826
bytesize += (bitoffs + bitsize + 7) / 8;
1828
if (pb->thing_word == HEADER_PROC_BIN
1829
&& heap_bin_size(bytesize) > PROC_BIN_SIZE) {
1831
if (bitoffs || bitsize) {
1832
*ep++ = BIT_BINARY_INTERNAL_REF;
1837
*ep++ = BINARY_INTERNAL_REF;
1840
erts_emasculate_writable_binary(pb);
1842
erts_refc_inc(&pb->val->refc, 2);
1844
sys_memcpy(&tmp, pb, sizeof(ProcBin));
1845
tmp.next = *off_heap;
1847
tmp.size = bytesize;
1848
sys_memcpy(ep, &tmp, sizeof(ProcBin));
1849
*off_heap = (struct erl_off_heap_header*) ep;
1850
ep += sizeof(ProcBin);
1606
1854
if (bitsize == 0) {
1607
1855
/* Plain old byte-sized binary. */
1608
1856
*ep++ = BINARY_EXT;
1638
1886
*ep++ = SMALL_INTEGER_EXT;
1639
1887
*ep++ = bitsize;
1643
1891
case EXPORT_DEF:
1645
Export* exp = (Export *) (export_val(obj))[1];
1893
Export* exp = *((Export **) (export_val(obj) + 1));
1646
1894
if ((dflags & DFLAG_EXPORT_PTR_TAG) != 0) {
1647
1895
*ep++ = EXPORT_EXT;
1648
1896
ep = enc_atom(acmp, exp->code[0], ep, dflags);
1649
1897
ep = enc_atom(acmp, exp->code[1], ep, dflags);
1650
ep = enc_term(acmp, make_small(exp->code[2]), ep, dflags);
1898
ep = enc_term(acmp, make_small(exp->code[2]), ep, dflags, off_heap);
1652
1900
/* Tag, arity */
1653
1901
*ep++ = SMALL_TUPLE_EXT;
1673
1921
*ep++ = NEW_FUN_EXT;
1674
ESTACK_PUSH(s, ENC_PATCH_FUN_SIZE);
1675
ESTACK_PUSH(s, (Eterm) ep); /* Position for patching in size */
1922
WSTACK_PUSH(s, ENC_PATCH_FUN_SIZE);
1923
WSTACK_PUSH(s, (UWord) ep); /* Position for patching in size */
1677
1925
*ep = funp->arity;
1683
1931
put_int32(funp->num_free, ep);
1685
1933
ep = enc_atom(acmp, funp->fe->module, ep, dflags);
1686
ep = enc_term(acmp, make_small(funp->fe->old_index), ep, dflags);
1687
ep = enc_term(acmp, make_small(funp->fe->old_uniq), ep, dflags);
1934
ep = enc_term(acmp, make_small(funp->fe->old_index), ep, dflags, off_heap);
1935
ep = enc_term(acmp, make_small(funp->fe->old_uniq), ep, dflags, off_heap);
1688
1936
ep = enc_pid(acmp, funp->creator, ep, dflags);
1691
1939
for (ei = funp->num_free-1; ei > 0; ei--) {
1692
ESTACK_PUSH(s, ENC_TERM);
1693
ESTACK_PUSH(s, funp->env[ei]);
1940
WSTACK_PUSH(s, ENC_TERM);
1941
WSTACK_PUSH(s, (UWord) funp->env[ei]);
1695
1943
if (funp->num_free != 0) {
1696
1944
obj = funp->env[0];
2027
/* Assumes that the ones to undo are preluding the list. */
2029
undo_offheap_in_area(ErlOffHeap* off_heap, Eterm* start, Eterm* end)
2031
const Uint area_sz = (end - start) * sizeof(Eterm);
2032
struct erl_off_heap_header* hdr;
2033
struct erl_off_heap_header** hdr_nextp = NULL;
2035
for (hdr = off_heap->first; ; hdr=hdr->next) {
2036
if (!in_area(hdr, start, area_sz)) {
2037
if (hdr_nextp != NULL) {
2039
erts_cleanup_offheap(off_heap);
2040
off_heap->first = hdr;
2044
hdr_nextp = &hdr->next;
2047
/* Assert that the ones to undo were indeed preluding the list. */
2049
for (hdr = off_heap->first; hdr != NULL; hdr = hdr->next) {
2050
ASSERT(!in_area(hdr, start, area_sz));
2055
/* Decode term from external format into *objp.
2056
** On failure return NULL and (R13B04) *hpp will be unchanged.
1779
2059
dec_term(ErtsDistExternal *edep, Eterm** hpp, byte* ep, ErlOffHeap* off_heap, Eterm* objp)
2061
Eterm* hp_saved = *hpp;
1782
2063
register Eterm* hp = *hpp; /* Please don't take the address of hp */
1783
2064
Eterm* next = objp;
1785
*next = (Eterm) NULL;
2066
*next = (Eterm) (UWord) NULL;
1787
2068
while (next != NULL) {
1789
next = (Eterm *) (*objp);
2070
next = (Eterm *) EXPAND_POINTER(*objp);
1791
2072
switch (*ep++) {
1792
2073
case INTEGER_EXT:
1865
2146
n = get_int16(ep);
1867
*objp = am_atom_put((char*)ep, n);
2148
goto dec_term_atom_common;
1870
2149
case SMALL_ATOM_EXT:
1871
2150
n = get_int8(ep);
1873
*objp = am_atom_put((char*)ep, n);
2152
dec_term_atom_common:
2153
if (edep && (edep->flags & ERTS_DIST_EXT_BTT_SAFE)) {
2154
if (!erts_atom_get((char*)ep, n, objp)) {
2158
*objp = am_atom_put((char*)ep, n);
1876
2162
case LARGE_TUPLE_EXT:
1904
2190
*objp = make_list(hp);
1907
objp[0] = (Eterm) (objp+1);
1908
objp[1] = (Eterm) next;
2193
objp[0] = (Eterm) COMPRESS_POINTER((objp+1));
2194
objp[1] = (Eterm) COMPRESS_POINTER(next);
1911
2197
while (--n > 0) {
1912
objp[0] = (Eterm) next;
2198
objp[0] = (Eterm) COMPRESS_POINTER(next);
1913
2199
objp[1] = make_list(objp + 2);
1993
if ((cre = get_int8(ep)) >= MAX_CREATION) {
1997
cre = dec_set_creation(sysname,cre);
1998
node = erts_find_or_insert_node(sysname, cre);
2281
if (!is_valid_creation(cre)) {
2285
node = dec_get_node(sysname, cre);
2000
2286
if(node == erts_this_node) {
2001
2287
*objp = make_internal_port(num);
2005
2291
hp += EXTERNAL_THING_HEAD_SIZE + 1;
2007
2293
etp->header = make_external_port_header(1);
2008
etp->next = off_heap->externals;
2294
etp->next = off_heap->first;
2009
2295
etp->node = node;
2010
2296
etp->data.ui[0] = num;
2012
off_heap->externals = etp;
2298
off_heap->first = (struct erl_off_heap_header*)etp;
2013
2299
*objp = make_external_port(etp);
2061
2349
ref_ext_common:
2063
cre = dec_set_creation(sysname, cre);
2064
node = erts_find_or_insert_node(sysname, cre);
2351
node = dec_get_node(sysname, cre);
2065
2352
if(node == erts_this_node) {
2066
2353
RefThing *rtp = (RefThing *) hp;
2067
hp += REF_THING_HEAD_SIZE;
2354
ref_num = (Uint32 *) (hp + REF_THING_HEAD_SIZE);
2356
#if defined(ARCH_64) && !HALFWORD_HEAP
2357
hp += REF_THING_HEAD_SIZE + ref_words/2 + 1;
2069
2358
rtp->header = make_ref_thing_header(ref_words/2 + 1);
2360
hp += REF_THING_HEAD_SIZE + ref_words;
2071
2361
rtp->header = make_ref_thing_header(ref_words);
2073
2363
*objp = make_internal_ref(rtp);
2076
2366
ExternalThing *etp = (ExternalThing *) hp;
2077
hp += EXTERNAL_THING_HEAD_SIZE;
2367
#if defined(ARCH_64) && !HALFWORD_HEAP
2368
hp += EXTERNAL_THING_HEAD_SIZE + ref_words/2 + 1;
2370
hp += EXTERNAL_THING_HEAD_SIZE + ref_words;
2373
#if defined(ARCH_64) && !HALFWORD_HEAP
2080
2374
etp->header = make_external_ref_header(ref_words/2 + 1);
2082
2376
etp->header = make_external_ref_header(ref_words);
2084
etp->next = off_heap->externals;
2378
etp->next = off_heap->first;
2085
2379
etp->node = node;
2087
off_heap->externals = etp;
2381
off_heap->first = (struct erl_off_heap_header*)etp;
2088
2382
*objp = make_external_ref(etp);
2383
ref_num = &(etp->data.ui32[0]);
2091
ref_num = (Uint32 *) hp;
2386
#if defined(ARCH_64) && !HALFWORD_HEAP
2093
2387
*(ref_num++) = ref_words /* 32-bit arity */;
2095
2389
ref_num[0] = r0;
2130
2421
hp += PROC_BIN_SIZE;
2131
2422
pb->thing_word = HEADER_PROC_BIN;
2133
pb->next = off_heap->mso;
2424
pb->next = off_heap->first;
2425
off_heap->first = (struct erl_off_heap_header*)pb;
2135
2426
pb->val = dbin;
2136
2427
pb->bytes = (byte*) dbin->orig_bytes;
2167
2458
pb = (ProcBin *) hp;
2168
2459
pb->thing_word = HEADER_PROC_BIN;
2170
pb->next = off_heap->mso;
2461
pb->next = off_heap->first;
2462
off_heap->first = (struct erl_off_heap_header*)pb;
2172
2463
pb->val = dbin;
2173
2464
pb->bytes = (byte*) dbin->orig_bytes;
2218
2509
if (arity < 0) {
2512
if (edep && (edep->flags & ERTS_DIST_EXT_BTT_SAFE)) {
2513
if (!erts_find_export_entry(mod, name, arity))
2221
2516
*objp = make_export(hp);
2222
2517
*hp++ = HEADER_EXPORT;
2519
*((UWord *) (UWord) hp) = (UWord) erts_export_get_or_make_stub(mod, name, arity);
2223
2522
*hp++ = (Eterm) erts_export_get_or_make_stub(mod, name, arity);
2248
2546
num_free = get_int32(ep);
2250
2548
hp += ERL_FUN_SIZE;
2252
/* Don't leave a hole in case we fail */
2253
*hp = make_pos_bignum_header(num_free-1);
2255
2549
hp += num_free;
2257
2550
funp->thing_word = HEADER_FUN;
2258
2551
funp->num_free = num_free;
2259
funp->creator = NIL; /* Don't leave a hole in case we fail */
2260
2552
*objp = make_fun(funp);
2263
if ((ep = dec_atom(edep, ep, &temp)) == NULL) {
2555
if ((ep = dec_atom(edep, ep, &module)) == NULL) {
2269
2560
if ((ep = dec_term(edep, hpp, ep, off_heap, &temp)) == NULL) {
2288
2579
* It is safe to link the fun into the fun list only when
2289
2580
* no more validity tests can fail.
2291
funp->next = off_heap->funs;
2292
off_heap->funs = funp;
2582
funp->next = off_heap->first;
2583
off_heap->first = (struct erl_off_heap_header*)funp;
2295
2586
funp->fe = erts_put_fun_entry2(module, old_uniq, old_index,
2306
2597
/* Environment */
2307
2598
for (i = num_free-1; i >= 0; i--) {
2308
funp->env[i] = (Eterm) next;
2599
funp->env[i] = (Eterm) COMPRESS_POINTER(next);
2309
2600
next = funp->env + i;
2312
funp->creator = (Eterm) next;
2603
funp->creator = (Eterm) COMPRESS_POINTER(next);
2313
2604
next = &(funp->creator);
2339
2624
*objp = make_fun(funp);
2341
2626
/* Creator pid */
2344
ep = dec_pid(edep, hpp, ++ep, off_heap, &funp->creator);
2346
funp->creator = NIL; /* Don't leave a hole in the heap */
2628
|| (ep = dec_pid(edep, hpp, ++ep, off_heap,
2629
&funp->creator))==NULL) {
2355
if ((ep = dec_atom(edep, ep, &temp)) == NULL) {
2634
if ((ep = dec_atom(edep, ep, &module)) == NULL) {
2361
2639
if ((ep = dec_term(edep, hpp, ep, off_heap, &temp)) == NULL) {
2379
2657
* It is safe to link the fun into the fun list only when
2380
2658
* no more validity tests can fail.
2382
funp->next = off_heap->funs;
2383
off_heap->funs = funp;
2660
funp->next = off_heap->first;
2661
off_heap->first = (struct erl_off_heap_header*)funp;
2386
2663
old_uniq = unsigned_val(temp);
2388
2665
funp->fe = erts_put_fun_entry(module, old_uniq, old_index);
2395
2672
/* Environment */
2396
2673
for (i = num_free-1; i >= 0; i--) {
2397
funp->env[i] = (Eterm) next;
2674
funp->env[i] = (Eterm) COMPRESS_POINTER(next);
2398
2675
next = funp->env + i;
2679
case ATOM_INTERNAL_REF2:
2682
if (n >= atom_table_size()) {
2685
*objp = make_atom(n);
2687
case ATOM_INTERNAL_REF3:
2690
if (n >= atom_table_size()) {
2693
*objp = make_atom(n);
2696
case BINARY_INTERNAL_REF:
2698
ProcBin* pb = (ProcBin*) hp;
2699
sys_memcpy(pb, ep, sizeof(ProcBin));
2700
ep += sizeof(ProcBin);
2702
erts_refc_inc(&pb->val->refc, 1);
2703
hp += PROC_BIN_SIZE;
2704
pb->next = off_heap->first;
2705
off_heap->first = (struct erl_off_heap_header*)pb;
2707
*objp = make_binary(pb);
2710
case BIT_BINARY_INTERNAL_REF:
2712
Sint bitoffs = *ep++;
2713
Sint bitsize = *ep++;
2714
ProcBin* pb = (ProcBin*) hp;
2716
sys_memcpy(pb, ep, sizeof(ProcBin));
2717
ep += sizeof(ProcBin);
2719
erts_refc_inc(&pb->val->refc, 1);
2720
hp += PROC_BIN_SIZE;
2721
pb->next = off_heap->first;
2722
off_heap->first = (struct erl_off_heap_header*)pb;
2725
sub = (ErlSubBin*)hp;
2726
sub->thing_word = HEADER_SUB_BIN;
2727
sub->size = pb->size - (bitoffs + bitsize + 7)/8;
2729
sub->bitoffs = bitoffs;
2730
sub->bitsize = bitsize;
2731
sub->is_writable = 0;
2732
sub->orig = make_binary(pb);
2734
hp += ERL_SUB_BIN_SIZE;
2735
*objp = make_binary(sub);
2405
* Be careful to return the updated heap pointer, to avoid
2406
* that the caller wipes out binaries or other off-heap objects
2407
* that may have been linked into the process.
2742
* Must unlink all off-heap objects that may have been
2743
* linked into the process.
2745
if (hp < *hpp) { /* Sometimes we used hp and sometimes *hpp */
2746
hp = *hpp; /* the largest must be the freshest */
2748
undo_offheap_in_area(off_heap, hp_saved, hp);
2423
2763
encode_size_struct2(ErtsAtomCacheMap *acmp, Eterm obj, unsigned dflags)
2426
2766
Uint m, i, arity;
2427
2767
Uint result = 0;
2429
2772
goto L_jump_start;
2432
while (!ESTACK_ISEMPTY(s)) {
2433
obj = ESTACK_POP(s);
2775
while (!WSTACK_ISEMPTY(s)) {
2777
obj = (Eterm) (wobj = WSTACK_POP(s));
2779
obj = WSTACK_POP(s);
2435
2781
handle_popped_obj:
2782
if (is_CP(obj)) { /* Does not look for CP, looks for "no tag" */
2784
Eterm* ptr = (Eterm *) wobj;
2437
2786
Eterm* ptr = (Eterm *) obj;
2440
2789
* Pointer into a tuple.
2443
2792
if (!is_header(obj)) {
2444
ESTACK_PUSH(s, (Eterm)ptr);
2793
WSTACK_PUSH(s, (UWord)ptr);
2446
2795
/* Reached tuple header */
2447
2796
ASSERT(header_is_arityval(obj));
2473
int alen = atom_tab(atom_val(obj))->len;
2474
if ((MAX_ATOM_LENGTH <= 255 || alen <= 255)
2475
&& (dflags & DFLAG_SMALL_ATOM_TAGS)) {
2476
/* Make sure a SMALL_ATOM_EXT fits: SMALL_ATOM_EXT l t1 t2... */
2477
result += 1 + 1 + alen;
2822
if (dflags & DFLAGS_INTERNAL_TAGS) {
2823
if (atom_val(obj) >= (1<<16)) {
2480
/* Make sure an ATOM_EXT fits: ATOM_EXT l1 l0 t1 t2... */
2481
result += 1 + 2 + alen;
2831
int alen = atom_tab(atom_val(obj))->len;
2832
if ((MAX_ATOM_LENGTH <= 255 || alen <= 255)
2833
&& (dflags & DFLAG_SMALL_ATOM_TAGS)) {
2834
/* Make sure a SMALL_ATOM_EXT fits: SMALL_ATOM_EXT l t1 t2... */
2835
result += 1 + 1 + alen;
2838
/* Make sure an ATOM_EXT fits: ATOM_EXT l1 l0 t1 t2... */
2839
result += 1 + 2 + alen;
2841
insert_acache_map(acmp, obj);
2483
insert_acache_map(acmp, obj);
2486
2844
case SMALL_DEF:
2488
2846
Sint val = signed_val(obj);
2490
2848
if ((Uint)val < 256)
2491
2849
result += 1 + 1; /* SMALL_INTEGER_EXT */
2492
else if (sizeof(Sint) == 4 || IS_SSMALL28(val))
2850
else if (sizeof(Sint) == 4 || IS_SSMALL32(val))
2493
2851
result += 1 + 4; /* INTEGER_EXT */
2853
DeclareTmpHeapNoproc(tmp_big,2);
2854
UseTmpHeapNoproc(2);
2496
2855
i = big_bytes(small_to_big(val, tmp_big));
2497
2856
result += 1 + 1 + 1 + i; /* SMALL_BIG_EXT */
2857
UnUseTmpHeapNoproc(2);
2502
if ((i = big_bytes(obj)) < 256)
2863
if (sizeof(Sint)==4 && i <= 4 && (big_digit(obj,0)-big_sign(obj)) < (1<<31))
2864
result += 1 + 4; /* INTEGER_EXT */
2503
2866
result += 1 + 1 + 1 + i; /* tag,size,sign,digits */
2505
2868
result += 1 + 4 + 1 + i; /* tag,size,sign,digits */
2554
2921
case BINARY_DEF:
2922
if (dflags & DFLAGS_INTERNAL_TAGS) {
2923
ProcBin* pb = (ProcBin*) binary_val(obj);
2925
Uint tot_bytes = pb->size;
2926
if (pb->thing_word == HEADER_SUB_BIN) {
2927
ErlSubBin* sub = (ErlSubBin*) pb;
2928
pb = (ProcBin*) binary_val(sub->orig);
2929
sub_extra = 2; /* bitoffs and bitsize */
2930
tot_bytes += (sub->bitoffs + sub->bitsize+ 7) / 8;
2932
if (pb->thing_word == HEADER_PROC_BIN
2933
&& heap_bin_size(tot_bytes) > PROC_BIN_SIZE) {
2935
result += 1 + sub_extra + sizeof(ProcBin);
2555
2939
result += 1 + 4 + binary_size(obj) +
2556
5; /* For unaligned binary */
2940
5; /* For unaligned binary */
2603
2987
case EXPORT_DEF:
2605
Export* ep = (Export *) (export_val(obj))[1];
2989
Export* ep = *((Export **) (export_val(obj) + 1));
2607
2995
result += encode_size_struct2(acmp, ep->code[0], dflags);
2608
2996
result += encode_size_struct2(acmp, ep->code[1], dflags);
2609
2997
result += encode_size_struct2(acmp, make_small(ep->code[2]), dflags);
2624
decoded_size(byte *ep, byte* endp, int no_refc_bins)
3012
decoded_size(byte *ep, byte* endp, int no_refc_bins, int internal_tags)
2626
3014
int heap_size = 0;
2729
3117
atom_extra_skip = 1 + 4*id_words;
2730
3118
/* In case it is an external ref */
3119
#if defined(ARCH_64) && !HALFWORD_HEAP
2732
3120
heap_size += EXTERNAL_THING_HEAD_SIZE + id_words/2 + 1;
2734
3122
heap_size += EXTERNAL_THING_HEAD_SIZE + id_words;
2827
3219
heap_size += ERL_FUN_SIZE + num_free;
3222
case ATOM_INTERNAL_REF2:
3223
SKIP(2+atom_extra_skip);
3224
atom_extra_skip = 0;
3226
case ATOM_INTERNAL_REF3:
3227
SKIP(3+atom_extra_skip);
3228
atom_extra_skip = 0;
3231
case BINARY_INTERNAL_REF:
3232
if (!internal_tags) {
3235
SKIP(sizeof(ProcBin));
3236
heap_size += PROC_BIN_SIZE;
3238
case BIT_BINARY_INTERNAL_REF:
3239
if (!internal_tags) {
3242
SKIP(2+sizeof(ProcBin));
3243
heap_size += PROC_BIN_SIZE + ERL_SUB_BIN_SIZE;