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.
82
87
switch (primary_tag(obj)) {
83
88
case TAG_PRIMARY_LIST:
90
ptr = list_val_rel(obj,base);
87
92
if (!IS_CONST(obj)) {
88
93
ESTACK_PUSH(s, obj);
92
97
case TAG_PRIMARY_BOXED:
94
Eterm hdr = *boxed_val(obj);
99
Eterm hdr = *boxed_val_rel(obj,base);
95
100
ASSERT(is_header(hdr));
96
101
switch (hdr & _TAG_HEADER_MASK) {
97
102
case ARITYVAL_SUBTAG:
103
ptr = tuple_val_rel(obj,base);
99
104
arity = header_arity(hdr);
100
105
sum += arity + 1;
101
106
if (arity == 0) { /* Empty tuple -- unusual. */
104
109
while (arity-- > 1) {
114
Eterm* bptr = fun_val(obj);
119
Eterm* bptr = fun_val_rel(obj,base);
115
120
ErlFunThing* funp = (ErlFunThing *) bptr;
116
121
unsigned eterms = 1 /* creator */ + funp->num_free;
117
122
unsigned sz = thing_arityval(hdr);
119
123
sum += 1 /* header */ + sz + eterms;
120
124
bptr += 1 /* header */ + sz;
121
125
while (eterms-- > 1) {
136
140
Uint extra_bytes;
138
ERTS_GET_REAL_BIN(obj, real_bin, offset, bitoffs, bitsize);
142
ERTS_GET_REAL_BIN_REL(obj, real_bin, offset, bitoffs, bitsize, base);
139
143
if ((bitsize + bitoffs) > 8) {
140
144
sum += ERL_SUB_BIN_SIZE;
148
hdr = *binary_val(real_bin);
152
hdr = *binary_val_rel(real_bin,base);
149
153
if (thing_subtag(hdr) == REFC_BINARY_SUBTAG) {
150
154
sum += PROC_BIN_SIZE;
152
sum += heap_bin_size(binary_size(obj)+extra_bytes);
156
sum += heap_bin_size(binary_size_rel(obj,base)+extra_bytes);
157
161
case BIN_MATCHSTATE_SUBTAG:
187
185
* Copy a structure to a heap.
190
copy_struct(Eterm obj, Uint sz, Eterm** hpp, ErlOffHeap* off_heap)
188
Eterm copy_struct_rel(Eterm obj, Uint sz, Eterm** hpp, ErlOffHeap* off_heap,
189
Eterm* src_base, Eterm* dst_base)
191
Eterm copy_struct(Eterm obj, Uint sz, Eterm** hpp, ErlOffHeap* off_heap)
220
222
/* Copy the object onto the heap */
221
223
switch (primary_tag(obj)) {
222
case TAG_PRIMARY_LIST: argp = &res; goto L_copy_list;
224
case TAG_PRIMARY_LIST:
226
objp = list_val_rel(obj,src_base);
223
228
case TAG_PRIMARY_BOXED: argp = &res; goto L_copy_boxed;
225
230
erl_exit(ERTS_ABORT_EXIT,
238
243
case TAG_PRIMARY_LIST:
239
objp = list_val(obj);
244
objp = list_val_rel(obj,src_base);
245
#if !HALFWORD_HEAP || defined(DEBUG)
240
246
if (in_area(objp,hstart,hsize)) {
247
ASSERT(!HALFWORD_HEAP);
245
253
/* Fall through */
249
while (is_list(obj)) {
250
objp = list_val(obj);
253
260
if (IS_CONST(elem)) {
263
*tp = make_list(tailp - 1);
268
CDR(htop) = CDR(objp);
269
*tailp = make_list_rel(htop,dst_base);
277
ASSERT(!HALFWORD_HEAP || tp < hp || tp >= hbot);
278
*tp = make_list_rel(tailp - 1, dst_base);
283
objp = list_val_rel(obj,src_base);
266
285
switch (primary_tag(obj)) {
267
286
case TAG_PRIMARY_IMMED1: *tailp = obj; goto L_copy;
275
294
case TAG_PRIMARY_BOXED:
276
if (in_area(boxed_val(obj),hstart,hsize)) {
295
#if !HALFWORD_HEAP || defined(DEBUG)
296
if (in_area(boxed_val_rel(obj,src_base),hstart,hsize)) {
297
ASSERT(!HALFWORD_HEAP);
283
objp = boxed_val(obj);
305
objp = boxed_val_rel(obj, src_base);
285
307
switch (hdr & _TAG_HEADER_MASK) {
286
308
case ARITYVAL_SUBTAG:
288
310
int const_flag = 1; /* assume constant tuple */
289
311
i = arityval(hdr);
290
*argp = make_tuple(htop);
312
*argp = make_tuple_rel(htop, dst_base);
291
313
tp = htop; /* tp is pointer to new arity value */
292
314
*htop++ = *objp++; /* copy arity value */
319
*argp = make_binary(hbot);
341
*argp = make_binary_rel(hbot, dst_base);
320
342
pb = (ProcBin*) hbot;
321
343
erts_refc_inc(&pb->val->refc, 2);
322
pb->next = off_heap->mso;
344
pb->next = off_heap->first;
325
off_heap->overhead += pb->size / sizeof(Eterm);
346
off_heap->first = (struct erl_off_heap_header*) pb;
347
OH_OVERHEAD(off_heap, pb->size / sizeof(Eterm));
328
350
case SUB_BINARY_SUBTAG:
345
367
real_size = size+extra_bytes;
346
objp = binary_val(real_bin);
368
objp = binary_val_rel(real_bin,src_base);
347
369
if (thing_subtag(*objp) == HEAP_BINARY_SUBTAG) {
348
370
ErlHeapBin* from = (ErlHeapBin *) objp;
368
390
to->val = from->val;
369
391
erts_refc_inc(&to->val->refc, 2);
370
392
to->bytes = from->bytes + offset;
371
to->next = off_heap->mso;
393
to->next = off_heap->first;
374
off_heap->overhead += to->size / sizeof(Eterm);
395
off_heap->first = (struct erl_off_heap_header*) to;
396
OH_OVERHEAD(off_heap, to->size / sizeof(Eterm));
376
*argp = make_binary(hbot);
398
*argp = make_binary_rel(hbot, dst_base);
377
399
if (extra_bytes != 0) {
379
401
hbot -= ERL_SUB_BIN_SIZE;
402
424
#ifndef HYBRID /* FIND ME! */
403
425
funp = (ErlFunThing *) tp;
404
funp->next = off_heap->funs;
405
off_heap->funs = funp;
426
funp->next = off_heap->first;
427
off_heap->first = (struct erl_off_heap_header*) funp;
406
428
erts_refc_inc(&funp->fe->refc, 2);
408
*argp = make_fun(tp);
430
*argp = make_fun_rel(tp, dst_base);
411
433
case EXTERNAL_PID_SUBTAG:
421
443
*htop++ = *objp++;
424
etp->next = off_heap->externals;
425
off_heap->externals = etp;
446
etp->next = off_heap->first;
447
off_heap->first = (struct erl_off_heap_header*)etp;
426
448
erts_refc_inc(&etp->node->refc, 2);
428
*argp = make_external(tp);
450
*argp = make_external_rel(tp, dst_base);
431
453
case BIN_MATCHSTATE_SUBTAG:
657
679
erts_refc_inc(&pb->val->refc, 2);
658
pb->next = erts_global_offheap.mso;
659
erts_global_offheap.mso = pb;
660
erts_global_offheap.overhead += pb->size / sizeof(Eterm);
680
pb->next = erts_global_offheap.first;
681
erts_global_offheap.first = pb;
682
OH_OVERHEAD(off_heap, pb->size / sizeof(Eterm));
680
#ifndef HYBRID // FIND ME!
681
funp->next = erts_global_offheap.funs;
682
erts_global_offheap.funs = funp;
702
#ifndef HYBRID /* FIND ME! */
703
funp->next = erts_global_offheap.first;
704
erts_global_offheap.first = funp;
683
705
erts_refc_inc(&funp->fe->refc, 2);
685
707
for (i = k; i < j; i++) {
726
etp->next = erts_global_offheap.externals;
727
erts_global_offheap.externals = etp;
748
etp->next = erts_global_offheap.first;
749
erts_global_offheap.first = etp;
728
750
erts_refc_inc(&etp->node->refc, 2);
780
802
to_bin->size = real_size;
781
803
to_bin->val = from_bin->val;
782
804
to_bin->bytes = from_bin->bytes + sub_offset;
783
to_bin->next = erts_global_offheap.mso;
784
erts_global_offheap.mso = to_bin;
785
erts_global_offheap.overhead += to_bin->size / sizeof(Eterm);
805
to_bin->next = erts_global_offheap.first;
806
erts_global_offheap.first = to_bin;
807
OH_OVERHEAD(&erts_global_offheap, to_bin->size / sizeof(Eterm));
786
808
res_binary=make_binary(to_bin);
787
809
hp += PROC_BIN_SIZE;
891
913
* NOTE: Assumes that term is a tuple (ptr is an untagged tuple ptr).
894
copy_shallow(Eterm* ptr, Uint sz, Eterm** hpp, ErlOffHeap* off_heap)
916
Eterm copy_shallow_rel(Eterm* ptr, Uint sz, Eterm** hpp, ErlOffHeap* off_heap,
919
Eterm copy_shallow(Eterm* ptr, Uint sz, Eterm** hpp, ErlOffHeap* off_heap)
897
923
Eterm* hp = *hpp;
924
const Eterm res = make_tuple(hp);
926
const Sint offs = COMPRESS_POINTER(hp - (tp - src_base));
928
const Sint offs = (hp - tp) * sizeof(Eterm);
901
932
Eterm val = *tp++;
916
947
case REFC_BINARY_SUBTAG:
918
ProcBin* pb = (ProcBin *) (hp-1);
919
int tari = thing_arityval(val);
949
ProcBin* pb = (ProcBin *) (tp-1);
925
950
erts_refc_inc(&pb->val->refc, 2);
926
pb->next = off_heap->mso;
928
off_heap->overhead += pb->size / sizeof(Eterm);
951
OH_OVERHEAD(off_heap, pb->size / sizeof(Eterm));
953
goto off_heap_common;
933
#ifndef HYBRID /* FIND ME! */
934
ErlFunThing* funp = (ErlFunThing *) (hp-1);
936
int tari = thing_arityval(val);
942
#ifndef HYBRID /* FIND ME! */
943
funp->next = off_heap->funs;
944
off_heap->funs = funp;
957
ErlFunThing* funp = (ErlFunThing *) (tp-1);
945
958
erts_refc_inc(&funp->fe->refc, 2);
960
goto off_heap_common;
949
962
case EXTERNAL_PID_SUBTAG:
950
963
case EXTERNAL_PORT_SUBTAG:
951
964
case EXTERNAL_REF_SUBTAG:
953
ExternalThing* etp = (ExternalThing *) (hp-1);
954
int tari = thing_arityval(val);
960
etp->next = off_heap->externals;
961
off_heap->externals = etp;
966
ExternalThing* etp = (ExternalThing *) (tp-1);
962
967
erts_refc_inc(&etp->node->refc, 2);
971
struct erl_off_heap_header* ohh = (struct erl_off_heap_header*)(hp-1);
972
int tari = thing_arityval(val);
978
ohh->next = off_heap->first;
979
off_heap->first = ohh;
967
984
int tari = header_arity(val);
980
return make_tuple(ptr + offs);
1001
/* Move all terms in heap fragments into heap. The terms must be guaranteed to
1002
* be contained within the fragments. The source terms are destructed with
1004
* Typically used to copy a multi-fragmented message (from NIF).
1006
void move_multi_frags(Eterm** hpp, ErlOffHeap* off_heap, ErlHeapFragment* first,
1007
Eterm* refs, unsigned nrefs)
1009
ErlHeapFragment* bp;
1010
Eterm* hp_start = *hpp;
1015
for (bp=first; bp!=NULL; bp=bp->next) {
1016
move_one_frag(hpp, bp->mem, bp->used_size, off_heap);
1017
OH_OVERHEAD(off_heap, bp->off_heap.overhead);
1020
for (hp=hp_start; hp<hp_end; ++hp) {
1024
switch (primary_tag(gval)) {
1025
case TAG_PRIMARY_BOXED:
1026
ptr = boxed_val(gval);
1028
if (IS_MOVED_BOXED(val)) {
1029
ASSERT(is_boxed(val));
1033
case TAG_PRIMARY_LIST:
1034
ptr = list_val(gval);
1036
if (IS_MOVED_CONS(val)) {
1040
case TAG_PRIMARY_HEADER:
1041
if (header_is_thing(gval)) {
1042
hp += thing_arityval(gval);
1047
for (i=0; i<nrefs; ++i) {
1048
refs[i] = follow_moved(refs[i]);
1053
move_one_frag(Eterm** hpp, Eterm* src, Uint src_sz, ErlOffHeap* off_heap)
1056
Eterm* end = ptr + src_sz;
1060
while (ptr != end) {
1064
ASSERT(val != ERTS_HOLE_MARKER);
1065
if (is_header(val)) {
1066
struct erl_off_heap_header* hdr = (struct erl_off_heap_header*)hp;
1067
ASSERT(ptr + header_arity(val) < end);
1068
MOVE_BOXED(ptr, val, hp, &dummy_ref);
1069
switch (val & _HEADER_SUBTAG_MASK) {
1070
case REFC_BINARY_SUBTAG:
1072
case EXTERNAL_PID_SUBTAG:
1073
case EXTERNAL_PORT_SUBTAG:
1074
case EXTERNAL_REF_SUBTAG:
1075
hdr->next = off_heap->first;
1076
off_heap->first = hdr;
1080
else { /* must be a cons cell */
1081
ASSERT(ptr+1 < end);
1082
MOVE_CONS(ptr, val, hp, &dummy_ref);