Skip to content

Commit 2fdb2cb

Browse files
author
Louis Jenkins
committedNov 1, 2016
Implemented the Load and Store instructions for majority of types. At
least int and long are working, not sure about double and float since I need to look at IEEE format. Point is though, its getting there.
1 parent 816e172 commit 2fdb2cb

File tree

5 files changed

+154
-30
lines changed

5 files changed

+154
-30
lines changed
 

‎DataTypes/Class_File.hs

+1-8
Original file line numberDiff line numberDiff line change
@@ -63,18 +63,11 @@ module DataTypes.Class_File where
6363
stack <- bootstrap
6464
str <- debugStack stack
6565
Prelude.putStrLn $ "Pre-Stack: " ++ str
66-
pushFrame stack [1]
66+
pushFrame stack [4,59,10,64]
6767
-- let codeAttr = getCodeAttribute (cp_info classFile) (classfile_attributes classFile)
6868
-- let code' = code codeAttr
6969
str' <- debugStack stack
7070
Prelude.putStrLn $ "Post-Stack: " ++ str'
7171
debugExec stack
7272
str'' <- debugStack stack
7373
Prelude.putStrLn $ "Final-Stack: " ++ str''
74-
pushFrame stack [1,1,1,1]
75-
debugExec stack
76-
debugExec stack
77-
debugExec stack
78-
debugExec stack
79-
str''' <- debugStack stack
80-
Prelude.putStrLn $ "Extended-Stack: " ++ str'''

‎VirtualMachine/ByteCode.hs

+135-4
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,145 @@
11
module VirtualMachine.ByteCode where
22
import Data.IORef
3+
import Data.Bits
34
import VirtualMachine.Types
45
import VirtualMachine.Stack_Frame
56

7+
execute' :: StackFrame -> ByteCode -> Instructions -> IO ()
8+
execute' frame bc instrRef
9+
-- NOP
10+
| bc == 0 = return ()
11+
-- *CONST*
12+
| bc >= 1 && bc <= 15 = constOp frame bc
13+
-- BIPUSH BYTE
14+
| bc == 16 = do
15+
byte <- getNextBC instrRef
16+
pushOp (fromIntegral byte) frame
17+
-- SIPUSH BYTE1 BYTE2
18+
| bc == 17 = do
19+
byte1 <- getNextBC instrRef
20+
byte2 <- getNextBC instrRef
21+
pushOp (fromIntegral byte1 `shift` 8 .|. fromIntegral byte2) frame
22+
-- LDC* (TODO)
23+
-- *LOAD*
24+
| bc >= 21 && bc <= 53 = loadOp frame bc instrRef
25+
-- *STORE*
26+
| bc >= 54 && bc <= 86 = storeOp frame bc instrRef
27+
| otherwise = error $ "Bad ByteCode Instruction: " ++ show bc
28+
629
execute :: StackFrame -> Instructions -> IO ()
730
execute frame instrRef = do
8-
mnemonic <- getNextBC instrRef
9-
case mnemonic of
10-
1 -> pushOp 0 frame
11-
_ -> return ()
31+
instr <- readIORef instrRef
32+
case length instr of
33+
0 -> return ()
34+
_ -> do
35+
bc <- getNextBC instrRef
36+
execute' frame bc instrRef
37+
execute frame instrRef
38+
39+
40+
constOp :: StackFrame -> ByteCode -> IO ()
41+
constOp frame bc
42+
-- ACONST_NULL
43+
| bc == 1 = pushOp 0 frame
44+
-- ICONST_*
45+
| bc >= 2 && bc <= 8 = pushOp (fromIntegral $ bc - 3) frame
46+
-- LCONST_*
47+
| bc == 9 || bc == 10 = pushOp (fromIntegral $ bc - 9) frame
48+
-- FCONST_*
49+
| bc >= 11 && bc <= 13 = pushOp (fromIntegral $ bc - 11) frame
50+
-- DCONST_*
51+
| bc >= 14 && bc <= 15 = pushOp (fromIntegral $ bc - 14) frame
52+
--
53+
| otherwise = error $ "Bad ByteCode Instruction: " ++ show bc
54+
55+
loadOp :: StackFrame -> ByteCode -> Instructions -> IO ()
56+
loadOp frame bc instrRef
57+
-- ILOAD || FLOAD || ALOAD
58+
| bc == 21 || bc == 23 || bc == 25 = do
59+
idx <- getNextBC instrRef
60+
local <- getLocal (fromIntegral idx) frame
61+
pushOp (fromIntegral local) frame
62+
-- LLOAD || DLOAD
63+
| bc == 22 || bc == 24 = do
64+
idx <- getNextBC instrRef
65+
high <- getLocal (fromIntegral idx) frame
66+
low <- getLocal (fromIntegral $ idx + 1) frame
67+
let local = high .|. low
68+
pushOp (fromIntegral local) frame
69+
-- ILOAD_*
70+
| bc >= 26 && bc <= 29 = do
71+
local <- getLocal (fromIntegral $ bc - 26) frame
72+
pushOp (fromIntegral local) frame
73+
-- LLOAD_*
74+
| bc >= 30 && bc <= 33 = do
75+
let idx = fromIntegral $ bc - 30
76+
high <- getLocal idx frame
77+
low <- getLocal (idx + 1) frame
78+
let local = high .|. low
79+
pushOp (fromIntegral local) frame
80+
-- FLOAD_*
81+
| bc >= 34 && bc <= 37 = do
82+
local <- getLocal (fromIntegral $ bc - 34) frame
83+
pushOp (fromIntegral local) frame
84+
-- DLOAD_*
85+
| bc >= 38 && bc <= 41 = do
86+
let idx = fromIntegral $ bc - 38
87+
high <- getLocal idx frame
88+
low <- getLocal (idx + 1) frame
89+
let local = high .|. low
90+
pushOp (fromIntegral local) frame
91+
-- ALOAD_*
92+
| bc >= 42 && bc <= 45 = do
93+
local <- getLocal (fromIntegral $ bc - 42) frame
94+
pushOp (fromIntegral local) frame
95+
-- *ALOAD (TODO)
96+
| otherwise = error $ "Bad ByteCode Instruction: " ++ show bc
97+
98+
storeOp :: StackFrame -> ByteCode -> Instructions -> IO ()
99+
storeOp frame bc instrRef
100+
-- ISTORE || FSTORE || ASTORE
101+
| bc == 54 || bc == 56 || bc == 58 = do
102+
idx <- getNextBC instrRef
103+
operand <- popOp frame
104+
putLocal (fromIntegral idx) (fromIntegral operand) frame
105+
-- LSTORE || DSTORE
106+
| bc == 55 || bc == 57 = do
107+
idx <- getNextBC instrRef
108+
operand <- popOp frame
109+
let high = operand `shiftR` 32
110+
let low = operand .&. 0xFFFFFFFF
111+
putLocal (fromIntegral idx) (fromIntegral high) frame
112+
putLocal (fromIntegral $ idx + 1) (fromIntegral low) frame
113+
-- ISTORE_*
114+
| bc >= 59 && bc <= 62 = do
115+
operand <- popOp frame
116+
putLocal (fromIntegral $ bc - 59) (fromIntegral operand) frame
117+
-- LSTORE_*
118+
| bc >= 63 && bc <= 66 = do
119+
let idx = fromIntegral $ bc - 63
120+
operand <- popOp frame
121+
let high = operand `shiftR` 32
122+
let low = operand .&. 0xFFFFFFFF
123+
putLocal (fromIntegral idx) (fromIntegral high) frame
124+
putLocal (fromIntegral $ idx + 1) (fromIntegral low) frame
125+
-- FSTORE_*
126+
| bc >= 67 && bc <= 70 = do
127+
operand <- popOp frame
128+
putLocal (fromIntegral $ bc - 67) (fromIntegral operand) frame
129+
-- DSTORE_*
130+
| bc >= 71 && bc <= 74 = do
131+
let idx = fromIntegral $ bc - 71
132+
operand <- popOp frame
133+
let high = operand `shiftR` 32
134+
let low = operand .&. 0xFFFFFFFF
135+
putLocal (fromIntegral idx) (fromIntegral high) frame
136+
putLocal (fromIntegral $ idx + 1) (fromIntegral low) frame
137+
-- ALOAD_*
138+
| bc >= 75 && bc <= 78 = do
139+
operand <- popOp frame
140+
putLocal (fromIntegral $ bc - 75) (fromIntegral operand) frame
141+
-- *ALOAD (TODO)
142+
| otherwise = error $ "Bad ByteCode Instruction: " ++ show bc
12143

13144
getNextBC :: Instructions -> IO ByteCode
14145
getNextBC instrRef = do

‎VirtualMachine/Stack_Frame.hs

+14-8
Original file line numberDiff line numberDiff line change
@@ -27,9 +27,15 @@ module VirtualMachine.Stack_Frame where
2727
putLocal offset val frameRef = do
2828
frame <- readIORef frameRef
2929
let l = locals frame
30-
old <- readIORef l
31-
writeIORef l ((element (fromEnum offset) .~ val) old)
32-
30+
-- TODO: Change to Data.Array.MArray, so I can avoid this mess
31+
modifyIORef l (inject 0 offset val)
32+
where
33+
inject :: Word16 -> Word16 -> Value -> [Local_Variable] -> [Local_Variable]
34+
inject m n val' (x:xs)
35+
| n == m = val' : x : xs
36+
| n > m = x : inject (m+1) n val' xs
37+
| otherwise = error $ "Bad range: " ++ show m ++ " of " ++ show n
38+
inject _ _ val' [] = [val']
3339
{-
3440
Returns the value associated the given index.
3541
-}
@@ -43,26 +49,26 @@ module VirtualMachine.Stack_Frame where
4349
{-
4450
Pushes a value on the operand stack
4551
-}
46-
pushOp :: Value -> StackFrame -> IO ()
52+
pushOp :: Operand -> StackFrame -> IO ()
4753
pushOp val frameRef = do
4854
frame <- readIORef frameRef
4955
let o = opStack frame
50-
modifyIORef' o (\old -> val : old)
56+
modifyIORef' o (\old -> fromIntegral val : old)
5157

5258
{-
5359
Pops the operand off of the stack
5460
-}
55-
popOp :: StackFrame -> IO Value
61+
popOp :: StackFrame -> IO Operand
5662
popOp frameRef = do
5763
frame <- readIORef frameRef
5864
let o = opStack frame
5965
arr <- readIORef o
6066
let val = head arr
6167
modifyIORef' o tail
62-
return val
68+
return $ fromIntegral val
6369

6470
{-
6571
Pops off N operands off of the stack
6672
-}
67-
popOpN :: Word8 -> StackFrame -> IO [Value]
73+
popOpN :: Word8 -> StackFrame -> IO [Operand]
6874
popOpN n frameRef = replicateM (fromEnum n) (popOp frameRef)

‎VirtualMachine/Types.hs

+4-4
Original file line numberDiff line numberDiff line change
@@ -9,12 +9,12 @@ module VirtualMachine.Types where
99
type ByteCode = Word8
1010
type Instructions = IORef [ByteCode]
1111

12-
type Local_Variable = Int
13-
type Operands = Int
14-
type Value = Int
12+
type Local_Variable = Word64
13+
type Operand = Word32
14+
type Value = Word64
1515

1616
data Stack_Frame = Frame {
1717
locals :: IORef [Local_Variable],
18-
opStack :: IORef [Operands],
18+
opStack :: IORef [Operand],
1919
instructions :: Instructions
2020
}

‎proposal.md

-6
Original file line numberDiff line numberDiff line change
@@ -26,9 +26,3 @@ the built-in Haskell functionality. As well, String concatenation of primitive t
2626
example of accessing constants can be seen at §3.4), as they can be further substituted for built-in types. As well, auto-boxed objects such as `Integer`, `Double`, and `Float` (auto-boxing generally created using the
2727
`valueOf` static method) can also be substituted. As well, support for invoking methods (creating a new stack frame) as well as basic exception handling (only `java/lang/Exception`), the latter being optional by the time
2828
of presentation, should simulate the stack.
29-
30-
### Haskell Implementation Details
31-
32-
This will make heavy-use of Haskell's built-in constructs as utilities, and involves comprehensive knowledge of mathematical constructs such as the `Functor` and `Monad`, as well as extensive knowledge of its control
33-
constructs. Parsing is handled using the `StateT` monad, which handles elegant simple state transitions, and the JVM `Environment` is kept mutable by using the `IORef` monad for mutable state, and also allowing interleaved
34-
IO. The implementation details, may change by the time of presentation.

0 commit comments

Comments
 (0)