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 ] unit-test
{ {
{ { 0 { 0 -1 } } { 0 { } } } { { 0 { 0 } } { 0 { } } }
} [ } [
V{ V{
T{ ##replace { src 10 } { loc D 0 } } T{ ##replace { src 10 } { loc D 0 } }
@ -199,7 +199,7 @@ IN: compiler.cfg.stacks.map.tests
] unit-test ] unit-test
{ {
{ { 0 { -1 } } { 0 { } } } { { 0 { } } { 0 { } } }
} [ } [
V{ V{
T{ ##inc f D 1 } T{ ##inc f D 1 }
@ -281,9 +281,9 @@ IN: compiler.cfg.stacks.map.tests
} }
{ {
3 V{ 3 V{
T{ ##peek { dst 0 } { loc D 0 } }
T{ ##peek { dst 0 } { loc D 1 } }
T{ ##inc f D 2 } 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 2 } }
T{ ##replace { src 0 } { loc D 3 } } T{ ##replace { src 0 } { loc D 3 } }
T{ ##replace { src 0 } { loc D 1 } } T{ ##replace { src 0 } { loc D 1 } }
@ -291,19 +291,19 @@ IN: compiler.cfg.stacks.map.tests
} }
{ {
8 V{ 8 V{
T{ ##peek { dst 0 } { loc D 2 } }
T{ ##peek { dst 0 } { loc D 1 } }
T{ ##inc f D 3 } 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 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 1 } }
T{ ##replace { src 0 } { loc D 2 } } T{ ##replace { src 0 } { loc D 2 } }
T{ ##replace { src 0 } { loc D 3 } }
} }
} }
{ {
10 V{ 10 V{
T{ ##inc f D -3 } 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 { } } } } } T{ ##alien-invoke { gc-map T{ gc-map { scrub-d { } } } } }
} }
} }
@ -320,21 +320,21 @@ IN: compiler.cfg.stacks.map.tests
{ 5 { { 2 { 1 } } { 0 { } } } } { 5 { { 2 { 1 } } { 0 { } } } }
{ 6 { { 2 { 1 0 } } { 0 { } } } } { 6 { { 2 { 1 0 } } { 0 { } } } }
{ 7 { { 2 { 1 0 } } { 0 { } } } } { 7 { { 2 { 1 0 } } { 0 { } } } }
{ 8 { { 4 { 3 2 } } { 0 { } } } } { 8 { { 2 { 1 0 } } { 0 { } } } }
{ 9 { { 4 { 3 2 } } { 0 { } } } } { 9 { { 2 { 1 0 } } { 0 { } } } }
{ 10 { { 4 { 3 2 } } { 0 { } } } } { 10 { { 4 { 3 2 } } { 0 { } } } }
{ 11 { { 4 { 3 2 } } { 0 { } } } } { 11 { { 4 { 3 2 } } { 0 { } } } }
{ 12 { { 4 { 3 2 } } { 0 { } } } } { 12 { { 4 { 3 2 } } { 0 { } } } }
{ 13 { { 4 { 3 2 1 } } { 0 { } } } } { 13 { { 4 { 3 2 1 } } { 0 { } } } }
{ 14 { { 7 { 6 5 4 } } { 0 { } } } } { 14 { { 4 { 3 2 1 } } { 0 { } } } }
{ 15 { { 7 { 6 5 4 } } { 0 { } } } } { 15 { { 4 { 3 2 1 } } { 0 { } } } }
{ 16 { { 7 { 6 5 4 0 } } { 0 { } } } } { 16 { { 7 { 6 5 4 } } { 0 { } } } }
{ 17 { { 7 { 6 5 4 0 3 } } { 0 { } } } } { 17 { { 7 { 6 5 4 0 } } { 0 { } } } }
{ 18 { { 7 { 6 5 4 0 3 } } { 0 { } } } } { 18 { { 7 { 6 5 4 0 1 } } { 0 { } } } }
{ 19 { { 7 { 6 5 4 0 3 1 } } { 0 { } } } } { 19 { { 7 { 6 5 4 0 1 2 } } { 0 { } } } }
{ 20 { { 7 { 6 5 4 0 3 1 2 } } { 0 { } } } } { 20 { { 7 { 6 5 4 0 1 2 3 } } { 0 { } } } }
{ 21 { { 4 { 3 2 1 -3 0 -2 -1 } } { 0 { } } } } { 21 { { 4 { 3 2 1 0 } } { 0 { } } } }
{ 22 { { 4 { 3 2 1 -3 0 -2 -1 } } { 0 { } } } } { 22 { { 4 { 3 2 1 0 } } { 0 { } } } }
} }
} [ } [
bug1021-cfg trace-stack-state bug1021-cfg trace-stack-state

View File

@ -33,18 +33,13 @@ GENERIC: visit-insn ( state insn -- state' )
M: ##inc visit-insn ( state insn -- state' ) M: ##inc visit-insn ( state insn -- state' )
[ first2 ] dip insn>location [ 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-imm visit-insn mark-location ;
M: ##replace 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 ; ERROR: vacant-peek insn ;
: underflowable-peek? ( state peek -- ? ) : 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: So for each call frame:
- scrub some uninitialized locations - scrub some uninitialized locations
- trace some overinitialized locations
- trace roots in spill slots - trace roots in spill slots
*/ */
template <typename Fixup> struct call_frame_slot_visitor { template <typename Fixup> struct call_frame_slot_visitor {
factor_vm* parent;
slot_visitor<Fixup>* visitor; slot_visitor<Fixup>* visitor;
/* NULL in case we're a visitor for a callstack object. */ /* NULL in case we're a visitor for a callstack object. */
context* ctx; 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) { void scrub_stack(cell stack, uint8_t* bitmap, cell base, uint32_t count) {
for (cell loc = 0; loc < count; loc++) { for (cell loc = 0; loc < count; loc++) {
if (bitmap_p(bitmap, base + 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, call_frame_slot_visitor(slot_visitor<Fixup>* visitor, context* ctx)
slot_visitor<Fixup>* visitor, : visitor(visitor), ctx(ctx) {}
context* ctx)
: parent(parent), visitor(visitor), ctx(ctx) {}
/* /*
frame top -> [return address] frame top -> [return address]
@ -342,16 +326,6 @@ template <typename Fixup> struct call_frame_slot_visitor {
bitmap, bitmap,
info->callsite_scrub_r(callsite), info->callsite_scrub_r(callsite),
info->scrub_r_count); 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. */ /* 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> template <typename Fixup>
void slot_visitor<Fixup>::visit_callstack_object(callstack* stack) { 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); parent->iterate_callstack_object(stack, call_frame_visitor, fixup);
} }
template <typename Fixup> template <typename Fixup>
void slot_visitor<Fixup>::visit_callstack(context* ctx) { 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); 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 { template <typename Fixup> struct call_frame_code_block_visitor {
factor_vm* parent;
Fixup fixup; Fixup fixup;
call_frame_code_block_visitor(factor_vm* parent, Fixup fixup) call_frame_code_block_visitor(Fixup fixup)
: parent(parent), fixup(fixup) {} : fixup(fixup) {}
void operator()(cell frame_top, cell size, code_block* owner, cell addr) { void operator()(cell frame_top, cell size, code_block* owner, cell addr) {
code_block* compiled = code_block* compiled =
@ -482,7 +455,7 @@ void slot_visitor<Fixup>::visit_object_code_block(object* obj) {
} }
case CALLSTACK_TYPE: { case CALLSTACK_TYPE: {
callstack* stack = (callstack*)obj; 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); parent->iterate_callstack_object(stack, call_frame_visitor, fixup);
break; break;
} }
@ -491,11 +464,12 @@ void slot_visitor<Fixup>::visit_object_code_block(object* obj) {
template <typename Fixup> template <typename Fixup>
void slot_visitor<Fixup>::visit_context_code_blocks() { 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 begin = parent->active_contexts.begin();
std::set<context*>::const_iterator end = parent->active_contexts.end(); std::set<context*>::const_iterator end = parent->active_contexts.end();
while (begin != end) { while (begin != end) {
parent->iterate_callstack(*begin++, call_frame_visitor, fixup); parent->iterate_callstack(*begin, call_frame_visitor, fixup);
begin++;
} }
} }