Skip to content

Commit 67f0d3f

Browse files
committed
Merge pull request #1739 from pguyot/w27/move-context-functions-out-of-opcodeswitch
Move and rename several functions out of opcodeswitch 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 5790613 + 09f7d94 commit 67f0d3f

File tree

6 files changed

+245
-237
lines changed

6 files changed

+245
-237
lines changed

src/libAtomVM/context.c

Lines changed: 172 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -971,3 +971,175 @@ term context_get_monitor_pid(Context *ctx, uint64_t ref_ticks, bool *is_monitori
971971
}
972972
return term_invalid_term();
973973
}
974+
975+
int context_get_catch_label(Context *ctx, Module **mod)
976+
{
977+
term *ct = ctx->e;
978+
term *last_frame = ctx->e;
979+
980+
while (ct != ctx->heap.heap_end) {
981+
if (term_is_catch_label(*ct)) {
982+
int target_module;
983+
int target_label = term_to_catch_label_and_module(*ct, &target_module);
984+
TRACE("- found catch: label: %i, module: %i\n", target_label, target_module);
985+
*mod = globalcontext_get_module_by_index(ctx->global, target_module);
986+
987+
DEBUG_DUMP_STACK(ctx);
988+
ctx->e = last_frame;
989+
DEBUG_DUMP_STACK(ctx);
990+
991+
return target_label;
992+
993+
} else if (term_is_cp(*ct)) {
994+
last_frame = ct + 1;
995+
}
996+
997+
ct++;
998+
}
999+
1000+
return 0;
1001+
}
1002+
1003+
COLD_FUNC void context_dump(Context *ctx)
1004+
{
1005+
GlobalContext *glb = ctx->global;
1006+
1007+
fprintf(stderr, "CRASH \n======\n");
1008+
1009+
fprintf(stderr, "pid: ");
1010+
term_display(stderr, term_from_local_process_id(ctx->process_id), ctx);
1011+
fprintf(stderr, "\n");
1012+
1013+
fprintf(stderr, "\nStacktrace:\n");
1014+
term_display(stderr, stacktrace_build(ctx, &ctx->x[2], 3), ctx);
1015+
fprintf(stderr, "\n\n");
1016+
1017+
{
1018+
Module *cp_mod;
1019+
int label;
1020+
int offset;
1021+
module_cp_to_label_offset(ctx->cp, &cp_mod, &label, &offset, NULL, ctx->global);
1022+
fprintf(stderr, "cp: #CP<module: %i, label: %i, offset: %i>\n\n",
1023+
cp_mod->module_index, label, offset);
1024+
}
1025+
1026+
fprintf(stderr, "x[0]: ");
1027+
term_display(stderr, ctx->x[0], ctx);
1028+
fprintf(stderr, "\nx[1]: ");
1029+
term_display(stderr, ctx->x[1], ctx);
1030+
fprintf(stderr, "\nx[2]: ");
1031+
term_display(stderr, ctx->x[2], ctx);
1032+
fprintf(stderr, "\n\nStack \n-----\n\n");
1033+
1034+
term *ct = ctx->e;
1035+
1036+
while (ct != ctx->heap.heap_end) {
1037+
if (term_is_catch_label(*ct)) {
1038+
int target_module;
1039+
int target_label = term_to_catch_label_and_module(*ct, &target_module);
1040+
fprintf(stderr, "catch: %i:%i\n", target_label, target_module);
1041+
1042+
} else if (term_is_cp(*ct)) {
1043+
Module *cp_mod;
1044+
int label;
1045+
int offset;
1046+
module_cp_to_label_offset(*ct, &cp_mod, &label, &offset, NULL, ctx->global);
1047+
fprintf(stderr, "#CP<module: %i, label: %i, offset: %i>\n", cp_mod->module_index, label, offset);
1048+
1049+
} else {
1050+
term_display(stderr, *ct, ctx);
1051+
fprintf(stderr, "\n");
1052+
}
1053+
1054+
ct++;
1055+
}
1056+
1057+
fprintf(stderr, "\n\nMailbox\n-------\n");
1058+
mailbox_crashdump(ctx);
1059+
1060+
fprintf(stderr, "\n\nMonitors\n--------\n");
1061+
// Lock processes table to make sure any dying process will not modify monitors
1062+
struct ListHead *processes_table = synclist_rdlock(&glb->processes_table);
1063+
UNUSED(processes_table);
1064+
struct ListHead *item;
1065+
LIST_FOR_EACH (item, &ctx->monitors_head) {
1066+
struct Monitor *monitor = GET_LIST_ENTRY(item, struct Monitor, monitor_list_head);
1067+
switch (monitor->monitor_type) {
1068+
case CONTEXT_MONITOR_LINK_LOCAL: {
1069+
struct LinkLocalMonitor *link_monitor = CONTAINER_OF(monitor, struct LinkLocalMonitor, monitor);
1070+
fprintf(stderr, "link ");
1071+
if (link_monitor->unlink_id) {
1072+
fprintf(stderr, "(inactive) ");
1073+
}
1074+
fprintf(stderr, "to ");
1075+
term_display(stderr, link_monitor->link_local_process_id, ctx);
1076+
fprintf(stderr, "\n");
1077+
break;
1078+
}
1079+
case CONTEXT_MONITOR_LINK_REMOTE: {
1080+
struct LinkRemoteMonitor *link_monitor = CONTAINER_OF(monitor, struct LinkRemoteMonitor, monitor);
1081+
fprintf(stderr, "remote link ");
1082+
if (link_monitor->unlink_id) {
1083+
fprintf(stderr, "(inactive) ");
1084+
}
1085+
fprintf(stderr, "to ");
1086+
term_display(stderr, link_monitor->node, ctx);
1087+
fprintf(stderr, "\n");
1088+
break;
1089+
}
1090+
case CONTEXT_MONITOR_MONITORING_LOCAL: {
1091+
struct MonitorLocalMonitor *monitoring_monitor = CONTAINER_OF(monitor, struct MonitorLocalMonitor, monitor);
1092+
fprintf(stderr, "monitor to ");
1093+
term_display(stderr, monitoring_monitor->monitor_obj, ctx);
1094+
fprintf(stderr, " ref=%lu", (long unsigned) monitoring_monitor->ref_ticks);
1095+
fprintf(stderr, "\n");
1096+
break;
1097+
}
1098+
case CONTEXT_MONITOR_MONITORED_LOCAL: {
1099+
struct MonitorLocalMonitor *monitored_monitor = CONTAINER_OF(monitor, struct MonitorLocalMonitor, monitor);
1100+
fprintf(stderr, "monitored by ");
1101+
term_display(stderr, monitored_monitor->monitor_obj, ctx);
1102+
fprintf(stderr, " ref=%lu", (long unsigned) monitored_monitor->ref_ticks);
1103+
fprintf(stderr, "\n");
1104+
break;
1105+
}
1106+
case CONTEXT_MONITOR_RESOURCE: {
1107+
struct ResourceContextMonitor *resource_monitor = CONTAINER_OF(monitor, struct ResourceContextMonitor, monitor);
1108+
fprintf(stderr, "monitored by resource %p ref=%lu", resource_monitor->resource_obj, (long unsigned) resource_monitor->ref_ticks);
1109+
fprintf(stderr, "\n");
1110+
break;
1111+
}
1112+
}
1113+
}
1114+
synclist_unlock(&glb->processes_table);
1115+
1116+
// If crash is caused by out_of_memory, print more data about memory usage
1117+
if (ctx->x[0] == ERROR_ATOM && ctx->x[1] == OUT_OF_MEMORY_ATOM) {
1118+
fprintf(stderr, "\n\nContext memory info\n-------------------\n");
1119+
fprintf(stderr, "context_size = %zu\n", context_size(ctx));
1120+
fprintf(stderr, "context_avail_free_memory = %zu\n", context_avail_free_memory(ctx));
1121+
fprintf(stderr, "heap_size = %zu\n", memory_heap_youngest_size(&ctx->heap));
1122+
fprintf(stderr, "total_heap_size = %zu\n", memory_heap_memory_size(&ctx->heap));
1123+
fprintf(stderr, "stack_size = %zu\n", context_stack_size(ctx));
1124+
fprintf(stderr, "message_queue_len = %zu\n", context_message_queue_len(ctx));
1125+
fprintf(stderr, "\n\nGlobal memory info\n------------------\n");
1126+
1127+
processes_table = synclist_rdlock(&glb->processes_table);
1128+
size_t process_count = 0;
1129+
size_t ports_count = 0;
1130+
LIST_FOR_EACH (item, processes_table) {
1131+
Context *p = GET_LIST_ENTRY(item, Context, processes_table_head);
1132+
process_count++;
1133+
if (p->native_handler) {
1134+
ports_count++;
1135+
}
1136+
}
1137+
synclist_unlock(&glb->processes_table);
1138+
1139+
fprintf(stderr, "process_count = %zu\n", process_count);
1140+
fprintf(stderr, "ports_count = %zu\n", ports_count);
1141+
fprintf(stderr, "atoms_count = %zu\n", atom_table_count(glb->atom_table));
1142+
fprintf(stderr, "refc_binary_total_size = %zu\n", refc_binary_total_size(ctx));
1143+
}
1144+
fprintf(stderr, "\n\n**End Of Crash Report**\n");
1145+
}

src/libAtomVM/context.h

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -563,6 +563,22 @@ term context_get_monitor_pid(Context *ctx, uint64_t ref_ticks, bool *is_monitori
563563
*/
564564
bool context_add_monitor(Context *ctx, struct Monitor *new_monitor);
565565

566+
/**
567+
* @brief Get catch label from stack
568+
*
569+
* @param ctx the context being executed
570+
* @param mod on output, the module
571+
* @return the found label or 0 if no catch label was found in the stack
572+
*/
573+
int context_get_catch_label(Context *ctx, Module **mod);
574+
575+
/**
576+
* @brief Dump context to stderr
577+
*
578+
* @param ctx context to dump
579+
*/
580+
void context_dump(Context *ctx);
581+
566582
#ifdef __cplusplus
567583
}
568584
#endif

src/libAtomVM/module.c

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -828,3 +828,43 @@ bool module_find_line(Module *mod, unsigned int offset, uint32_t *line, size_t *
828828
DECODE_LITERAL(line_ref, ref_pc);
829829
return module_find_line_ref(mod, line_ref, line, filename_len, filename);
830830
}
831+
832+
COLD_FUNC void module_cp_to_label_offset(term cp, Module **cp_mod, int *label, int *l_off, long *out_mod_offset, GlobalContext *global)
833+
{
834+
Module *mod = globalcontext_get_module_by_index(global, ((uintptr_t) cp) >> 24);
835+
long mod_offset = (cp & 0xFFFFFF) >> 2;
836+
if (out_mod_offset) {
837+
*out_mod_offset = mod_offset;
838+
}
839+
840+
if (cp_mod) {
841+
*cp_mod = mod;
842+
}
843+
844+
uint8_t *code = &mod->code->code[0];
845+
int labels_count = ENDIAN_SWAP_32(mod->code->labels);
846+
847+
int i = 1;
848+
const uint8_t *l = mod->labels[1];
849+
while (mod_offset > l - code) {
850+
i++;
851+
if (i >= labels_count) {
852+
// last label + 1 is reserved for end of module.
853+
if (label) {
854+
*label = i;
855+
}
856+
if (l_off) {
857+
*l_off = 0;
858+
}
859+
return;
860+
}
861+
l = mod->labels[i];
862+
}
863+
864+
if (label) {
865+
*label = i - 1;
866+
}
867+
if (l_off) {
868+
*l_off = mod_offset - (mod->labels[*label] - code);
869+
}
870+
}

src/libAtomVM/module.h

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -396,6 +396,18 @@ static inline bool module_has_line_chunk(Module *mod)
396396
return mod->line_refs_table != NULL;
397397
}
398398

399+
/*
400+
* @brief Get the module, offset, label and label offset from module start from a continuation pointer.
401+
*
402+
* @param cp continuation pointer to parse
403+
* @param cp_mod if not null, set to found module
404+
* @param label if not null, set to found label
405+
* @param l_off if not null, set to offset of label from module start
406+
* @param mod_offset if not null, set to offset of cp from module start
407+
* @param global the global context
408+
*/
409+
void module_cp_to_label_offset(term cp, Module **cp_mod, int *label, int *l_off, long *mod_offset, GlobalContext *global);
410+
399411
#ifdef __cplusplus
400412
}
401413
#endif

0 commit comments

Comments
 (0)