text‹
state is modeled as $\textrm{heap} \times\textrm{stack-variables} \times\textrm{local-variables}$
and local variables are modeled as pairs of natural numbers. The first number
the position in the call stack (i.e. the method in which the variable is used),
second the position in the method's stack or array of local variables resp.
stack variables are numbered from bottom up (which is the reverse order of the
for the stack in Jinja's state representation), whereas local variables are identified
their position in the array of local variables of Jinja's state representation. ›
text‹
function models instruction execution for our state representation.
parameters are the call depth of the current program point,
stack length of the current program point,
length of the stack in the underlying call frame (needed for {\sc Return}),
(for {\sc Invoke}) the length of the array of local variables of the invoked method.
handling is not covered by this function. ›
fun exec_instr :: "instr ==> wf_jvmprog ==> state ==> nat ==> nat ==> nat ==> nat ==> state" where
exec_instr_Load: "exec_instr (Load n) P s calldepth stk_length rs ill = (let (h,stk,loc) = s in (h, stk((calldepth,stk_length):=loc(calldepth,n)), loc))"
| exec_instr_Store: "exec_instr (Store n) P s calldepth stk_length rs ill = (let (h,stk,loc) = s in (h, stk, loc((calldepth,n):=stk(calldepth,stk_length - 1))))"
| exec_instr_Push: "exec_instr (Push v) P s calldepth stk_length rs ill = (let (h,stk,loc) = s in (h, stk((calldepth,stk_length):=v), loc))"
| exec_instr_New: "exec_instr (New C) P s calldepth stk_length rs ill = (let (h,stk,loc) = s; a = the(new_Addr h) in (h(a ↦ (blank (P) C)), stk((calldepth,stk_length):=Addr a), loc))"
| exec_instr_Getfield: "exec_instr (Getfield F C) P s calldepth stk_length rs ill = (let (h,stk,loc) = s; a = the_Addr (stk (calldepth,stk_length - 1)); (D,fs) = the(h a) in (h, stk((calldepth,stk_length - 1) := the(fs(F,C))), loc))"
| exec_instr_Putfield: "exec_instr (Putfield F C) P s calldepth stk_length rs ill = (let (h,stk,loc) = s; v = stk (calldepth,stk_length - 1); a = the_Addr (stk (calldepth,stk_length - 2)); (D,fs) = the(h a) in (h(a ↦ (D,fs((F,C) ↦ v))), stk, loc))"
| exec_instr_Checkcast: "exec_instr (Checkcast C) P s calldepth stk_length rs ill = s"
| exec_instr_Pop: "exec_instr (Pop) P s calldepth stk_length rs ill = s"
| exec_instr_Goto: "exec_instr (Goto i) P s calldepth stk_length rs ill = s"
| exec_instr_Throw: "exec_instr (Throw) P s calldepth stk_length rs ill = s"
| exec_instr_Invoke: "exec_instr (Invoke M n) P s calldepth stk_length rs invoke_loc_length = (let (h,stk,loc) = s; loc' = (λ(a,b). if (a ≠ Suc calldepth ∨ b ≥ invoke_loc_length) then loc(a,b) else (if (b ≤ n) then stk(calldepth, stk_length - (Suc n - b)) else arbitrary)) in (h,stk,loc'))"
| exec_instr_Return: "exec_instr (Return) P s calldepth stk_length ret_stk_length ill = (if (calldepth = 0) then s else (let (h,stk,loc) = s; v = stk(calldepth, stk_length - 1) in (h,stk((calldepth - 1, ret_stk_length - 1) := v),loc)) )"
subsubsection‹length of stack and local variables›
text‹The following terms extract the stack length at a given program point
the well-typing of the given program›
abbreviation stkLength :: "wf_jvmprog ==> cname ==> mname ==> pc ==> nat" where "stkLength P C M pc ≡ length (fst(the(((P<Phi>) C M)!pc)))"
abbreviation locLength :: "wf_jvmprog ==> cname ==> mname ==> pc ==> nat" where "locLength P C M pc ≡ length (snd(the(((P<Phi>) C M)!pc)))"
subsubsection‹Conversion functions›
text‹
function takes a natural number n and a function f with domain ‹nat›
creates the array [f 0, f 1, f 2, ..., f (n - 1)].
is used for extracting the array of local variables ›
(* funlocs::"nat\<Rightarrow>(nat\<Rightarrow>'a)\<Rightarrow>'alist" where "locs0loc=[]" |"locs(Sucn)loc=(locsnloc)@[locn]"
*)
abbreviation locs :: "nat ==> (nat ==> 'a) ==> 'a list" where"locs n loc ≡ map loc [0..<n]"
text‹
function takes a natural number n and a function f with domain ‹nat›
creates the array [f (n - 1), ..., f 1, f 0].
is used for extracting the stack as a list ›
(* funstks::"nat\<Rightarrow>(nat\<Rightarrow>'a)\<Rightarrow>'alist" where "stks0stk=[]" |"stks(Sucn)stk=(stkn)#(stksnstk)"
*)
abbreviation stks :: "nat ==> (nat ==> 'a) ==> 'a list" where"stks n stk ≡ map stk (rev [0..<n])"
text‹
function creates a list of the arrays for local variables from the given state
to the given callstack ›
fun locss :: "wf_jvmprog ==> callstack ==> ((nat × nat) ==> 'a) ==> 'a list list" where "locss P [] loc = []"
| "locss P ((C,M,pc)#cs) loc = (locs (locLength P C M pc) (λa. loc (length cs, a)))#(locss P cs loc)"
text‹
function creates a list of the (methods') stacks from the given state
to the given callstack ›
fun stkss :: "wf_jvmprog ==> callstack ==> ((nat × nat) ==> 'a) ==> 'a list list" where "stkss P [] stk = []"
| "stkss P ((C,M,pc)#cs) stk = (stks (stkLength P C M pc) (λa. stk (length cs, a)))#(stkss P cs stk)"
text‹Given a callstack and a state, this abbreviation converts the state
Jinja's state representation ›
abbreviation state_to_jvm_state :: "wf_jvmprog ==> callstack ==> state ==> jvm_state" where"state_to_jvm_state P cs s ≡ (None, heap_of s, zip (stkss P cs (stk_of s)) (zip (locss P cs (loc_of s)) cs))"
text‹This function extracts the call stack from a given frame stack (as it is given
Jinja's state representation) ›
text‹Now we lift byte code verifier conformance to our state representation›
definition bv_conform :: "wf_jvmprog ==> callstack ==> state ==> bool"
(‹_,_ ⊨ _ √›) where"P,cs ⊨ s √≡ correct_state (P) (P<Phi>) (state_to_jvm_state P cs s)"
subsubsection‹Statically determine catch-block›
text‹This function is equivalent to Jinja's ‹find_handler› function› fun find_handler_for :: "wf_jvmprog ==> cname ==> callstack ==> callstack" where "find_handler_for P C [] = []"
| "find_handler_for P C (c#cs) = (let (C',M',pc') = c in (case match_ex_table (P) C pc' (ex_table_of (P) C' M') of None ==> find_handler_for P C cs | Some pc_d ==> (C', M', fst pc_d)#cs))"
subsection‹Simplification lemmas›
lemma find_handler_decr [simp]: "find_handler_for P Exc cs ≠ c#cs" proof assume"find_handler_for P Exc cs = c#cs" hence"length cs < length (find_handler_for P Exc cs)"by simp thus False by (induct cs, auto) qed
lemma stkss_length [simp]: "length (stkss P cs stk) = length cs" by (induct cs) auto
lemma locss_length [simp]: "length (locss P cs loc) = length cs" by (induct cs) auto
(* lemmanth_stks:"b<n\<Longrightarrow>stksnstk!b=stk(n-Sucb)" by(autosimp:rev_nth) proof(inductnarbitrary:b) case(0b) thus?casebysimp next case(Sucnb) thus?case by(autosimp:nth_Cons'less_Suc_eq) qed
*)
lemma nth_stkss: "[ a < length cs; b < length (stkss P cs stk ! (length cs - Suc a)) ] ==> stkss P cs stk ! (length cs - Suc a) ! (length (stkss P cs stk ! (length cs - Suc a)) - Suc b) = stk (a,b)" proof (induct cs) case Nil thus ?caseby (simp add: nth_Cons') next case (Cons aa cs) thus ?case by (cases aa, auto simp add: nth_Cons' rev_nth less_Suc_eq) qed
(* lemmanth_locs:"b<n\<Longrightarrow>locsnloc!b=locb" proof(inductn) case0 thus?casebysimp next case(Sucn) thus?case by(autosimp:nth_appendless_Suc_eq) qed
*)
lemma nth_locss: "[ a < length cs; b < length (locss P cs loc ! (length cs - Suc a)) ] ==> locss P cs loc ! (length cs - Suc a) ! b = loc (a,b)" proof (induct cs) case Nil thus ?caseby (simp add: nth_Cons') next case (Cons aa cs) thus ?case by (cases aa, auto simp: nth_Cons' (* nth_locs *) less_Suc_eq) qed
lemma hd_stks [simp]: "n ≠ 0 ==> hd (stks n stk) = stk(n - 1)" by (cases n, simp_all)
lemma hd_tl_stks: "n > 1 ==> hd (tl (stks n stk)) = stk(n - 2)" by (cases n, auto)
lemma stkss_purge: "length cs ≤ a ==> stkss P cs (stk((a,b) := c)) = stkss P cs stk" by (induct cs, auto (* simp: stks_purge *))
lemma stkss_purge': "length cs ≤ a ==> stkss P cs (λs. if s = (a, b) then c else stk s) = stkss P cs stk" by (fold fun_upd_def, simp only: stkss_purge)
lemma locss_purge: "length cs ≤ a ==> locss P cs (loc((a,b) := c)) = locss P cs loc" by (induct cs, auto (*simp: locs_purge *))
lemma locss_purge': "length cs ≤ a ==> locss P cs (λs. if s = (a, b) then c else loc s) = locss P cs loc" by (fold fun_upd_def, simp only: locss_purge)
lemma locs_pullout [simp]: "locs b (loc(n := e)) = (locs b loc) [n := e]" proof (induct b) case0 thus ?caseby simp next case (Suc b) thus ?case by (cases "n - b", auto simp: list_update_beyond list_update_append not_less_eq less_Suc_eq) qed
lemma locs_pullout' [simp]: "locs b (λa. if a = n then e else loc (c, a)) = (locs b (λa. loc (c, a))) [n := e]" by (fold fun_upd_def) simp
lemma stks_pullout: "n < b ==> stks b (stk(n := e)) = (stks b stk) [b - Suc n := e]" proof (induct b) case0 thus ?caseby simp next case (Suc b) thus ?case proof (cases "b = n") case True with Suc show ?thesis by auto (* by (auto simp: stks_purge') *) next case False with Suc show ?thesis by (cases "b - n") (auto intro!: nth_equalityI simp: nth_list_update) qed qed
lemma nth_tl : "xs ≠ [] ==> tl xs ! n = xs ! (Suc n)" by (cases xs, simp_all)
text‹Nodes are labeled with a callstack and an optional tuple (consisting of
callstack and a flag).
first callstack determines the current program point (i.e. the next statement
execute). If the second parameter is not None, we are at an intermediate state,
the target of the instruction is determined (the second callstack)
the flag is set to whether an exception is thrown or not. › datatype j_node =
Entry (‹'('_Entry'_')›)
| Node "callstack""(callstack × bool) option" (‹'('_ _,_ '_')›)
text‹An edge is a triple, consisting of two nodes and the edge kind›
type_synonym j_edge = "(j_node × state edge_kind × j_node)"
subsection‹CFG›
text‹
CFG is constructed by a case analysis on the instructions and
different behavior in different states. E.g. the exceptional behavior of \sc New}, if there is no more space in the heap, vs. the normal behavior.
: The set of edges defined by this predicate is a first approximation to the
set of edges in the CFG. We later (theory JVMInterpretation) add some well-formedness
to the nodes. ›
| JCFG_ReturnExit: "[ prog = (P,C0,Main); (instrs_of (P) C M) ! pc = Return ] ==> prog ⊨ (_ [(C, M, pc)],None _) -⇑id→ (_Exit_)"
| JCFG_Straight_NoExc: "[ prog = (P, C0, Main); instrs_of (P) C M ! pc ∈ {Load idx, Store idx, Push val, Pop, IAdd, CmpEq}; ek = ⇑(λs. exec_instr ((instrs_of (P) C M) ! pc) P s (length cs) (stkLength P C M pc) arbitrary arbitrary) ] ==> prog ⊨ (_ (C, M, pc)#cs,None _) -ek→ (_ (C, M, Suc pc)#cs,None _)"
| JCFG_New_Normal_Pred: "[ prog = (P, C0, Main); (instrs_of (P) C M) ! pc = (New Cl); ek = (λ(h,stk,loc). new_Addr h ≠ None)\<surd>] ==> prog ⊨ (_ (C, M, pc)#cs,None _) -ek→ (_ (C, M, pc)#cs,⌊((C, M, Suc pc)#cs,False)⌋ _)"
| JCFG_New_Normal_Update: "[ prog = (P, C0, Main); (instrs_of (P) C M) ! pc = (New Cl); ek = ⇑(λs. exec_instr (New Cl) P s (length cs) (stkLength P C M pc) arbitrary arbitrary) ] ==> prog ⊨ (_ (C, M, pc)#cs,⌊((C, M, Suc pc)#cs, False)⌋ _) -ek→ (_ (C, M, Suc pc)#cs,None _)"
| JCFG_New_Exc_Pred: "[ prog = (P, C0, Main); (instrs_of (P) C M) ! pc = (New Cl); find_handler_for P OutOfMemory ((C, M, pc)#cs) = cs'; ek = (λ(h,stk,loc). new_Addr h = None)\<surd> ] ==> prog ⊨ (_ (C, M, pc)#cs,None _) -ek→ (_ (C, M, pc)#cs,⌊(cs',True)⌋ _)"
| JCFG_New_Exc_Update: "[ prog = (P, C0, Main); (instrs_of (P) C M) ! pc = (New Cl); find_handler_for P OutOfMemory ((C, M, pc)#cs) = (C', M', pc')#cs'; ek = ⇑(λ(h,stk,loc). (h, stk((length cs',(stkLength P C' M' pc') - 1) := Addr (addr_of_sys_xcpt OutOfMemory)), loc) ) ] ==> prog ⊨ (_ (C, M, pc)#cs,⌊((C', M', pc')#cs', True)⌋ _) -ek→ (_ (C', M', pc')#cs',None _)"
| JCFG_New_Exc_Exit: "[ prog = (P, C0, Main); (instrs_of (P) C M) ! pc = (New Cl); find_handler_for P OutOfMemory ((C, M, pc)#cs) = [] ] ==> prog ⊨ (_ (C, M, pc)#cs,⌊([], True)⌋ _) -⇑id→ (_Exit_)"
| JCFG_Getfield_Normal_Pred: "[ prog = (P, C0, Main); (instrs_of (P) C M) ! pc = (Getfield Fd Cl); ek = (λ(h,stk,loc). stk(length cs, stkLength P C M pc - 1) ≠ Null)\<surd> ] ==> prog ⊨ (_ (C, M, pc)#cs,None _) -ek→ (_ (C, M, pc)#cs,⌊((C, M, Suc pc)#cs, False)⌋ _)"
| JCFG_Getfield_Normal_Update: "[ prog = (P, C0, Main); (instrs_of (P) C M) ! pc = (Getfield Fd Cl); ek = ⇑(λs. exec_instr (Getfield Fd Cl) P s (length cs) (stkLength P C M pc) arbitrary arbitrary) ] ==> prog ⊨ (_ (C, M, pc)#cs,⌊((C, M, Suc pc)#cs, False)⌋ _) -ek→ (_ (C, M, Suc pc)#cs,None _)"
| JCFG_Getfield_Exc_Pred: "[ prog = (P, C0, Main); (instrs_of (P) C M) ! pc = (Getfield Fd Cl); find_handler_for P NullPointer ((C, M, pc)#cs) = cs'; ek = (λ(h,stk,loc). stk(length cs, stkLength P C M pc - 1) = Null)\<surd> ] ==> prog ⊨ (_ (C, M, pc)#cs,None _) -ek→ (_ (C, M, pc)#cs,⌊(cs', True)⌋ _)"
| JCFG_Getfield_Exc_Update: "[ prog = (P, C0, Main); (instrs_of (P) C M) ! pc = (Getfield Fd Cl); find_handler_for P NullPointer ((C, M, pc)#cs) = (C', M', pc')#cs'; ek = ⇑(λ(h,stk,loc). (h, stk((length cs',(stkLength P C' M' pc') - 1) := Addr (addr_of_sys_xcpt NullPointer)), loc) ) ] ==> prog ⊨ (_ (C, M, pc)#cs,⌊((C', M', pc')#cs', True)⌋ _) -ek→ (_ (C', M', pc')#cs',None _)"
| JCFG_Getfield_Exc_Exit: "[ prog = (P, C0, Main); (instrs_of (P) C M) ! pc = (Getfield Fd Cl); find_handler_for P NullPointer ((C, M, pc)#cs) = [] ] ==> prog ⊨ (_ (C, M, pc)#cs,⌊([], True)⌋ _) -⇑id→ (_Exit_)"
| JCFG_Putfield_Normal_Pred: "[ prog = (P, C0, Main); (instrs_of (P) C M) ! pc = (Putfield Fd Cl); ek = (λ(h,stk,loc). stk(length cs, stkLength P C M pc - 2) ≠ Null)\<surd> ] ==> prog ⊨ (_ (C, M, pc)#cs,None _) -ek→ (_ (C, M, pc)#cs,⌊((C, M, Suc pc)#cs, False)⌋ _)"
| JCFG_Putfield_Normal_Update: "[ prog = (P, C0, Main); (instrs_of (P) C M) ! pc = (Putfield Fd Cl); ek = ⇑(λs. exec_instr (Putfield Fd Cl) P s (length cs) (stkLength P C M pc) arbitrary arbitrary) ] ==> prog ⊨ (_ (C, M, pc)#cs,⌊((C, M, Suc pc)#cs, False)⌋ _) -ek→ (_ (C, M, Suc pc)#cs,None _)"
| JCFG_Putfield_Exc_Pred: "[ prog = (P, C0, Main); (instrs_of (P) C M) ! pc = (Putfield Fd Cl); find_handler_for P NullPointer ((C, M, pc)#cs) = cs'; ek = (λ(h,stk,loc). stk(length cs, stkLength P C M pc - 2) = Null)\<surd> ] ==> prog ⊨ (_ (C, M, pc)#cs,None _) -ek→ (_ (C, M, pc)#cs,⌊(cs', True)⌋ _)"
| JCFG_Putfield_Exc_Update: "[ prog = (P, C0, Main); (instrs_of (P) C M) ! pc = (Putfield Fd Cl); find_handler_for P NullPointer ((C, M, pc)#cs) = (C', M', pc')#cs'; ek = ⇑(λ(h,stk,loc). (h, stk((length cs',(stkLength P C' M' pc') - 1) := Addr (addr_of_sys_xcpt NullPointer)), loc) ) ] ==> prog ⊨ (_ (C, M, pc)#cs,⌊((C', M', pc')#cs', True)⌋ _) -ek→ (_ (C', M', pc')#cs',None _)"
| JCFG_Putfield_Exc_Exit: "[ prog = (P, C0, Main); (instrs_of (P) C M) ! pc = (Putfield Fd Cl); find_handler_for P NullPointer ((C, M, pc)#cs) = [] ] ==> prog ⊨ (_ (C, M, pc)#cs,⌊([], True)⌋ _) -⇑id→ (_Exit_)"
| JCFG_Checkcast_Normal_Pred: "[ prog = (P, C0, Main); (instrs_of (P) C M) ! pc = (Checkcast Cl); ek = (λ(h,stk,loc). cast_ok (P) Cl h (stk(length cs, stkLength P C M pc - Suc 0)))\<surd> ] ==> prog ⊨ (_ (C, M, pc)#cs,None _) -ek→ (_ (C, M, Suc pc)#cs,None _)"
| JCFG_Checkcast_Exc_Pred: "[ prog = (P, C0, Main); (instrs_of (P) C M) ! pc = (Checkcast Cl); find_handler_for P ClassCast ((C, M, pc)#cs) = cs'; ek = (λ(h,stk,loc). ¬ cast_ok (P) Cl h (stk(length cs, stkLength P C M pc - Suc 0)))\<surd> ] ==> prog ⊨ (_ (C, M, pc)#cs,None _) -ek→ (_ (C, M, pc)#cs,⌊(cs', True)⌋ _)"
| JCFG_Checkcast_Exc_Update: "[ prog = (P, C0, Main); (instrs_of (P) C M) ! pc = (Checkcast Cl); find_handler_for P ClassCast ((C, M, pc)#cs) = (C', M', pc')#cs'; ek = ⇑(λ(h,stk,loc). (h, stk((length cs',(stkLength P C' M' pc') - 1) := Addr (addr_of_sys_xcpt ClassCast)), loc) ) ] ==> prog ⊨ (_ (C, M, pc)#cs,⌊((C', M', pc')#cs', True)⌋ _) -ek→ (_ (C', M', pc')#cs',None _)"
| JCFG_Checkcast_Exc_Exit: "[ prog = (P, C0, Main); (instrs_of (P) C M) ! pc = (Checkcast Cl); find_handler_for P ClassCast ((C, M, pc)#cs) = [] ] ==> prog ⊨ (_ (C, M, pc)#cs,⌊([], True)⌋ _) -⇑id→ (_Exit_)"
| JCFG_Invoke_Normal_Pred: "[ prog = (P, C0, Main); (instrs_of (P) C M) ! pc = (Invoke M2 n); cd = length cs; stk_length = stkLength P C M pc; ek = (λ(h,stk,loc). stk(cd, stk_length - Suc n) ≠ Null ∧ fst(method (P) (cname_of h (the_Addr(stk(cd, stk_length - Suc n)))) M2) = D )\<surd> ] ==> prog ⊨ (_ (C, M, pc)#cs,None _) -ek→ (_ (C, M, pc)#cs,⌊((D, M2, 0)#(C, M, pc)#cs, False)⌋ _)"
| JCFG_Invoke_Normal_Update: "[ prog = (P, C0, Main); (instrs_of (P) C M) ! pc = (Invoke M2 n); stk_length = stkLength P C M pc; loc_length = locLength P D M2 0; ek = ⇑(λs. exec_instr (Invoke M2 n) P s (length cs) stk_length arbitrary loc_length) ] ==> prog ⊨ (_ (C, M, pc)#cs,⌊((D, M2, 0)#(C, M, pc)#cs, False)⌋ _) -ek→ (_ (D, M2, 0)#(C, M, pc)#cs,None _)"
| JCFG_Invoke_Exc_Pred: "[ prog = (P, C0, Main); (instrs_of (P) C M) ! pc = (Invoke m2 n); find_handler_for P NullPointer ((C, M, pc)#cs) = cs'; ek = (λ(h,stk,loc). stk(length cs, stkLength P C M pc - Suc n) = Null)\<surd> ] ==> prog ⊨ (_ (C, M, pc)#cs,None _) -ek→ (_ (C, M, pc)#cs,⌊(cs', True)⌋ _)"
| JCFG_Invoke_Exc_Update: "[ prog = (P, C0, Main); (instrs_of (P) C M) ! pc = (Invoke M2 n); find_handler_for P NullPointer ((C, M, pc)#cs) = (C', M', pc')#cs'; ek = ⇑(λ(h,stk,loc). (h, stk((length cs',(stkLength P C' M' pc') - 1) := Addr (addr_of_sys_xcpt NullPointer)), loc) ) ] ==> prog ⊨ (_ (C, M, pc)#cs,⌊((C', M', pc')#cs', True)⌋ _) -ek→ (_ (C', M', pc')#cs',None _)"
| JCFG_Invoke_Exc_Exit: "[ prog = (P, C0, Main); (instrs_of (P) C M) ! pc = (Invoke M2 n); find_handler_for P NullPointer ((C, M, pc)#cs) = [] ] ==> prog ⊨ (_ (C, M, pc)#cs,⌊([], True)⌋ _) -⇑id→ (_Exit_)"
| JCFG_Return_Update: "[ prog = (P, C0, Main); (instrs_of (P) C M) ! pc = Return; stk_length = stkLength P C M pc; r_stk_length = stkLength P C' M' (Suc pc'); ek = ⇑(λs. exec_instr Return P s (Suc (length cs)) stk_length r_stk_length arbitrary) ] ==> prog ⊨ (_ (C, M, pc)#(C', M', pc')#cs,None _) -ek→ (_ (C', M', Suc pc')#cs,None _)"
| JCFG_Goto_Update: "[ prog = (P, C0, Main); (instrs_of (P) C M) ! pc = Goto idx ] ==> prog ⊨ (_ (C, M, pc)#cs,None _) -⇑id→ (_ (C, M, nat (int pc + idx))#cs,None _)"
| JCFG_IfFalse_False: "[ prog = (P, C0, Main); (instrs_of (P) C M) ! pc = (IfFalse b); b ≠ 1; ek = (λ(h,stk,loc). stk(length cs, stkLength P C M pc - 1) = Bool False)\<surd> ] ==> prog ⊨ (_ (C, M, pc)#cs,None _) -ek→ (_ (C, M, nat (int pc + b))#cs,None _)"
| JCFG_IfFalse_Next: "[ prog = (P, C0, Main); (instrs_of (P) C M) ! pc = (IfFalse b); ek = (λ(h,stk,loc). stk(length cs, stkLength P C M pc - 1) ≠ Bool False ∨ b = 1)\<surd> ] ==> prog ⊨ (_ (C, M, pc)#cs,None _) -ek→ (_ (C, M, Suc pc)#cs,None _)"
| JCFG_Throw_Pred: "[ prog = (P, C0, Main); (instrs_of (P) C M) ! pc = Throw; cd = length cs; stk_length = stkLength P C M pc; ∃Exc. find_handler_for P Exc ((C, M, pc)#cs) = cs'; ek = (λ(h,stk,loc). (stk(length cs, stkLength P C M pc - 1) = Null ∧ find_handler_for P NullPointer ((C, M, pc)#cs) = cs') ∨ (stk(length cs, stkLength P C M pc - 1) ≠ Null ∧ find_handler_for P (cname_of h (the_Addr(stk(cd, stk_length - 1)))) ((C, M, pc)#cs) = cs') )\<surd> ] ==> prog ⊨ (_ (C, M, pc)#cs,None _) -ek→ (_ (C, M, pc)#cs,⌊(cs', True)⌋ _)"
| JCFG_Throw_Update: "[ prog = (P, C0, Main); (instrs_of (P) C M) ! pc = Throw; ek = ⇑(λ(h,stk,loc). (h, stk((length cs',(stkLength P C' M' pc') - 1) := if (stk(length cs, stkLength P C M pc - 1) = Null) then Addr (addr_of_sys_xcpt NullPointer) else (stk(length cs, stkLength P C M pc - 1))), loc) ) ] ==> prog ⊨ (_ (C, M, pc)#cs,⌊((C', M', pc')#cs', True)⌋ _) -ek→ (_ (C', M', pc')#cs',None _)"
| JCFG_Throw_Exit: "[ prog = (P, C0, Main); (instrs_of (P) C M) ! pc = Throw ] ==> prog ⊨ (_ (C, M, pc)#cs,⌊([],True)⌋ _) -⇑id→ (_Exit_)"
subsection‹CFG properties›
lemma JVMCFG_Exit_no_sourcenode [dest]: assumes edge:"prog ⊨ (_Exit_) -et→ n'" shows"False" proof -
{ fix n have"[prog ⊨ n -et→ n'; n = (_Exit_)]==> False" by (auto elim!: JVM_CFG.cases)
} with edge show ?thesis by fastforce qed
lemma JVMCFG_Entry_no_targetnode [dest]: assumes edge:"prog ⊨ n -et→ (_Entry_)" shows"False" proof -
{ fix n' have"[prog ⊨ n -et→ n'; n' = (_Entry_)]==> False" by (auto elim!: JVM_CFG.cases)
} with edge show ?thesis by fastforce qed
lemma JVMCFG_EntryD: "[(P,C,M) ⊨ n -et→ n'; n = (_Entry_)] ==> (n' = (_Exit_) ∧ et = (λs. False)\<surd>) ∨ (n' = (_ [(C,M,0)],None _) ∧ et = (λs. True)\<surd>)" by (erule JVM_CFG.cases) simp_all
(* The following lemma explores many cases, it takes a little while to prove *) lemma JVMCFG_edge_det: "[prog ⊨ n -et→ n'; prog ⊨ n -et'→ n']==> et = et'" by (erule JVM_CFG.cases; erule JVM_CFG.cases; fastforce)
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.