Skip to content

Commit 8effe63

Browse files
committed
Merge pull request #1772 from pguyot/w29/optimize-term-compare
Optimize `term_compare` These changes are made under both the "Apache 2.0" and the "GNU Lesser General Public License 2.1 or later" license terms (dual license). SPDX-License-Identifier: Apache-2.0 OR LGPL-2.1-or-later
2 parents 26acfe2 + 1afe70a commit 8effe63

File tree

3 files changed

+445
-389
lines changed

3 files changed

+445
-389
lines changed

src/libAtomVM/memory.c

Lines changed: 87 additions & 87 deletions
Original file line numberDiff line numberDiff line change
@@ -470,101 +470,101 @@ unsigned long memory_estimate_usage(term t)
470470
}
471471

472472
while (!temp_stack_is_empty(&temp_stack)) {
473-
if (term_is_atom(t)) {
474-
t = temp_stack_pop(&temp_stack);
475-
476-
} else if (term_is_integer(t)) {
477-
t = temp_stack_pop(&temp_stack);
478-
479-
} else if (term_is_nil(t)) {
480-
t = temp_stack_pop(&temp_stack);
481-
482-
} else if (term_is_local_pid(t)) {
483-
t = temp_stack_pop(&temp_stack);
484-
485-
} else if (term_is_local_port(t)) {
486-
t = temp_stack_pop(&temp_stack);
487-
488-
} else if (term_is_nonempty_list(t)) {
489-
acc += 2;
490-
if (UNLIKELY(temp_stack_push(&temp_stack, term_get_list_tail(t)) != TempStackOk)) {
491-
// TODO: handle failed malloc
492-
AVM_ABORT();
493-
}
494-
t = term_get_list_head(t);
495-
496-
} else if (term_is_tuple(t)) {
497-
int tuple_size = term_get_tuple_arity(t);
498-
acc += tuple_size + 1;
499-
500-
if (tuple_size > 0) {
501-
for (int i = 1; i < tuple_size; i++) {
502-
if (UNLIKELY(temp_stack_push(&temp_stack, term_get_tuple_element(t, i)) != TempStackOk)) {
503-
// TODO: handle failed malloc
504-
AVM_ABORT();
505-
}
506-
}
507-
t = term_get_tuple_element(t, 0);
508-
509-
} else {
510-
t = term_nil();
511-
}
512-
513-
} else if (term_is_map(t)) {
514-
int map_size = term_get_map_size(t);
515-
acc += term_map_size_in_terms(map_size);
516-
if (map_size > 0) {
517-
for (int i = 1; i < map_size; i++) {
518-
if (UNLIKELY(temp_stack_push(&temp_stack, term_get_map_key(t, i)) != TempStackOk)) {
519-
// TODO: handle failed malloc
520-
AVM_ABORT();
521-
}
522-
if (UNLIKELY(temp_stack_push(&temp_stack, term_get_map_value(t, i)) != TempStackOk)) {
523-
// TODO: handle failed malloc
524-
AVM_ABORT();
525-
}
526-
}
527-
if (UNLIKELY(temp_stack_push(&temp_stack, term_get_map_value(t, 0)) != TempStackOk)) {
473+
switch (t & TERM_PRIMARY_MASK) {
474+
case TERM_PRIMARY_IMMED:
475+
t = temp_stack_pop(&temp_stack);
476+
break;
477+
case TERM_PRIMARY_LIST:
478+
acc += 2;
479+
if (UNLIKELY(temp_stack_push(&temp_stack, term_get_list_tail(t)) != TempStackOk)) {
528480
// TODO: handle failed malloc
529481
AVM_ABORT();
530482
}
531-
t = term_get_map_key(t, 0);
483+
t = term_get_list_head(t);
484+
break;
485+
case TERM_PRIMARY_BOXED: {
486+
const term *boxed_value = term_to_const_term_ptr(t);
487+
term boxed_value_0 = boxed_value[0];
488+
switch (boxed_value_0 & TERM_BOXED_TAG_MASK) {
489+
case TERM_BOXED_TUPLE: {
490+
int tuple_size = term_get_size_from_boxed_header(boxed_value_0);
491+
acc += tuple_size + 1;
492+
493+
if (tuple_size > 0) {
494+
for (int i = 1; i < tuple_size; i++) {
495+
if (UNLIKELY(temp_stack_push(&temp_stack, term_get_tuple_element(t, i)) != TempStackOk)) {
496+
// TODO: handle failed malloc
497+
AVM_ABORT();
498+
}
499+
}
500+
t = term_get_tuple_element(t, 0);
501+
502+
} else {
503+
t = term_nil();
504+
}
505+
} break;
532506

533-
} else {
534-
t = term_nil();
535-
}
507+
case TERM_BOXED_MAP: {
508+
int map_size = term_get_map_size(t);
509+
acc += term_map_size_in_terms(map_size);
510+
if (map_size > 0) {
511+
for (int i = 1; i < map_size; i++) {
512+
if (UNLIKELY(temp_stack_push(&temp_stack, term_get_map_key(t, i)) != TempStackOk)) {
513+
// TODO: handle failed malloc
514+
AVM_ABORT();
515+
}
516+
if (UNLIKELY(temp_stack_push(&temp_stack, term_get_map_value(t, i)) != TempStackOk)) {
517+
// TODO: handle failed malloc
518+
AVM_ABORT();
519+
}
520+
}
521+
if (UNLIKELY(temp_stack_push(&temp_stack, term_get_map_value(t, 0)) != TempStackOk)) {
522+
// TODO: handle failed malloc
523+
AVM_ABORT();
524+
}
525+
t = term_get_map_key(t, 0);
526+
527+
} else {
528+
t = term_nil();
529+
}
530+
} break;
536531

537-
} else if (term_is_function(t)) {
538-
int boxed_size = term_boxed_size(t);
539-
acc += boxed_size + 1;
540-
const term *boxed_value = term_to_const_term_ptr(t);
541-
542-
// We skip the first two elements:
543-
// First is either a module atom or a pointer to a Module
544-
// Second is either a function atom or a function index
545-
// Third would be arity as a term int (external function) or
546-
// the first argument (if built with make_fun3) which we should
547-
// estimate.
548-
for (int i = 2; i < boxed_size; i++) {
549-
if (UNLIKELY(temp_stack_push(&temp_stack, boxed_value[i + 1]) != TempStackOk)) {
550-
// TODO: handle failed malloc
551-
AVM_ABORT();
552-
}
553-
}
554-
t = boxed_value[2];
532+
case TERM_BOXED_FUN: {
533+
int boxed_size = term_get_size_from_boxed_header(boxed_value_0);
534+
acc += boxed_size + 1;
535+
536+
// We skip the first two elements:
537+
// First is either a module atom or a pointer to a Module
538+
// Second is either a function atom or a function index
539+
// Third would be arity as a term int (external function) or
540+
// the first argument (if built with make_fun3) which we should
541+
// estimate.
542+
for (int i = 2; i < boxed_size; i++) {
543+
if (UNLIKELY(temp_stack_push(&temp_stack, boxed_value[i + 1]) != TempStackOk)) {
544+
// TODO: handle failed malloc
545+
AVM_ABORT();
546+
}
547+
}
548+
t = boxed_value[2];
549+
} break;
555550

556-
} else if (term_is_sub_binary(t)) {
557-
acc += term_boxed_size(t) + 1;
558-
t = term_get_sub_binary_ref(t);
551+
case TERM_BOXED_SUB_BINARY: {
552+
int boxed_size = term_get_size_from_boxed_header(boxed_value_0);
553+
acc += boxed_size + 1;
554+
t = term_get_sub_binary_ref(t);
555+
} break;
559556

560-
} else if (term_is_boxed(t)) {
561-
// Default type of boxed terms
562-
acc += term_boxed_size(t) + 1;
563-
t = temp_stack_pop(&temp_stack);
557+
default: {
558+
// Default type of boxed terms
559+
int boxed_size = term_get_size_from_boxed_header(boxed_value_0);
560+
acc += boxed_size + 1;
561+
t = temp_stack_pop(&temp_stack);
562+
}
563+
}
564+
} break;
564565

565-
} else {
566-
fprintf(stderr, "bug: found unknown term type: 0x%" TERM_X_FMT "\n", t);
567-
AVM_ABORT();
566+
default:
567+
UNREACHABLE();
568568
}
569569
}
570570

0 commit comments

Comments
 (0)