compiler.cfg.stacks.*: many new and fixed tests

db4
Björn Lindqvist 2015-01-01 16:14:14 +01:00 committed by Doug Coleman
parent d4493858da
commit d19869f906
3 changed files with 156 additions and 166 deletions

View File

@ -6,9 +6,10 @@ IN: compiler.cfg.stacks.clearing.tests
{ { 0 { } } { 0 { } } } state>replaces { { 0 { } } { 0 { } } } state>replaces
] unit-test ] unit-test
{ t f } [ { t f f } [
{ { 0 { } } { 0 { } } } T{ ##peek { loc D 0 } } dangerous-insn? { { 0 { } } { 0 { } } } T{ ##peek { loc D 0 } } dangerous-insn?
{ { 0 { } } { 0 { } } } T{ ##peek { loc D -1 } } dangerous-insn? { { 1 { 0 } } { 0 { } } } T{ ##peek { loc D 0 } } dangerous-insn?
{ { 0 { -1 } } { 0 { } } } T{ ##peek { loc D -1 } } dangerous-insn?
] unit-test ] unit-test
{ {

View File

@ -5,27 +5,63 @@ compiler.cfg.utilities compiler.cfg.stacks.map kernel math namespaces
sequences sorting tools.test vectors ; sequences sorting tools.test vectors ;
IN: compiler.cfg.stacks.map.tests IN: compiler.cfg.stacks.map.tests
! Utils ! classify-read: vacant locations
: output-stack-map ( cfg -- map ) { 2 2 2 } [
H{ } clone stack-record set { 3 { } } 2 classify-read
map-analysis run-dataflow-analysis { 0 { } } -1 classify-read
nip [ [ number>> ] dip ] assoc-map >alist natural-sort last second ; { 3 { } } -1 classify-read
] unit-test
! Initially both the d and r stacks are empty. ! classify-read: over locations
{ 1 1 1 1 1 } [
{ 1 { 0 } } 1 classify-read
{ 0 { } } 0 classify-read
{ 3 { } } 4 classify-read
{ 0 { } } 4 classify-read
{ 1 { 0 } } 4 classify-read
] unit-test
! classify-read: initialized locations
{ 0 0 0 } [
{ 1 { 0 } } 0 classify-read
{ 2 { 0 1 2 } } 0 classify-read
{ 0 { 0 1 2 } } 0 classify-read
] unit-test
! fill-vacancies
{ {
{ { 0 { } } { 0 { } } } { { 0 { } } { 2 { 0 1 } } }
} [ V{ } insns>cfg output-stack-map ] unit-test { { 0 { } } { 2 { 0 1 } } }
{ { 0 { -1 -2 } } { 2 { 0 1 } } }
} [
{ { 0 { } } { 2 { } } } fill-vacancies
{ { 0 { } } { 2 { 0 } } } fill-vacancies
{ { 0 { -1 -2 } } { 2 { 0 } } } fill-vacancies
] unit-test
! Raise d stack. ! visit-insn
! After a ##peek that can cause a stack underflow, it is certain that
! all stack locations are initialized.
{ {
{ { 1 { } } { 0 { } } } { { 2 { 0 1 2 } } { 0 { } } }
} [ V{ T{ ##inc-d f 1 } } insns>cfg output-stack-map ] unit-test } [
{ { 2 { } } { 0 { } } } T{ ##peek f f D 2 } visit-insn
] unit-test
! Raise r stack. ! If the ##peek can't cause a stack underflow, then we don't have the
{ ! same guarantees.
{ { 0 { } } { 1 { } } } [
} [ V{ T{ ##inc-r f 1 } } insns>cfg output-stack-map ] unit-test { { 2 { } } { 0 { } } } T{ ##peek f f D 0 } visit-insn
] [ vacant-peek? ] must-fail-with
! verboten peek
[
{ { 1 { } } { 0 { } } } T{ ##peek { loc D 0 } } visit-insn
] [ vacant-peek? ] must-fail-with
! trace-stack-state
{ {
H{ H{
{ {
@ -40,7 +76,6 @@ IN: compiler.cfg.stacks.map.tests
T{ ##inc-d { n 0 } } T{ ##inc-d { n 0 } }
{ { 2 { 0 1 2 } } { 0 { } } } { { 2 { 0 1 2 } } { 0 { } } }
} }
} }
} [ } [
{ {
@ -50,32 +85,17 @@ IN: compiler.cfg.stacks.map.tests
} insns>cfg trace-stack-state } insns>cfg trace-stack-state
] unit-test ] unit-test
! Here the peek refers to a parameter of the word. ! Runs the analysis and check what the resulting stack map becomes.
[ ] [
V{
T{ ##peek { dst 0 } { loc D 25 } }
} insns>cfg
compute-map-sets
] unit-test
! Replace -1 then peek is ok. : output-stack-map ( cfg -- map )
[ ] [ H{ } clone stack-record set
V{ map-analysis run-dataflow-analysis
T{ ##replace { src 10 } { loc D -1 } } nip [ [ number>> ] dip ] assoc-map >alist natural-sort last second ;
T{ ##peek { dst 0 } { loc D -1 } }
} insns>cfg
compute-map-sets
] unit-test
! Should be ok because the value was at 0 when the gc ran. ! Initially both the d and r stacks are empty.
{ { -1 { -1 } } } [ {
V{ { { 0 { } } { 0 { } } }
T{ ##replace { src 10 } { loc D 0 } } } [ V{ } insns>cfg output-stack-map ] unit-test
T{ ##alien-invoke { gc-map T{ gc-map { scrub-d { } } } } }
T{ ##inc-d f -1 }
T{ ##peek { dst 0 } { loc D -1 } }
} insns>cfg output-stack-map first
] unit-test
{ {
{ { 0 { } } { 0 { } } } { { 0 { } } { 0 { } } }
@ -84,6 +104,55 @@ IN: compiler.cfg.stacks.map.tests
insns>cfg output-stack-map insns>cfg output-stack-map
] unit-test ] unit-test
{
{ { 1 { } } { 0 { } } }
} [ V{ T{ ##inc-d f 1 } } insns>cfg output-stack-map ] unit-test
{
{ { 0 { } } { 1 { } } }
} [ V{ T{ ##inc-r f 1 } } insns>cfg output-stack-map ] unit-test
! Here the peek refers to a parameter of the word.
{
{ { 0 { 25 } } { 0 { } } }
} [
V{
T{ ##peek { loc D 25 } }
} insns>cfg output-stack-map
] unit-test
! The peek "causes" the vacant locations to become populated.
{
{ { 3 { 0 1 2 3 } } { 0 { } } }
} [
V{
T{ ##inc-d f 3 }
T{ ##peek { loc D 3 } }
} insns>cfg output-stack-map
] unit-test
! Replace -1 then peek is ok.
{
{ { 0 { -1 } } { 0 { } } }
} [
V{
T{ ##replace { src 10 } { loc D -1 } }
T{ ##peek { loc D -1 } }
} insns>cfg output-stack-map
] unit-test
! Should be ok because the value was at 0 when the gc ran.
{
{ { -1 { -1 } } { 0 { } } }
} [
V{
T{ ##replace { src 10 } { loc D 0 } }
T{ ##alien-invoke { gc-map T{ gc-map { scrub-d { } } } } }
T{ ##inc-d f -1 }
T{ ##peek { loc D -1 } }
} insns>cfg output-stack-map
] unit-test
{ {
{ { 0 { 0 1 2 } } { 0 { } } } { { 0 { 0 1 2 } } { 0 { } } }
} [ } [
@ -105,37 +174,60 @@ IN: compiler.cfg.stacks.map.tests
] unit-test ] unit-test
{ {
{ 0 { 0 -1 } } { { 0 { 0 -1 } } { 0 { } } }
} [ } [
V{ V{
T{ ##replace { src 10 } { loc D 0 } } T{ ##replace { src 10 } { loc D 0 } }
T{ ##inc-d f 1 } T{ ##inc-d f 1 }
T{ ##replace { src 10 } { loc D 0 } } T{ ##replace { src 10 } { loc D 0 } }
T{ ##inc-d f -1 } T{ ##inc-d f -1 }
} insns>cfg output-stack-map first } insns>cfg output-stack-map
] unit-test ] unit-test
{ {
{ 0 { -1 } } { { 0 { -1 } } { 0 { } } }
} [ } [
V{ V{
T{ ##inc-d f 1 } T{ ##inc-d f 1 }
T{ ##replace { src 10 } { loc D 0 } } T{ ##replace { src 10 } { loc D 0 } }
T{ ##inc-d f -1 } T{ ##inc-d f -1 }
} insns>cfg output-stack-map first } insns>cfg output-stack-map
] unit-test ] unit-test
! ##call clears the overinitialized slots. ! ##call clears the overinitialized slots.
{ {
{ -1 { } } { { -1 { } } { 0 { } } }
} [ } [
V{ V{
T{ ##replace { src 10 } { loc D 0 } } T{ ##replace { src 10 } { loc D 0 } }
T{ ##inc-d f -1 } T{ ##inc-d f -1 }
T{ ##call } T{ ##call }
} insns>cfg output-stack-map first } insns>cfg output-stack-map
] unit-test ] unit-test
! Should not be ok because the value wasn't initialized when gc ran.
[
V{
T{ ##inc-d f 1 }
T{ ##alien-invoke { gc-map T{ gc-map { scrub-d { } } } } }
T{ ##peek { loc D 0 } }
} insns>cfg output-stack-map
] [ vacant-peek? ] must-fail-with
[
V{
T{ ##inc-d f 1 }
T{ ##peek { loc D 0 } }
} insns>cfg output-stack-map
] [ vacant-peek? ] must-fail-with
[
V{
T{ ##inc-r f 1 }
T{ ##peek { loc R 0 } }
} insns>cfg output-stack-map
] [ vacant-peek? ] must-fail-with
: cfg1 ( -- cfg ) : cfg1 ( -- cfg )
V{ V{
T{ ##inc-d f 1 } T{ ##inc-d f 1 }
@ -147,7 +239,9 @@ IN: compiler.cfg.stacks.map.tests
} 1 insns>block } 1 insns>block
1vector >>successors block>cfg ; 1vector >>successors block>cfg ;
{ { 0 { -1 } } } [ cfg1 output-stack-map first ] unit-test {
{ { 0 { -1 } } { 0 { } } }
} [ cfg1 output-stack-map ] unit-test
! Same cfg structure as the bug1021:run-test word but with ! Same cfg structure as the bug1021:run-test word but with
! non-datastack instructions mostly omitted. ! non-datastack instructions mostly omitted.
@ -200,34 +294,3 @@ IN: compiler.cfg.stacks.map.tests
{ { 4 { 3 2 1 -3 0 -2 -1 } } } [ { { 4 { 3 2 1 -3 0 -2 -1 } } } [
bug1021-cfg output-stack-map first bug1021-cfg output-stack-map first
] unit-test ] unit-test
! After a ##peek that can cause a stack underflow, it is certain that
! all stack locations are initialized.
{
{ { 2 { 0 1 2 } } { 0 { } } }
} [
{ { 2 { } } { 0 { } } } T{ ##peek f f D 2 } visit-insn
] unit-test
! If the ##peek can't cause a stack underflow, then we don't have the
! same guarantees.
{
{ { 2 { 0 } } { 0 { } } }
} [
{ { 2 { } } { 0 { } } } T{ ##peek f f D 0 } visit-insn
] unit-test
{ t f t } [
{ { 0 { } } { 0 { } } } T{ ##peek { loc D 0 } } dangerous-peek?
{ { 0 { } } { 0 { } } } T{ ##peek { loc D -1 } } dangerous-peek?
{ { 2 { 0 1 2 } } { 0 { } } } T{ ##peek { loc D 2 } } dangerous-peek?
] unit-test
{
{ { 0 { } } { 2 { 0 1 } } }
{ { 0 { } } { 2 { 0 1 } } }
} [
{ { 0 { } } { 2 { } } } fill-vacancies
{ { 0 { } } { 2 { 0 } } } fill-vacancies
] unit-test

View File

@ -19,31 +19,21 @@ IN: compiler.cfg.stacks.vacant.tests
T{ ##alien-invoke { gc-map T{ gc-map { scrub-d { } } } } } T{ ##alien-invoke { gc-map T{ gc-map { scrub-d { } } } } }
T{ ##peek { dst 0 } { loc D -1 } } T{ ##peek { dst 0 } { loc D -1 } }
} }
[ insns>cfg fill-in-gc-maps ] [ insns>cfg fill-gc-maps ]
[ second gc-map>> check-d>> ] bi [ second gc-map>> check-d>> ] bi
] unit-test ] unit-test
! ! Replace -1, then gc. Peek is ok here because the -1 should be ! Replace -1, then gc. Peek is ok here because the -1 should be
! ! checked. ! checked.
! { { 0 } } [ { { 0 } } [
! V{ V{
! T{ ##replace { src 10 } { loc D -1 } } T{ ##replace { src 10 } { loc D -1 } }
! T{ ##alien-invoke { gc-map T{ gc-map { scrub-d { } } } } } T{ ##alien-invoke { gc-map T{ gc-map { scrub-d { } } } } }
! T{ ##peek { dst 0 } { loc D -1 } } T{ ##peek { dst 0 } { loc D -1 } }
! } }
! [ insns>cfg compute-vacant-sets ] [ insns>cfg fill-gc-maps ]
! [ second gc-map>> check-d>> ] bi [ second gc-map>> check-d>> ] bi
! ] unit-test ] unit-test
! ! Should not be ok because the value wasn't initialized when gc ran.
! [
! V{
! T{ ##inc-d f 1 }
! T{ ##alien-invoke { gc-map T{ gc-map { scrub-d { } } } } }
! T{ ##peek { dst 0 } { loc D 0 } }
! } insns>cfg
! compute-vacant-sets
! ] [ vacant-peek? ] must-fail-with
! visit-insn should set the gc info. ! visit-insn should set the gc info.
{ { 0 0 } { } } [ { { 0 0 } { } } [
@ -51,67 +41,3 @@ IN: compiler.cfg.stacks.vacant.tests
T{ ##alien-invoke { gc-map T{ gc-map } } } T{ ##alien-invoke { gc-map T{ gc-map } } }
[ gc-map>> set-gc-map ] keep gc-map>> [ scrub-d>> ] [ scrub-r>> ] bi [ gc-map>> set-gc-map ] keep gc-map>> [ scrub-d>> ] [ scrub-r>> ] bi
] unit-test ] unit-test
! ! read-ok?
! { t } [
! 0 { 0 { 0 1 2 } } read-ok?
! ] unit-test
! { f } [
! 2 { 3 { } } read-ok?
! ] unit-test
! { f } [
! -1 { 3 { } } read-ok?
! ] unit-test
! ! { f } [
! ! 4 { 3 { } } read-ok?
! ! ] unit-test
! { t } [
! 4 { 0 { } } read-ok?
! ] unit-test
! { t } [
! 4 { 1 { 0 } } read-ok?
! ] unit-test
! ! Uninitialized peeks
! [
! V{
! T{ ##inc-d f 1 }
! T{ ##peek { dst 0 } { loc D 0 } }
! } insns>cfg
! compute-vacant-sets
! ] [ vacant-peek? ] must-fail-with
! [
! V{
! T{ ##inc-r f 1 }
! T{ ##peek { dst 0 } { loc R 0 } }
! } insns>cfg
! compute-vacant-sets
! ] [ vacant-peek? ] must-fail-with
! ! Here again the peek refers to a parameter word, but there are
! ! uninitialized stack locations. That probably isn't ok.
! [
! V{
! T{ ##inc-d f 3 }
! T{ ##peek { dst 0 } { loc D 3 } }
! } insns>cfg
! compute-vacant-sets
! ] [ vacant-peek? ] must-fail-with
! ! Should not be ok because the value wasn't initialized when gc ran.
! ! [
! ! V{
! ! T{ ##inc-d f 1 }
! ! T{ ##alien-invoke { gc-map T{ gc-map { scrub-d { } } } } }
! ! T{ ##peek { dst 0 } { loc D 0 } }
! ! } insns>cfg
! ! compute-map-sets
! ! ] [ vacant-peek? ] must-fail-with