summaryrefslogtreecommitdiff
path: root/libguile
diff options
context:
space:
mode:
authorAndy Wingo <wingo@pobox.com>2015-10-28 16:40:53 +0000
committerAndy Wingo <wingo@pobox.com>2015-10-28 16:40:53 +0000
commite7660a607cabdb0061784ada2869e47db946275b (patch)
treecf58c7b791fe855811b98482345a3e404ee554d7 /libguile
parentdd77a818ba6aefc98a78d03dec61454546992671 (diff)
downloadguile-e7660a607cabdb0061784ada2869e47db946275b.tar.gz
VM support for raw slots
* libguile/loader.c (scm_find_slot_map_unlocked): Rename from scm_find_dead_slot_map_unlocked. * libguile/vm.c (struct slot_map_cache_entry, struct slot_map_cache) (find_slot_map): Rename, changing "dead_slot" to "slot". (enum slot_desc): New type. (scm_i_vm_mark_stack): Interpret slot maps as having two bits per slot, allowing us to indicate that a slot is live but not a pointer. * module/language/cps/compile-bytecode.scm (compile-function): Adapt to emit-slot-map name change. * module/system/vm/assembler.scm (<asm>): Rename dead-slot-maps field to slot-maps. (emit-slot-map): Rename from emit-dead-slot-map. (link-frame-maps): 2 bits per slot. * module/language/cps/slot-allocation.scm (lookup-slot-map): Rename from lookup-dead-slot-map. (compute-var-representations): New function. (allocate-slots): Adapt to encode two-bit slot representations.
Diffstat (limited to 'libguile')
-rw-r--r--libguile/loader.c4
-rw-r--r--libguile/loader.h4
-rw-r--r--libguile/vm.c77
3 files changed, 49 insertions, 36 deletions
diff --git a/libguile/loader.c b/libguile/loader.c
index a55bd15b0..97effb30d 100644
--- a/libguile/loader.c
+++ b/libguile/loader.c
@@ -1,5 +1,5 @@
/* Copyright (C) 2001, 2009, 2010, 2011, 2012
- * 2013, 2014 Free Software Foundation, Inc.
+ * 2013, 2014, 2015 Free Software Foundation, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public License
@@ -748,7 +748,7 @@ verify (sizeof (struct frame_map_prefix) == 8);
verify (sizeof (struct frame_map_header) == 8);
const scm_t_uint8 *
-scm_find_dead_slot_map_unlocked (const scm_t_uint32 *ip)
+scm_find_slot_map_unlocked (const scm_t_uint32 *ip)
{
struct mapped_elf_image *image;
char *base;
diff --git a/libguile/loader.h b/libguile/loader.h
index 6fd950279..5c719cbce 100644
--- a/libguile/loader.h
+++ b/libguile/loader.h
@@ -1,4 +1,4 @@
-/* Copyright (C) 2001, 2009, 2010, 2011, 2012, 2013, 2014 Free Software Foundation, Inc.
+/* Copyright (C) 2001, 2009, 2010, 2011, 2012, 2013, 2014, 2015 Free Software Foundation, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public License
@@ -25,7 +25,7 @@ SCM_API SCM scm_load_thunk_from_file (SCM filename);
SCM_API SCM scm_load_thunk_from_memory (SCM bv);
SCM_INTERNAL const scm_t_uint8 *
-scm_find_dead_slot_map_unlocked (const scm_t_uint32 *ip);
+scm_find_slot_map_unlocked (const scm_t_uint32 *ip);
SCM_INTERNAL void scm_bootstrap_loader (void);
SCM_INTERNAL void scm_init_loader (void);
diff --git a/libguile/vm.c b/libguile/vm.c
index 9d9cc3129..5ea6b2bd4 100644
--- a/libguile/vm.c
+++ b/libguile/vm.c
@@ -895,31 +895,31 @@ return_unused_stack_to_os (struct scm_vm *vp)
#endif
}
-#define DEAD_SLOT_MAP_CACHE_SIZE 32U
-struct dead_slot_map_cache_entry
+#define SLOT_MAP_CACHE_SIZE 32U
+struct slot_map_cache_entry
{
scm_t_uint32 *ip;
const scm_t_uint8 *map;
};
-struct dead_slot_map_cache
+struct slot_map_cache
{
- struct dead_slot_map_cache_entry entries[DEAD_SLOT_MAP_CACHE_SIZE];
+ struct slot_map_cache_entry entries[SLOT_MAP_CACHE_SIZE];
};
static const scm_t_uint8 *
-find_dead_slot_map (scm_t_uint32 *ip, struct dead_slot_map_cache *cache)
+find_slot_map (scm_t_uint32 *ip, struct slot_map_cache *cache)
{
/* The lower two bits should be zero. FIXME: Use a better hash
function; we don't expose scm_raw_hashq currently. */
- size_t slot = (((scm_t_uintptr) ip) >> 2) % DEAD_SLOT_MAP_CACHE_SIZE;
+ size_t slot = (((scm_t_uintptr) ip) >> 2) % SLOT_MAP_CACHE_SIZE;
const scm_t_uint8 *map;
if (cache->entries[slot].ip == ip)
map = cache->entries[slot].map;
else
{
- map = scm_find_dead_slot_map_unlocked (ip);
+ map = scm_find_slot_map_unlocked (ip);
cache->entries[slot].ip = ip;
cache->entries[slot].map = map;
}
@@ -927,21 +927,29 @@ find_dead_slot_map (scm_t_uint32 *ip, struct dead_slot_map_cache *cache)
return map;
}
+enum slot_desc
+ {
+ SLOT_DESC_DEAD = 0,
+ SLOT_DESC_LIVE_RAW = 1,
+ SLOT_DESC_LIVE_SCM = 2,
+ SLOT_DESC_UNUSED = 3
+ };
+
/* Mark the active VM stack region. */
struct GC_ms_entry *
scm_i_vm_mark_stack (struct scm_vm *vp, struct GC_ms_entry *mark_stack_ptr,
struct GC_ms_entry *mark_stack_limit)
{
union scm_vm_stack_element *sp, *fp;
- /* The first frame will be marked conservatively (without a dead
- slot map). This is because GC can happen at any point within the
- hottest activation, due to multiple threads or per-instruction
- hooks, and providing dead slot maps for all points in a program
- would take a prohibitive amount of space. */
- const scm_t_uint8 *dead_slots = NULL;
+ /* The first frame will be marked conservatively (without a slot map).
+ This is because GC can happen at any point within the hottest
+ activation, due to multiple threads or per-instruction hooks, and
+ providing slot maps for all points in a program would take a
+ prohibitive amount of space. */
+ const scm_t_uint8 *slot_map = NULL;
void *upper = (void *) GC_greatest_plausible_heap_addr;
void *lower = (void *) GC_least_plausible_heap_addr;
- struct dead_slot_map_cache cache;
+ struct slot_map_cache cache;
memset (&cache, 0, sizeof (cache));
@@ -953,24 +961,29 @@ scm_i_vm_mark_stack (struct scm_vm *vp, struct GC_ms_entry *mark_stack_ptr,
size_t slot = nlocals - 1;
for (slot = nlocals - 1; sp < fp; sp++, slot--)
{
- if (SCM_NIMP (sp->as_scm) &&
- sp->as_ptr >= lower && sp->as_ptr <= upper)
+ enum slot_desc desc = SLOT_DESC_LIVE_SCM;
+
+ if (slot_map)
+ desc = (slot_map[slot / 4U] >> ((slot % 4U) * 2)) & 3U;
+
+ switch (desc)
{
- if (dead_slots)
- {
- if (dead_slots[slot / 8U] & (1U << (slot % 8U)))
- {
- /* This value may become dead as a result of GC,
- so we can't just leave it on the stack. */
- sp->as_scm = SCM_UNSPECIFIED;
- continue;
- }
- }
-
- mark_stack_ptr = GC_mark_and_push (sp->as_ptr,
- mark_stack_ptr,
- mark_stack_limit,
- NULL);
+ case SLOT_DESC_LIVE_RAW:
+ break;
+ case SLOT_DESC_UNUSED:
+ case SLOT_DESC_LIVE_SCM:
+ if (SCM_NIMP (sp->as_scm) &&
+ sp->as_ptr >= lower && sp->as_ptr <= upper)
+ mark_stack_ptr = GC_mark_and_push (sp->as_ptr,
+ mark_stack_ptr,
+ mark_stack_limit,
+ NULL);
+ break;
+ case SLOT_DESC_DEAD:
+ /* This value may become dead as a result of GC,
+ so we can't just leave it on the stack. */
+ sp->as_scm = SCM_UNSPECIFIED;
+ break;
}
}
sp = SCM_FRAME_PREVIOUS_SP (fp);
@@ -978,7 +991,7 @@ scm_i_vm_mark_stack (struct scm_vm *vp, struct GC_ms_entry *mark_stack_ptr,
Note that there may be other reasons to not have a dead slots
map, e.g. if all of the frame's slots below the callee frame
are live. */
- dead_slots = find_dead_slot_map (SCM_FRAME_RETURN_ADDRESS (fp), &cache);
+ slot_map = find_slot_map (SCM_FRAME_RETURN_ADDRESS (fp), &cache);
}
return_unused_stack_to_os (vp);