py, unix: Trace root pointers with native emitter under unix port.
Native code has GC-heap pointers in it so it must be scanned. But on unix port memory for native functions is mmap'd, and so it must have explicit code to scan it for root pointers.
This commit is contained in:
parent
c935d69f74
commit
2127e9a844
|
@ -1174,6 +1174,7 @@ STATIC void emit_native_load_const_str(emit_t *emit, qstr qst, bool bytes) {
|
||||||
|
|
||||||
STATIC void emit_native_load_const_obj(emit_t *emit, void *obj) {
|
STATIC void emit_native_load_const_obj(emit_t *emit, void *obj) {
|
||||||
emit_native_pre(emit);
|
emit_native_pre(emit);
|
||||||
|
need_reg_single(emit, REG_RET, 0);
|
||||||
ASM_MOV_ALIGNED_IMM_TO_REG(emit->as, (mp_uint_t)obj, REG_RET);
|
ASM_MOV_ALIGNED_IMM_TO_REG(emit->as, (mp_uint_t)obj, REG_RET);
|
||||||
emit_post_push_reg(emit, VTYPE_PYOBJ, REG_RET);
|
emit_post_push_reg(emit, VTYPE_PYOBJ, REG_RET);
|
||||||
}
|
}
|
||||||
|
|
|
@ -569,6 +569,9 @@ typedef double mp_float_t;
|
||||||
#define MICROPY_MAKE_POINTER_CALLABLE(p) (p)
|
#define MICROPY_MAKE_POINTER_CALLABLE(p) (p)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
// If these MP_PLAT_* macros are overridden then the memory allocated by them
|
||||||
|
// must be somehow reachable for marking by the GC, since the native code
|
||||||
|
// generators store pointers to GC managed memory in the code.
|
||||||
#ifndef MP_PLAT_ALLOC_EXEC
|
#ifndef MP_PLAT_ALLOC_EXEC
|
||||||
#define MP_PLAT_ALLOC_EXEC(min_size, ptr, size) do { *ptr = m_new(byte, min_size); *size = min_size; } while(0)
|
#define MP_PLAT_ALLOC_EXEC(min_size, ptr, size) do { *ptr = m_new(byte, min_size); *size = min_size; } while(0)
|
||||||
#endif
|
#endif
|
||||||
|
|
38
unix/alloc.c
38
unix/alloc.c
|
@ -24,16 +24,29 @@
|
||||||
* THE SOFTWARE.
|
* THE SOFTWARE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
#include <sys/mman.h>
|
#include <sys/mman.h>
|
||||||
|
|
||||||
#include "mpconfigport.h"
|
#include "py/mpstate.h"
|
||||||
|
#include "py/gc.h"
|
||||||
|
|
||||||
#if defined(__OpenBSD__) || defined(__MACH__)
|
#if defined(__OpenBSD__) || defined(__MACH__)
|
||||||
#define MAP_ANONYMOUS MAP_ANON
|
#define MAP_ANONYMOUS MAP_ANON
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
// The memory allocated here is not on the GC heap (and it may contain pointers
|
||||||
|
// that need to be GC'd) so we must somehow trace this memory. We do it by
|
||||||
|
// keeping a linked list of all mmap'd regions, and tracing them explicitly.
|
||||||
|
|
||||||
|
typedef struct _mmap_region_t {
|
||||||
|
void *ptr;
|
||||||
|
size_t len;
|
||||||
|
struct _mmap_region_t *next;
|
||||||
|
} mmap_region_t;
|
||||||
|
|
||||||
void mp_unix_alloc_exec(mp_uint_t min_size, void **ptr, mp_uint_t *size) {
|
void mp_unix_alloc_exec(mp_uint_t min_size, void **ptr, mp_uint_t *size) {
|
||||||
// size needs to be a multiple of the page size
|
// size needs to be a multiple of the page size
|
||||||
*size = (min_size + 0xfff) & (~0xfff);
|
*size = (min_size + 0xfff) & (~0xfff);
|
||||||
|
@ -41,8 +54,31 @@ void mp_unix_alloc_exec(mp_uint_t min_size, void **ptr, mp_uint_t *size) {
|
||||||
if (*ptr == MAP_FAILED) {
|
if (*ptr == MAP_FAILED) {
|
||||||
*ptr = NULL;
|
*ptr = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// add new link to the list of mmap'd regions
|
||||||
|
mmap_region_t *rg = m_new_obj(mmap_region_t);
|
||||||
|
rg->ptr = *ptr;
|
||||||
|
rg->len = min_size;
|
||||||
|
rg->next = MP_STATE_VM(mmap_region_head);
|
||||||
|
MP_STATE_VM(mmap_region_head) = rg;
|
||||||
}
|
}
|
||||||
|
|
||||||
void mp_unix_free_exec(void *ptr, mp_uint_t size) {
|
void mp_unix_free_exec(void *ptr, mp_uint_t size) {
|
||||||
munmap(ptr, size);
|
munmap(ptr, size);
|
||||||
|
|
||||||
|
// unlink the mmap'd region from the list
|
||||||
|
for (mmap_region_t **rg = (mmap_region_t**)&MP_STATE_VM(mmap_region_head); *rg != NULL; *rg = (*rg)->next) {
|
||||||
|
if ((*rg)->ptr == ptr) {
|
||||||
|
mmap_region_t *next = (*rg)->next;
|
||||||
|
m_del_obj(mmap_region_t, *rg);
|
||||||
|
*rg = next;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void mp_unix_mark_exec(void) {
|
||||||
|
for (mmap_region_t *rg = MP_STATE_VM(mmap_region_head); rg != NULL; rg = rg->next) {
|
||||||
|
gc_collect_root(rg->ptr, rg->len / sizeof(mp_uint_t));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -31,8 +31,6 @@
|
||||||
|
|
||||||
#if MICROPY_ENABLE_GC
|
#if MICROPY_ENABLE_GC
|
||||||
|
|
||||||
extern char *stack_top;
|
|
||||||
|
|
||||||
#if MICROPY_GCREGS_SETJMP
|
#if MICROPY_GCREGS_SETJMP
|
||||||
#include <setjmp.h>
|
#include <setjmp.h>
|
||||||
|
|
||||||
|
@ -133,6 +131,7 @@ void gc_collect(void) {
|
||||||
// GC stack (and regs because we captured them)
|
// GC stack (and regs because we captured them)
|
||||||
void **regs_ptr = (void**)(void*)®s;
|
void **regs_ptr = (void**)(void*)®s;
|
||||||
gc_collect_root(regs_ptr, ((mp_uint_t)MP_STATE_VM(stack_top) - (mp_uint_t)®s) / sizeof(mp_uint_t));
|
gc_collect_root(regs_ptr, ((mp_uint_t)MP_STATE_VM(stack_top) - (mp_uint_t)®s) / sizeof(mp_uint_t));
|
||||||
|
mp_unix_mark_exec();
|
||||||
gc_collect_end();
|
gc_collect_end();
|
||||||
|
|
||||||
//printf("-----\n");
|
//printf("-----\n");
|
||||||
|
|
|
@ -148,6 +148,7 @@ typedef const void *machine_const_ptr_t; // must be of pointer size
|
||||||
|
|
||||||
void mp_unix_alloc_exec(mp_uint_t min_size, void** ptr, mp_uint_t *size);
|
void mp_unix_alloc_exec(mp_uint_t min_size, void** ptr, mp_uint_t *size);
|
||||||
void mp_unix_free_exec(void *ptr, mp_uint_t size);
|
void mp_unix_free_exec(void *ptr, mp_uint_t size);
|
||||||
|
void mp_unix_mark_exec(void);
|
||||||
#define MP_PLAT_ALLOC_EXEC(min_size, ptr, size) mp_unix_alloc_exec(min_size, ptr, size)
|
#define MP_PLAT_ALLOC_EXEC(min_size, ptr, size) mp_unix_alloc_exec(min_size, ptr, size)
|
||||||
#define MP_PLAT_FREE_EXEC(ptr, size) mp_unix_free_exec(ptr, size)
|
#define MP_PLAT_FREE_EXEC(ptr, size) mp_unix_free_exec(ptr, size)
|
||||||
|
|
||||||
|
@ -158,7 +159,8 @@ extern const struct _mp_obj_fun_builtin_t mp_builtin_open_obj;
|
||||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_open), (mp_obj_t)&mp_builtin_open_obj },
|
{ MP_OBJ_NEW_QSTR(MP_QSTR_open), (mp_obj_t)&mp_builtin_open_obj },
|
||||||
|
|
||||||
#define MICROPY_PORT_ROOT_POINTERS \
|
#define MICROPY_PORT_ROOT_POINTERS \
|
||||||
mp_obj_t keyboard_interrupt_obj;
|
mp_obj_t keyboard_interrupt_obj; \
|
||||||
|
void *mmap_region_head; \
|
||||||
|
|
||||||
// We need to provide a declaration/definition of alloca()
|
// We need to provide a declaration/definition of alloca()
|
||||||
#ifdef __FreeBSD__
|
#ifdef __FreeBSD__
|
||||||
|
|
Loading…
Reference in New Issue