VM: the compiler doesn't emit any live overinitialized locations anymore
Any overinitialized location immediately becomes garbage and is not reused again. This is very nice because then the gc maps can be simpler again.db4
parent
ded3760d46
commit
2cd2aa498a
|
@ -188,7 +188,7 @@ IN: compiler.cfg.stacks.map.tests
|
|||
] unit-test
|
||||
|
||||
{
|
||||
{ { 0 { 0 -1 } } { 0 { } } }
|
||||
{ { 0 { 0 } } { 0 { } } }
|
||||
} [
|
||||
V{
|
||||
T{ ##replace { src 10 } { loc D 0 } }
|
||||
|
@ -199,7 +199,7 @@ IN: compiler.cfg.stacks.map.tests
|
|||
] unit-test
|
||||
|
||||
{
|
||||
{ { 0 { -1 } } { 0 { } } }
|
||||
{ { 0 { } } { 0 { } } }
|
||||
} [
|
||||
V{
|
||||
T{ ##inc f D 1 }
|
||||
|
@ -281,9 +281,9 @@ IN: compiler.cfg.stacks.map.tests
|
|||
}
|
||||
{
|
||||
3 V{
|
||||
T{ ##peek { dst 0 } { loc D 0 } }
|
||||
T{ ##peek { dst 0 } { loc D 1 } }
|
||||
T{ ##inc f D 2 }
|
||||
T{ ##peek { dst 0 } { loc D 2 } }
|
||||
T{ ##peek { dst 0 } { loc D 3 } }
|
||||
T{ ##replace { src 0 } { loc D 2 } }
|
||||
T{ ##replace { src 0 } { loc D 3 } }
|
||||
T{ ##replace { src 0 } { loc D 1 } }
|
||||
|
@ -291,19 +291,19 @@ IN: compiler.cfg.stacks.map.tests
|
|||
}
|
||||
{
|
||||
8 V{
|
||||
T{ ##peek { dst 0 } { loc D 2 } }
|
||||
T{ ##peek { dst 0 } { loc D 1 } }
|
||||
T{ ##inc f D 3 }
|
||||
T{ ##peek { dst 0 } { loc D 5 } }
|
||||
T{ ##replace { src 0 } { loc D 0 } }
|
||||
T{ ##replace { src 0 } { loc D 3 } }
|
||||
T{ ##peek { dst 0 } { loc D 4 } }
|
||||
T{ ##replace { src 0 } { loc D 1 } }
|
||||
T{ ##replace { src 0 } { loc D 2 } }
|
||||
T{ ##replace { src 0 } { loc D 3 } }
|
||||
}
|
||||
}
|
||||
{
|
||||
10 V{
|
||||
T{ ##inc f D -3 }
|
||||
T{ ##peek { dst 0 } { loc D -3 } }
|
||||
T{ ##peek { dst 0 } { loc D 0 } }
|
||||
T{ ##alien-invoke { gc-map T{ gc-map { scrub-d { } } } } }
|
||||
}
|
||||
}
|
||||
|
@ -320,21 +320,21 @@ IN: compiler.cfg.stacks.map.tests
|
|||
{ 5 { { 2 { 1 } } { 0 { } } } }
|
||||
{ 6 { { 2 { 1 0 } } { 0 { } } } }
|
||||
{ 7 { { 2 { 1 0 } } { 0 { } } } }
|
||||
{ 8 { { 4 { 3 2 } } { 0 { } } } }
|
||||
{ 9 { { 4 { 3 2 } } { 0 { } } } }
|
||||
{ 8 { { 2 { 1 0 } } { 0 { } } } }
|
||||
{ 9 { { 2 { 1 0 } } { 0 { } } } }
|
||||
{ 10 { { 4 { 3 2 } } { 0 { } } } }
|
||||
{ 11 { { 4 { 3 2 } } { 0 { } } } }
|
||||
{ 12 { { 4 { 3 2 } } { 0 { } } } }
|
||||
{ 13 { { 4 { 3 2 1 } } { 0 { } } } }
|
||||
{ 14 { { 7 { 6 5 4 } } { 0 { } } } }
|
||||
{ 15 { { 7 { 6 5 4 } } { 0 { } } } }
|
||||
{ 16 { { 7 { 6 5 4 0 } } { 0 { } } } }
|
||||
{ 17 { { 7 { 6 5 4 0 3 } } { 0 { } } } }
|
||||
{ 18 { { 7 { 6 5 4 0 3 } } { 0 { } } } }
|
||||
{ 19 { { 7 { 6 5 4 0 3 1 } } { 0 { } } } }
|
||||
{ 20 { { 7 { 6 5 4 0 3 1 2 } } { 0 { } } } }
|
||||
{ 21 { { 4 { 3 2 1 -3 0 -2 -1 } } { 0 { } } } }
|
||||
{ 22 { { 4 { 3 2 1 -3 0 -2 -1 } } { 0 { } } } }
|
||||
{ 14 { { 4 { 3 2 1 } } { 0 { } } } }
|
||||
{ 15 { { 4 { 3 2 1 } } { 0 { } } } }
|
||||
{ 16 { { 7 { 6 5 4 } } { 0 { } } } }
|
||||
{ 17 { { 7 { 6 5 4 0 } } { 0 { } } } }
|
||||
{ 18 { { 7 { 6 5 4 0 1 } } { 0 { } } } }
|
||||
{ 19 { { 7 { 6 5 4 0 1 2 } } { 0 { } } } }
|
||||
{ 20 { { 7 { 6 5 4 0 1 2 3 } } { 0 { } } } }
|
||||
{ 21 { { 4 { 3 2 1 0 } } { 0 { } } } }
|
||||
{ 22 { { 4 { 3 2 1 0 } } { 0 { } } } }
|
||||
}
|
||||
} [
|
||||
bug1021-cfg trace-stack-state
|
||||
|
|
|
@ -33,18 +33,13 @@ GENERIC: visit-insn ( state insn -- state' )
|
|||
|
||||
M: ##inc visit-insn ( state insn -- state' )
|
||||
[ first2 ] dip insn>location
|
||||
[ rot adjust-stack swap ] [ swap adjust-stack ] if 2array ;
|
||||
[ rot adjust-stack swap ] [ swap adjust-stack ] if 2array
|
||||
! Negative out-of stack locations immediately becomes garbage.
|
||||
[ first2 [ 0 >= ] filter 2array ] map ;
|
||||
|
||||
M: ##replace-imm visit-insn mark-location ;
|
||||
M: ##replace visit-insn mark-location ;
|
||||
|
||||
M: ##call visit-insn ( state insn -- state' )
|
||||
! A call instruction may increase the stack height. Then issue a
|
||||
! minor-gc with some of the stack locations scrubbed which would
|
||||
! overwrite the overinitialized locations we're tracking. That is
|
||||
! why they need to be cleared here.
|
||||
drop [ first2 [ 0 >= ] filter 2array ] map ;
|
||||
|
||||
ERROR: vacant-peek insn ;
|
||||
|
||||
: underflowable-peek? ( state peek -- ? )
|
||||
|
|
|
@ -268,27 +268,13 @@ template <typename Fixup> void slot_visitor<Fixup>::visit_all_roots() {
|
|||
So for each call frame:
|
||||
|
||||
- scrub some uninitialized locations
|
||||
- trace some overinitialized locations
|
||||
- trace roots in spill slots
|
||||
*/
|
||||
template <typename Fixup> struct call_frame_slot_visitor {
|
||||
factor_vm* parent;
|
||||
slot_visitor<Fixup>* visitor;
|
||||
/* NULL in case we're a visitor for a callstack object. */
|
||||
context* ctx;
|
||||
|
||||
void check_stack(cell stack, uint8_t* bitmap, cell base, uint32_t count) {
|
||||
for (uint32_t loc = 0; loc < count; loc++) {
|
||||
if (bitmap_p(bitmap, base + loc)) {
|
||||
#ifdef DEBUG_GC_MAPS
|
||||
std::cout << "checking stack location " << loc << std::endl;
|
||||
#endif
|
||||
cell* value_ptr = ((cell*)stack + loc + 1);
|
||||
visitor->visit_handle(value_ptr);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void scrub_stack(cell stack, uint8_t* bitmap, cell base, uint32_t count) {
|
||||
for (cell loc = 0; loc < count; loc++) {
|
||||
if (bitmap_p(bitmap, base + loc)) {
|
||||
|
@ -300,10 +286,8 @@ template <typename Fixup> struct call_frame_slot_visitor {
|
|||
}
|
||||
}
|
||||
|
||||
call_frame_slot_visitor(factor_vm* parent,
|
||||
slot_visitor<Fixup>* visitor,
|
||||
context* ctx)
|
||||
: parent(parent), visitor(visitor), ctx(ctx) {}
|
||||
call_frame_slot_visitor(slot_visitor<Fixup>* visitor, context* ctx)
|
||||
: visitor(visitor), ctx(ctx) {}
|
||||
|
||||
/*
|
||||
frame top -> [return address]
|
||||
|
@ -342,16 +326,6 @@ template <typename Fixup> struct call_frame_slot_visitor {
|
|||
bitmap,
|
||||
info->callsite_scrub_r(callsite),
|
||||
info->scrub_r_count);
|
||||
|
||||
/* Trace overinitialized stack locations. */
|
||||
check_stack(ctx->datastack,
|
||||
bitmap,
|
||||
info->callsite_check_d(callsite),
|
||||
info->check_d_count);
|
||||
check_stack(ctx->retainstack,
|
||||
bitmap,
|
||||
info->callsite_check_r(callsite),
|
||||
info->check_r_count);
|
||||
}
|
||||
|
||||
/* Subtract old value of base pointer from every derived pointer. */
|
||||
|
@ -391,13 +365,13 @@ template <typename Fixup> struct call_frame_slot_visitor {
|
|||
|
||||
template <typename Fixup>
|
||||
void slot_visitor<Fixup>::visit_callstack_object(callstack* stack) {
|
||||
call_frame_slot_visitor<Fixup> call_frame_visitor(parent, this, NULL);
|
||||
call_frame_slot_visitor<Fixup> call_frame_visitor(this, NULL);
|
||||
parent->iterate_callstack_object(stack, call_frame_visitor, fixup);
|
||||
}
|
||||
|
||||
template <typename Fixup>
|
||||
void slot_visitor<Fixup>::visit_callstack(context* ctx) {
|
||||
call_frame_slot_visitor<Fixup> call_frame_visitor(parent, this, ctx);
|
||||
call_frame_slot_visitor<Fixup> call_frame_visitor(this, ctx);
|
||||
parent->iterate_callstack(ctx, call_frame_visitor, fixup);
|
||||
}
|
||||
|
||||
|
@ -450,11 +424,10 @@ void slot_visitor<Fixup>::visit_embedded_literals(code_block* compiled) {
|
|||
}
|
||||
|
||||
template <typename Fixup> struct call_frame_code_block_visitor {
|
||||
factor_vm* parent;
|
||||
Fixup fixup;
|
||||
|
||||
call_frame_code_block_visitor(factor_vm* parent, Fixup fixup)
|
||||
: parent(parent), fixup(fixup) {}
|
||||
call_frame_code_block_visitor(Fixup fixup)
|
||||
: fixup(fixup) {}
|
||||
|
||||
void operator()(cell frame_top, cell size, code_block* owner, cell addr) {
|
||||
code_block* compiled =
|
||||
|
@ -482,7 +455,7 @@ void slot_visitor<Fixup>::visit_object_code_block(object* obj) {
|
|||
}
|
||||
case CALLSTACK_TYPE: {
|
||||
callstack* stack = (callstack*)obj;
|
||||
call_frame_code_block_visitor<Fixup> call_frame_visitor(parent, fixup);
|
||||
call_frame_code_block_visitor<Fixup> call_frame_visitor(fixup);
|
||||
parent->iterate_callstack_object(stack, call_frame_visitor, fixup);
|
||||
break;
|
||||
}
|
||||
|
@ -491,11 +464,12 @@ void slot_visitor<Fixup>::visit_object_code_block(object* obj) {
|
|||
|
||||
template <typename Fixup>
|
||||
void slot_visitor<Fixup>::visit_context_code_blocks() {
|
||||
call_frame_code_block_visitor<Fixup> call_frame_visitor(parent, fixup);
|
||||
call_frame_code_block_visitor<Fixup> call_frame_visitor(fixup);
|
||||
std::set<context*>::const_iterator begin = parent->active_contexts.begin();
|
||||
std::set<context*>::const_iterator end = parent->active_contexts.end();
|
||||
while (begin != end) {
|
||||
parent->iterate_callstack(*begin++, call_frame_visitor, fixup);
|
||||
parent->iterate_callstack(*begin, call_frame_visitor, fixup);
|
||||
begin++;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue