aboutsummaryrefslogtreecommitdiffstats
path: root/erts/emulator/beam/external.c
diff options
context:
space:
mode:
Diffstat (limited to 'erts/emulator/beam/external.c')
-rw-r--r--erts/emulator/beam/external.c39
1 files changed, 35 insertions, 4 deletions
diff --git a/erts/emulator/beam/external.c b/erts/emulator/beam/external.c
index 4cd57d8aeb..8f0e19d27d 100644
--- a/erts/emulator/beam/external.c
+++ b/erts/emulator/beam/external.c
@@ -4172,8 +4172,12 @@ encode_size_struct_int(TTBSizeContext* ctx, ErtsAtomCacheMap *acmp, Eterm obj,
case HAMT_SUBTAG_HEAD_ARRAY:
ptr++;
node_sz = 16;
+ result += 1 + 4; /* tag + 4 bytes size */
break;
- case HAMT_SUBTAG_HEAD_BITMAP: ptr++;
+ case HAMT_SUBTAG_HEAD_BITMAP:
+ ptr++;
+ result += 1 + 4; /* tag + 4 bytes size */
+ /*fall through*/
case HAMT_SUBTAG_NODE_BITMAP:
node_sz = hashmap_bitcount(MAP_HEADER_VAL(hdr));
ASSERT(node_sz < 17);
@@ -4183,11 +4187,38 @@ encode_size_struct_int(TTBSizeContext* ctx, ErtsAtomCacheMap *acmp, Eterm obj,
}
ptr++;
- ESTACK_RESERVE(s, node_sz);
+ ESTACK_RESERVE(s, node_sz*2);
while(node_sz--) {
- ESTACK_FAST_PUSH(s, *ptr++);
+ if (is_list(*ptr)) {
+ Eterm* leaf = list_val(*ptr);
+ if (is_not_list(CAR(leaf))) {
+ ESTACK_FAST_PUSH(s, CAR(leaf));
+ }
+ else {
+ if ((m = is_string(CAR(leaf))) && (m < MAX_STRING_LEN)) {
+ result += m + 2 + 1;
+ } else {
+ result += 5;
+ ESTACK_FAST_PUSH(s, CAR(leaf));
+ }
+ }
+ if (is_not_list(CDR(leaf))) {
+ ESTACK_FAST_PUSH(s, CDR(leaf));
+ }
+ else {
+ if ((m = is_string(CDR(leaf))) && (m < MAX_STRING_LEN)) {
+ result += m + 2 + 1;
+ } else {
+ result += 5;
+ ESTACK_FAST_PUSH(s, CDR(leaf));
+ }
+ }
+ }
+ else {
+ ESTACK_FAST_PUSH(s, *ptr);
+ }
+ ptr++;
}
- result += 1 + 4; /* tag + 4 bytes size */
}
break;