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
Björn Lindqvist 2015-03-04 13:17:23 +00:00 committed by John Benediktsson
parent ded3760d46
commit 2cd2aa498a
3 changed files with 32 additions and 63 deletions

View File

@ -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

View File

@ -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 -- ? )

View File

@ -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++;
}
}