Upload
others
View
7
Download
0
Embed Size (px)
Citation preview
Model Checking Program Equivalence Model Checking Program Equivalence in Interface Middleweight Javain Interface Middleweight Java
Andrzej Murawski Steven Ramsay Nikos Tzevelekos Uni. of Warwick Uni. of Oxford Queen Mary U. of London
Higher-Order Model Checking, Shonan, Mar 2016
Supported by a Royal Academy of Engineering Research Fellowship
what this talk is about
We examine contextual equivalence of Java programs● these are 'higher'-order
We work in an fragment of Middleweight Java ● open code modelled by use of interfaces● denotational approach based on game semantics
Full characterisation based on type disciplines:● queue machine encodings (negative cases)
● pushdown register automata (algorithms)
Implementation of decidable fragment in Coneqct
Program equivalence
M ≅ M'
same observable behaviour in every context
for all closing contexts C:
(C[M],) →* (skip,S) � (C[M'],) →* (skip,S')
● subsumes standard verification properties● contextual: quantification over every context● several methods for proving given equivalences
yet no general procedures
Interface Middleweight Java (IMJ)
Object calculus based on MJ [Bierman, Parkinson, Pitts]● Objects, inheritance, casting, interfaces
Types θ ::= void | int |
Interface definitions
Θ ::= | ( f : θ ), Θ | ( m : θ → θ ), Θ
Interface tables
Δ ::= | ( : Θ ), Δ | ( : Θ
), Δ
Interface Middleweight Java (IMJ)
Object calculus based on MJ [Bierman, Parkinson, Pitts]● Objects, inheritance, casting, interfaces
Types θ ::= void | int |
Interface definitions
Θ ::= | ( f : θ ), Θ | ( m : θ → θ ), Θ
Interface tables
Δ ::= | ( : Θ ), Δ | ( : Θ
), Δ
interface ident.
field identifier
method identif.
Interface Middleweight Java (IMJ)
TermsM ::= skip | a | null | x | i | M ⊕ M | if M M M
| let x = M in M | M = M | ()M | while M M
| new(x : ; M) | M.f | M.f := M | M.m( M )
Method implementations M ::= | (m : λx.Μ), M
Interface Middleweight Java (IMJ)
TermsM ::= skip | a | null | x | i | M ⊕ M | if M M M
| let x = M in M | M = M | ()M | while M M
| new(x : ; M) | M.f | M.f := M | M.m( M )
Method implementations M ::= | (m : λx.Μ), M
M = { mi : λxi .Μi | 1 i n }
IMJ: operational semantics
S, Μ → S', M'
S, let x = v in M → S, M[v/x]
S, a = a' → S, 0/1
S, new(x : ; M) → S ) {(a, , (V, M[a/x])}, a
S stores object names + their types and values
Obj : set of obj. names
a,a' Î Obj
V : default field values
Program equivalence – the plan
M ≅ M'
same observable behaviour in every context
for all closing contexts C:
(C[M],) →* (skip,S) � (C[M'],) →* (skip,S')
Program equivalence – the plan
M ≅ M'
same observable behaviour in every context
for all closing contexts C:
(C[M],) →* (skip,S) � (C[M'],) →* (skip,S')
we consider a finitary restriction IMJfin
and first identify the fragment decidable for termination
we use game semantics and types to characterise the fragment of IMJ
fin decidable for equivalence
termination inequivalence→
Two distinct sources of undecidability:
I.recursive methods
new(x : ; main: λy. {… x.main(..) … } )
II.objects with methods can be stored
let a = new(x : ; main: λy. {… } ) in
let b = new(x' : '; ) in b.var a
Termination
Theorem: Termination is undecidable for IMJfin terms that mayfeature I or II.Conversely, given an IMJfin term M that does not feature I or II, we can always decide whether it terminates.
M terminates if: (M,) →* (skip,S)
Games for program equivalence
We focus on:
and employ the fully abstract game semantics for IMJ:
M ≅ M' ⇔ M = M'
IMJfin
– {I,II}
program: M
denotation: M M
L
.
Games for program equivalence
We focus on:
and employ the fully abstract game semantics for IMJ:
● for negative results, given a queue machine Q, devise terms M, M':
● for decidability, given terms M, M', devise automata A, A':
M ≅ M' ⇔ M = M'
QÝ ⇔ M = M'
M = M' A ~⇔ A'
IMJfin
– {I,II}
Model the execution of programs as a 2-player game:
● Opponent (the environment, O )● Proponent (the program, P )
Qualitative games (no winning conditions)
Computations = plays of a specified game
Programs = strategies for P
Categories of games, extended with names & effects● storage: moves with stores
● conditions for name privacy and propagation
Nominal game semantics
Game apparatus
x1:θ
1, …, x
n:θ
n ⊢ M : θ
input types
output typefree variables
program
Game apparatus
x1:θ
1, …, x
n:θ
n ⊢ M : θ
input types
output typefree variables
program
M : θ1, …, θ
n θ
strategy arenas
Initial game moves
arenas
void = { * }
int = { 0, 1, -1, … }
= { a, b, … , n, … }
moves
M : θ1, …, θ
n θ
a, b, n, … N
N
a set of names
strategy
Games for IMJ programs
Program interactions are modelled by sequences of moves-with-store, written mΣ, where:
● move m is either:
– a value/arena move– an object method call/return
● stores are of the form:
Σ = {n (Emp, ), a (Ptr, val a), p (Pt2, x 1, y 0), c (Ptr', ), q (Pt2', ), … }
call c.set(c'), ret q.get(), …
Ptr' : ( get : Ptr' → Ptr', set : Ptr' → Ptr' )Pt2' : ( get : void → (int,int), set : (int,int) → void )
[ Murawski & T. '14 ]
IMJ example: game semantics
M1 = * c Σ0 ( call c.get() Σ0 ret c.get( nul ) Σ0 )*
call c.set( n1 ) Σ1 ret c.set() Σ1
( call c.get() Σ1 ret c.get( n1 ) Σ1 )*
call c.set( n2 ) Σ2 ret c.set( ) Σ2 ...
Σi = { c (Cell, ) } { nj (Empty, ) | 1 j i }
O OP P
Δ = Empty: , Cell: (get: void → Empty,
set: Empty → void),Var
Emp: (val: Empty),
VarInt
: (val: int)
M1 : let u = new( VarEmp ) in
new( M1 ) : Cell
M1 : get : λ_. u.val,
set : λy. u.val := y
Δ = Empty: , Cell: (get: void → Empty,
set: Empty → void), Var
Emp: (val: Empty),
VarInt
: (val: int)
* [Koutavas & Wand' 07]
IMJ example: game semantics
Δ = Empty: , Cell: (get: void → Empty,
set: Empty → void),Var
Emp: (val: Empty),
VarInt
: (val: int)
M1 : let u = new( VarEmp
) in
new( Cell; M1 ) : Cell
M1 : get : λ(). u.val,
set : λy. u.val := y
M1 = * c Σ0 ( call c.get() Σ0 ret c.get( nul ) Σ0 )*
call c.set( n1 ) Σ1 ret c.set() Σ1
( call c.get() Σ1 ret c.get( n1 ) Σ1 )*
call c.set( n2 ) Σ2 ret c.set( ) Σ2 ... = M2
Σi = { c (Cell, ) } { nj (Empty, ) | 1 j i }
O OP P
M2 : let b = new( VarInt ) in
let u1 = new( VarEmp
) in
let u2 = new( VarEmp
) in
new( M2 ) : Cell
M2 : get : λ_. if b.val
then b.val := 0 ; u1.val
else b.val := 1 ; u2.val,
set : λy. u1.val := y ;
u2.val := y
* [Koutavas & Wand' 07]
Games for program equivalence
We focus on:
and employ the fully abstract game semantics for IMJ:
● for negative results, given a queue machine Q, devise terms M, M':
● for decidability, given terms M, M', devise automata A, A':
M ≅ M' ⇔ M = M'
QÝ ⇔ M = M'
M = M' A ~⇔ A'
IMJfin
– {I,II}
One source of Undecidability
step state
P passes objects of type , and contains methods
: (step: void→void)N : (val: int)
(run: →void) ⊢ void
we can encodecomputations of queue machines!
One source of Undecidability
step
sym
previd
step
id
sym
previd
step
state
P passes objects of type , and contains methods
: (step: void→void)N : (val: int)
(run: →void) ⊢ void
we can encodecomputations of queue machines!
One source of Undecidability
step
sym
previd
step
id
sym
previd
step
state
P passes objects of type , and contains methods
: (step: void→void)N : (val: int)
(run: →void) ⊢ void
we can encodecomputations of queue machines!
One source of Undecidability
step
sym
previd
step
id
sym
previd
stepsym
previd
step
idid
state
P passes objects of type , and contains methods
: (step: void→void)N : (val: int)
(run: →void) ⊢ void
we can encodecomputations of queue machines!
One source of Undecidability
step
sym
previd
step
id
sym
previd
stepsym
previd
step
idid
state
P passes objects of type , and contains methods
: (step: void→void)N : (val: int)
(run: →void) ⊢ void
we can encodecomputations of queue machines!
One source of Undecidability
step
sym
previd
step
id
sym
previd
step
idid
state
P passes objects of type , and contains methods
: (step: void→void)N : (val: int)
(run: →void) ⊢ void
we can encodecomputations of queue machines!
One source of Undecidability
step
sym
previd
step
id
sym
previd
step
idid
state
P passes objects of type , and contains methods
: (step: void→void)N : (val: int)
(run: →void) ⊢ void
we can encodecomputations of queue machines!
One source of Undecidability
P passes objects of type , and contains methods
: (step: void→void)N : (val: int)
(run: →void) ⊢ void
we can encodecomputations of queue machines!
step
id
sym
previd
step
state
Undecidability
Three cases for undecidability:
● L = (…, m : → θ)● R = (…, m : θ → )● R = (…, m : ' → θ) where ' = (…, m : → θ)
and contains methods (i.e. is higher-order)
x : L ⊢ M : R
Decidable types – IMJ*
x : L M : R
G ::= void | int | (f : G)
L ::= void | int | (f : G, m : G → L)
R ::= void | int | (f : G, m : L → G)
Games for program equivalence
We focus on:
and employ the fully abstract game semantics for IMJ:
● for negative results, given a queue machine Q, devise terms M, M':
● for decidability, given terms M, M', devise automata A, A':
M ≅ M' ⇔ M = M'
QÝ ⇔ M = M'
M = M' A ~⇔ A'
IMJfin
– {I,II}
Model checking equivalence
GameSemantics
Automata
M
A(M)
Programs M M ≅ M'⇔
M = M'
GameSemantics
Automata
M
A(M)
Programs M Translation done in two steps:
● terms reduced to canonical forms
● canonical terms are compositionally transformed into automata
We work with pushdown automata:
● over infinite alphabets
● visibly pushdown & deterministic
Implemented in Coneqct!
Model checking equivalence
M ≅ M' ⇔ M = M' A⇔ ~ A' A⇔ ÄA' = 0
Coneqct
Coneqct architecture
IMJA Compiler
Canonical form Converter
Automaton Generator
Input IMJ* terms
IMJA Automata
FPDRA Builder
IMJ2A Converter
FPDRA Converter
FPDRA Automaton
FPDRA Reachability
Checker
FPDRA : Fresh Pushdown Register Automata
● MRT: Reachability in Pushdown Register Automata, MFCS'14
● MT: Algorithmic Games for Full Ground References, ICALP'12
Coneqct example
q32808[s1]
(((q32782, s2), s3), s4)[s1]
(((q32783, s2), s3), s4)[s5]
nu {4}. 4[s5]
(((q196, s2), s3), s4)[s5]
p1
(((q32169, s2), s3), s4)[s5]
nu {}. call 4.get(*)[s5]
((((q436, s6), s2), s3), s4)[s5]
nu {}. call 4.set(null)[s5]
(((q31586, s2), s3), s4)[s7]
nu {5}. call 4.set(5)[s7]
(((q32167, s2), s3), s10)[s5]
{4}
(((((q216, s1), s9), s2), s3), s4)[s5]
{4}
(((q31585, s2), s8), s4)[s7]
{4,5}
(((q31583, s11), s8), s4)[s7]
{4,5}
nu {}. *[s1]
(((q32680, s2), s3), s10)[s5]
nu {}. ret 4.get(null)[s5]
(((q32681, s2), s3), s10)[s5]
{4}
(((((q214, s1), s9), s2), s3), s4)[s5]
nu {}. *[s1]
(((q32388, s11), s8), s4)[s7]
nu {}. ret 4.set(*)[s7]
(((q32389, s11), s8), s4)[s7]
{4,5}(((q197, s2), s3), s10)[s5]
p1
(((q32172, s2), s3), s10)[s5]
nu {}. call 4.get(*)[s5]
((((q707, s6), s2), s3), s10)[s5]
nu {}. call 4.set(null)[s5]
(((q31518, s2), s3), s10)[s7]
nu {5}. call 4.set(5)[s7]
(((q209, s11), s8), s4)[s7]
p2
(((q32289, s11), s8), s4)[s7]
nu {}. call 4.get(*)[s7]
((((q24551, s12), s11), s8), s4)[s7]
nu {}. call 4.set(null)[s7]
(((q31626, s11), s8), s4)[s7]
nu {}. call 4.set(5)[s7]
(((q31810, s11), s8), s4)[s13]
nu {6}. call 4.set(6)[s13]
(((q32170, s2), s3), s4)[s5]
{4}
(((((q496, s1), s9), s2), s3), s10)[s5]
{4}
(((q31517, s2), s8), s10)[s7]
{4,5}
(((q31515, s11), s8), s10)[s7]
{4,5}
nu {}. *[s1]
(((q32682, s2), s3), s4)[s5]
nu {}. ret 4.get(null)[s5]
(((q32287, s11), s8), s10)[s7]
{4,5}
(((((q24322, s1), s15), s11), s8), s4)[s7]
{4,5}
(((q31625, s11), s8), s4)[s7]
{4,5}
(((q31809, s11), s14), s4)[s13]
{4,5,6}
(((q31807, s16), s14), s4)[s17]
{4,6}
(((q31623, s11), s8), s4)[s7]
{4,5}nu {}. *[s1]
(((q32760, s11), s8), s10)[s7]
nu {}. ret 4.get(5)[s7]
(((q32683, s2), s3), s4)[s5]
{4}
(((((q494, s1), s9), s2), s3), s10)[s5]
nu {}. *[s1]
(((q32354, s11), s8), s10)[s7]
nu {}. ret 4.set(*)[s7]
(((q32355, s11), s8), s10)[s7]
{4,5}
p1
(((q32761, s11), s8), s10)[s7]
{4,5}
(((((q24320, s1), s15), s11), s8), s4)[s7]
nu {}. *[s1]
(((q32408, s11), s8), s4)[s7]
nu {}. ret 4.set(*)[s7]
(((q32500, s16), s14), s4)[s17]
nu {}. ret 4.set(*)[s17]
(((q32501, s16), s14), s4)[s17]
{4,6}
(((q32409, s11), s8), s4)[s7]
{4,5}
(((q205, s11), s8), s10)[s7]
p2
p2
(((q32241, s11), s8), s10)[s7]
nu {}. call 4.get(*)[s7]
((((q14410, s12), s11), s8), s10)[s7]
nu {}. call 4.set(null)[s7]
(((q31558, s11), s8), s10)[s7]
nu {}. call 4.set(5)[s7]
(((q31742, s11), s8), s10)[s13]
nu {6}. call 4.set(6)[s13]
p2 p3
(((q32239, s11), s8), s4)[s7]
{4,5}
(((((q14100, s1), s15), s11), s8), s10)[s7]
{4,5}
(((q31557, s11), s8), s10)[s7]
{4,5}
(((q31741, s11), s14), s10)[s13]
{4,5,6}
(((q31739, s16), s14), s10)[s17]
{4,6}
(((q31555, s11), s8), s10)[s7]
{4,5}
nu {}. *[s1]
(((q32728, s11), s8), s4)[s7]
nu {}. ret 4.get(5)[s7]
(((q32729, s11), s8), s4)[s7]
{4,5}
(((((q14098, s1), s15), s11), s8), s10)[s7]
nu {}. *[s1]
(((q32374, s11), s8), s10)[s7]
nu {}. ret 4.set(*)[s7]
(((q32466, s16), s14), s10)[s17]
nu {}. ret 4.set(*)[s17]
(((q32467, s16), s14), s10)[s17]
{4,6}
(((q32375, s11), s8), s10)[s7]
{4,5} p2
p2 p3
s1: map []s2: map [(3, (VarEmpty, map [(val, null)]))]s3: map [(2, (VarEmpty, map [(val, null)]))]s4: map [(1, (VarInt, map [(val, 0)]))]s5: map [(4, (Cell, map []))]s6: map [(5, (_VarInt, map [(_val, 0)]))]s7: map [(4, (Cell, map [])); (5, (Empty, map []))]s8: map [(2, (VarEmpty, map [(val, 5)]))]s9: map [(5, (_VarInt, map [(_val, 1)]))]s10: map [(1, (VarInt, map [(val, 1)]))]s11: map [(3, (VarEmpty, map [(val, 5)]))]s12: map [(6, (_VarInt, map [(_val, 0)]))]s13: map [(4, (Cell, map [])); (5, (Empty, map [])); (6, (Empty, map []))]s14: map [(2, (VarEmpty, map [(val, 6)]))]s15: map [(6, (_VarInt, map [(_val, 1)]))]s16: map [(3, (VarEmpty, map [(val, 6)]))]
s17: map [(4, (Cell, map [])); (6, (Empty, map []))]
p1: map [(1, 1); (2, 2); (3, 3); ... ]p2: map [(1, 1); (2, 2); (3, 3); ... ]p3: map [(1, 1); (2, 2); (3, 3); ... ]
(q191, s1)[s2]
(q192, s1)[s3]
nu {2}. 2[s3]
(q1, s1)[s3]
p1
(q165, s1)[s3]
nu {}. call 2.get(*)[s3]
((q33, s4), s1)[s3]
nu {}. call 2.set(null)[s3]
(q146, s1)[s5]
nu {3}. call 2.set(3)[s5]
(q185, s1)[s3]
nu {}. ret 2.get(null)[s3]
(((q8, s2), s7), s1)[s3]
{2}
(q144, s6)[s5]
{2,3}
(q171, s6)[s5]
nu {}. ret 2.set(*)[s5]
(((q6, s2), s7), s1)[s3]
{2}
(q186, s1)[s3]
{2}
p1
{2}
(q172, s6)[s5]
{2,3}
(q2, s6)[s5]
p2
(q167, s6)[s5]
nu {}. call 2.get(*)[s5]
((q85, s8), s6)[s5]
nu {}. call 2.set(null)[s5]
(q149, s6)[s5]
nu {}. call 2.set(3)[s5]
(q158, s6)[s9]
nu {4}. call 2.set(4)[s9]
(q187, s6)[s5]
nu {}. ret 2.get(3)[s5]
(((q54, s2), s12), s6)[s5]
{2,3}
(q147, s6)[s5]
{2,3}
(q156, s10)[s11]
{2,4}
(q179, s10)[s11]
nu {}. ret 2.set(*)[s11]
(q173, s6)[s5]
nu {}. ret 2.set(*)[s5]
(((q52, s2), s12), s6)[s5]
{2,3}
(q188, s6)[s5]
{2,3}
p2
{2,3}
(q174, s6)[s5]
{2,3}
(q180, s10)[s11]
{2,4}
p3p2
s1: map [(1, (VarEmpty, map [(val, null)]))]s2: map []s3: map [(2, (Cell, map []))]s4: map [(3, (_VarInt, map [(_val, 0)]))]s5: map [(2, (Cell, map [])); (3, (Empty, map []))]s6: map [(1, (VarEmpty, map [(val, 3)]))]s7: map [(3, (_VarInt, map [(_val, 1)]))]s8: map [(4, (_VarInt, map [(_val, 0)]))]s9: map [(2, (Cell, map [])); (3, (Empty, map [])); (4, (Empty, map []))]s10: map [(1, (VarEmpty, map [(val, 4)]))]s11: map [(2, (Cell, map [])); (4, (Empty, map []))]
s12: map [(4, (_VarInt, map [(_val, 1)]))]
p1: map [(1, 1); (2, 2)]p2: map [(1, 1); (2, 2); (3, 3)]p3: map [(1, 1); (2, 2); (4, 3)]
M1 : let v = new { _: VarEmpty t
} in new { _: Cell; get : λ_. v.val,
set : λy. if y = null then divelse v.val := y ; w.val := y
M2 : let b = new { _: VarInt
} in
let v = new { _: VarEmpty
} in
let w = new { _: VarEmpty
} in new { _: Cell; get : λ_. if b.val = 1 then b.val := 0 ; v.val
else b.val := 1 ; w.val, set : λy. if y = null then div
else v.val := y ; w.val := y
(q191, s1)[s2]
(q192, s1)[s3]
nu {2}. 2[s3]
(q1, s1)[s3]
p1
(q165, s1)[s3]
nu {}. call 2.get(*)[s3]
((q33, s4), s1)[s3]
nu {}. call 2.set(null)[s3]
(q146, s1)[s5]
nu {3}. call 2.set(3)[s5]
(q185, s1)[s3]
nu {}. ret 2.get(null)[s3]
(((q8, s2), s7), s1)[s3]
{2}
(q144, s6)[s5]
{2,3}
(q171, s6)[s5]
nu {}. ret 2.set(*)[s5]
(((q6, s2), s7), s1)[s3]
{2}
(q186, s1)[s3]
{2}
p1
{2}
(q172, s6)[s5]
{2,3}
(q2, s6)[s5]
p2
(q167, s6)[s5]
nu {}. call 2.get(*)[s5]
((q85, s8), s6)[s5]
nu {}. call 2.set(null)[s5]
(q149, s6)[s5]
nu {}. call 2.set(3)[s5]
(q158, s6)[s9]
nu {4}. call 2.set(4)[s9]
(q187, s6)[s5]
nu {}. ret 2.get(3)[s5]
(((q54, s2), s12), s6)[s5]
{2,3}
(q147, s6)[s5]
{2,3}
(q156, s10)[s11]
{2,4}
(q179, s10)[s11]
nu {}. ret 2.set(*)[s11]
(q173, s6)[s5]
nu {}. ret 2.set(*)[s5]
(((q52, s2), s12), s6)[s5]
{2,3}
(q188, s6)[s5]
{2,3}
p2
{2,3}
(q174, s6)[s5]
{2,3}
(q180, s10)[s11]
{2,4}
p3p2
s1: map [(1, (VarEmpty, map [(val, null)]))]s2: map []s3: map [(2, (Cell, map []))]s4: map [(3, (_VarInt, map [(_val, 0)]))]s5: map [(2, (Cell, map [])); (3, (Empty, map []))]s6: map [(1, (VarEmpty, map [(val, 3)]))]s7: map [(3, (_VarInt, map [(_val, 1)]))]s8: map [(4, (_VarInt, map [(_val, 0)]))]s9: map [(2, (Cell, map [])); (3, (Empty, map [])); (4, (Empty, map []))]s10: map [(1, (VarEmpty, map [(val, 4)]))]s11: map [(2, (Cell, map [])); (4, (Empty, map []))]
s12: map [(4, (_VarInt, map [(_val, 1)]))]
p1: map [(1, 1); (2, 2)]p2: map [(1, 1); (2, 2); (3, 3)]p3: map [(1, 1); (2, 2); (4, 3)]
Coneqct example
M1 : let v = new { _: VarEmpty t
} in new { _: Cell; get : λ_. v.val,
set : λy. if y = null then divelse v.val := y ; w.val := y
M2 : let b = new { _: VarInt
} in
let v = new { _: VarEmpty
} in
let w = new { _: VarEmpty
} in new { _: Cell; get : λ_. if b.val = 1 then b.val := 0 ; v.val
else b.val := 1 ; w.val, set : λy. if y = null then div
else v.val := y ; w.val := y
Wrapping up
Contextual equivalence● decidability characterised via games● automated decision via FPDRAs Coneqct →
Further on● sound methods for the whole of IMJ● general model checking and logics
References● MRT: Game Semantic Analysis of Equivalence in IMJ, ATVA'15
● MRT: A Contextual Equivalence Checker for IMJ*, ATVA'15