summaryrefslogtreecommitdiff
path: root/py
diff options
context:
space:
mode:
Diffstat (limited to 'py')
-rw-r--r--py/mpconfig.h12
-rw-r--r--py/mpstate.h5
-rw-r--r--py/persistentcode.c14
-rw-r--r--py/runtime.c4
4 files changed, 34 insertions, 1 deletions
diff --git a/py/mpconfig.h b/py/mpconfig.h
index 287b15aae..3d9ce8bb5 100644
--- a/py/mpconfig.h
+++ b/py/mpconfig.h
@@ -351,6 +351,18 @@
// Convenience definition for whether any native or inline assembler emitter is enabled
#define MICROPY_EMIT_MACHINE_CODE (MICROPY_EMIT_NATIVE || MICROPY_EMIT_INLINE_ASM)
+// Whether native relocatable code loaded from .mpy files is explicitly tracked
+// so that the GC cannot reclaim it. Needed on architectures that allocate
+// executable memory on the MicroPython heap and don't explicitly track this
+// data some other way.
+#ifndef MICROPY_PERSISTENT_CODE_TRACK_RELOC_CODE
+#if !MICROPY_EMIT_MACHINE_CODE || defined(MP_PLAT_ALLOC_EXEC) || defined(MP_PLAT_COMMIT_EXEC)
+#define MICROPY_PERSISTENT_CODE_TRACK_RELOC_CODE (0)
+#else
+#define MICROPY_PERSISTENT_CODE_TRACK_RELOC_CODE (1)
+#endif
+#endif
+
/*****************************************************************************/
/* Compiler configuration */
diff --git a/py/mpstate.h b/py/mpstate.h
index 5f6cf5593..2519c77e2 100644
--- a/py/mpstate.h
+++ b/py/mpstate.h
@@ -167,6 +167,11 @@ typedef struct _mp_state_vm_t {
mp_obj_dict_t *mp_module_builtins_override_dict;
#endif
+ #if MICROPY_PERSISTENT_CODE_TRACK_RELOC_CODE
+ // An mp_obj_list_t that tracks relocated native code to prevent the GC from reclaiming them.
+ mp_obj_t track_reloc_code_list;
+ #endif
+
// include any root pointers defined by a port
MICROPY_PORT_ROOT_POINTERS
diff --git a/py/persistentcode.c b/py/persistentcode.c
index 386ea4947..da3234a5f 100644
--- a/py/persistentcode.c
+++ b/py/persistentcode.c
@@ -3,7 +3,7 @@
*
* The MIT License (MIT)
*
- * Copyright (c) 2013-2016 Damien P. George
+ * Copyright (c) 2013-2020 Damien P. George
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -516,6 +516,18 @@ STATIC mp_raw_code_t *load_raw_code(mp_reader_t *reader, qstr_window_t *qw) {
fun_data = MP_PLAT_COMMIT_EXEC(fun_data, fun_data_len, opt_ri);
#else
if (prelude.scope_flags & MP_SCOPE_FLAG_VIPERRELOC) {
+ #if MICROPY_PERSISTENT_CODE_TRACK_RELOC_CODE
+ // If native code needs relocations then it's not guaranteed that a pointer to
+ // the head of `buf` (containing the machine code) will be retained for the GC
+ // to trace. This is because native functions can start inside `buf` and so
+ // it's possible that the only GC-reachable pointers are pointers inside `buf`.
+ // So put this `buf` on a list of reachable root pointers.
+ if (MP_STATE_PORT(track_reloc_code_list) == MP_OBJ_NULL) {
+ MP_STATE_PORT(track_reloc_code_list) = mp_obj_new_list(0, NULL);
+ }
+ mp_obj_list_append(MP_STATE_PORT(track_reloc_code_list), MP_OBJ_FROM_PTR(fun_data));
+ #endif
+ // Do the relocations.
mp_native_relocate(&ri, fun_data, (uintptr_t)fun_data);
}
#endif
diff --git a/py/runtime.c b/py/runtime.c
index 78da38691..38da2f453 100644
--- a/py/runtime.c
+++ b/py/runtime.c
@@ -106,6 +106,10 @@ void mp_init(void) {
MP_STATE_VM(mp_module_builtins_override_dict) = NULL;
#endif
+ #if MICROPY_PERSISTENT_CODE_TRACK_RELOC_CODE
+ MP_STATE_VM(track_reloc_code_list) = MP_OBJ_NULL;
+ #endif
+
#if MICROPY_PY_OS_DUPTERM
for (size_t i = 0; i < MICROPY_PY_OS_DUPTERM; ++i) {
MP_STATE_VM(dupterm_objs[i]) = MP_OBJ_NULL;