; Formal Model of the JVM - Spring 2007 ; J Strother Moore ; Practice Final Exam ; There are five problems. Each is worth 20 points. Be sure to ; put your name on your paper! You have 3 hours to do the five ; problems. You may use your notes and books. Laptops are not ; permitted. ; Partial credit will be given. ; During the actual final you will not be allowed to use ACL2. ; But to play with this practice final, you might: (include-book "m5") (in-package "M5") ; ----------------------------------------------------------------- ; Problem 1. On the actual JVM, each class description has a ; ``constant pool'' component, which associates 16-bit indices to ; various data structures. Programs are coded as a strings of ; bytes. Consider the M5's GETFIELD instruction, which we write ; as (GETFIELD (class field)). On the JVM, this is coded in three ; successive 8-bit bytes, the first of which is the hex byte B4 ; (180, decimal), which stands for GETFIELD. The next two bytes, ; say x and then y, are combined to form a 16-bit index (with x ; being the high order part and y the low order part) into the ; constant pool. The data structure at that index contains the ; class and field (strings) we write in the M5 instruction. ; Why does the JVM use the constant pool concept? Why not put ; the data in the program, as we do in M1? ; Answer 1: ; The instruction stream is just a list of bytes. To include constants in it ; would slow down the parsing and require that the constants be allocated as ; objects in the heap. Thus, without runtime modification of the instruction ; stream (a sort of mini-JIT compiling) constants would be (re-)allocated upon ; every arrival at an instruction. The constant pool allows all constants to ; be allocated at class load time. It simplifies instruction parsing. It ; makes the legal pcs in a program easier to determine. It makes the ; instruction syntax more regular. And it allows multiple occurrences of ; constants to be shared. ; ----------------------------------------------------------------- ; Problem 2. An M5 ``method description'' is a keytuple with the ; components :name, :formals, :sync, :code, and :xtbl. Thus, ; given a method description m, (get :code m) is the list of ; bytecode instructions and (get :xtbl m) is the exception table. ; The exception table is expected to satisfy the specification: ; An exception table is a list of 4-tuples, each of the form ; (pc1 pc2 pc3 class), where the pci are legal pcs in the method, ; pc1 <= pc2, and class is the name of some class in the class ; table. ; Write an ACL2 function, chk-xt (``check exception table''), ; that takes a method description, m, and a class-table, ct, and ; returns t or nil to indicate whether the method-exception-table ; of m satisfies the above specification. ; Answer 2: (defun legal-pcp (pc prog) (and (integerp pc) (<= 0 pc) (< pc (len prog)))) (defun chk-handler (h prog ct) (and (true-listp h) (equal (len h) 4) (let ((pc1 (nth 0 h)) (pc2 (nth 1 h)) (pc3 (nth 2 h)) (css (nth 3 h))) (and (legal-pcp pc1 prog) (legal-pcp pc2 prog) (legal-pcp pc3 prog) (<= pc1 pc2) (find :name css ct))))) (defun chk-xt-aux (tbl prog ct) (if (endp tbl) t (and (chk-handler (car tbl) prog ct) (chk-xt-aux (cdr tbl) prog ct)))) (defun chk-xt (m ct) (chk-xt-aux (get :xtbl m) (get :code m) ct)) ; ----------------------------------------------------------------- ; Problem 3. Extend M5 to include the new instruction described ; below. It is sufficient to define execute-XRETURNN. ; Format: (XRETURNN n) ; Operand Stack: ... val => ..., val ; Description: Return val from the nth frame from the current ; one. If n is 0, this instruction is the same as XRETURN. If n ; is 1, we return val from the frame that called the current ; frame, etc. If the call-stack is insufficiently deep, halt the ; machine. ; Note: To play with M5, you might execute (redef) and ; (set-ignore-ok t) so that you can use defsem and can redefine ; do-inst, but that is not necessary in answering these ; questions. ; Answer 3: (defun execute-XRETURNN1 (n id s) (cond ((zp n) (execute-XRETURN '(XRETURN) id s)) ((endp (pop (cst id s))) nil) (t (let ((s1 (execute-XRETURN '(XRETURN) id s))) (execute-XRETURNN1 (- n 1) id s1))))) (set-ignore-ok t) (defsem (XRETURNN n) (let ((s1 (execute-XRETURNN1 n id s))) (if s1 s1 s))) ; ----------------------------------------------------------------- ; Problem 4. Extend M5 to include the new instruction described ; below. It is sufficient to define execute-INC. ; Format: (INC n) ; Operand Stack: ... => ... ; Description: Increment the value of local variable n by 1. ; Answer 4. (defsem (INC n) (modify id s :locs (update-nth n (+ 1 (nth n -locs-)) -locs-))) ; ----------------------------------------------------------------- ; Problem 5. Extend M5 to include the new instruction described ; below. It is sufficient to define execute-STORENEW. ; Format: (STORENEW n class) ; Operand Stack: ... => ... ; Description: Create a new object of class class and store the ; reference to it into local n. (defsem (STORENEW n class) (execute-STORE (list 'STORE n) id (execute-NEW (list 'NEW class) id (modify id s :pc (- -pc- 1))))) ; Note: before executing the NEW I backed the pc up by 1 so it ; would still point to the (STORENEW n class) when I execute the ; STORE. This is a little funky but it works. Note that the ; intermediate pc might even be -1, but that doesn't matter since ; all we do is increment it again. ; -----------------------------------------------------------------