classpool: copy field members refs from superclass
[mate.git] / Mate / ClassPool.hs
index d14c2f30c61a5eda67982866fc3cf136f69a767f..b1618edda9c3dac1ff955ba91d790626de3b4cdb 100644 (file)
@@ -2,33 +2,78 @@
 {-# LANGUAGE ForeignFunctionInterface #-}
 module Mate.ClassPool where
 
-import Data.Binary
-import Data.String.Utils
 import qualified Data.Map as M
 import qualified Data.Set as S
 import qualified Data.ByteString.Lazy as B
-import System.Plugins
 
 import Text.Printf
 
 import Foreign.Ptr
 import Foreign.C.Types
-import Foreign.C.String
-import Foreign.StablePtr
 import Foreign.Marshal.Alloc
 
 import JVM.ClassFile
 import JVM.Converter
 
-import Harpy
-import Harpy.X86Disassembler
-
-import Mate.BasicBlocks
 import Mate.Types
-import Mate.Utilities
 
+getClassInfo :: B.ByteString -> IO ClassInfo
+getClassInfo path = do
+  ptr_classmap <- get_classmap
+  class_map <- ptr2classmap ptr_classmap
+  case M.lookup path class_map of
+    Nothing -> loadClass path
+    Just ci -> return ci
 
 getClassFile :: B.ByteString -> IO (Class Resolved)
 getClassFile path = do
+  (ClassInfo _ cfile _ _) <- getClassInfo path
+  return cfile
+
+-- TODO(bernhard): I think we don't need that anymore. also remove fieldbase
+--                 entry in ClassInfo
+getFieldBase :: B.ByteString -> IO (CUInt)
+getFieldBase path = do
+  (ClassInfo _ _ fs _) <- getClassInfo path
+  return $ fromIntegral $ ptrToIntPtr fs
+
+getFieldOffset :: B.ByteString -> B.ByteString -> IO (CUInt)
+getFieldOffset path field = do
+  (ClassInfo _ _ _ fieldmap) <- getClassInfo path
+  return $ fromIntegral $ fieldmap M.! field
+
+foreign export ccall getFieldAddr :: CUInt -> Ptr () -> IO CUInt
+getFieldAddr :: CUInt -> Ptr () -> IO CUInt
+getFieldAddr from ptr_trapmap = do
+  trapmap <- ptr2tmap ptr_trapmap
+  let w32_from = fromIntegral from
+  let sfi = trapmap M.! w32_from
+  case sfi of
+    (SFI (StaticFieldInfo cls field)) -> do
+      getFieldOffset cls field
+    _ -> error $ "getFieldAddr: no trapInfo. abort"
+
+loadClass :: B.ByteString -> IO ClassInfo
+loadClass path = do
+  printf "loadClass: \"%s\"\n" $ toString path
   let rpath = toString $ path `B.append` ".class"
-  parseClassFile rpath
+  cfile <- parseClassFile rpath
+  superclass <- case (path /= "java/lang/Object") of
+      True -> do
+        sc <- loadClass $ superClass cfile
+        return $ Just $ sc
+      False -> return $ Nothing
+  class_map <- get_classmap >>= ptr2classmap
+  -- TODO(bernhard): correct sizes. int only atm
+  let filteredfields = filter (S.member ACC_STATIC . fieldAccessFlags) (classFields cfile)
+  fieldbase <- mallocBytes ((fromIntegral $ length filteredfields) * 4)
+  let i_fb = fromIntegral $ ptrToIntPtr $ fieldbase
+  let fm = zipWith (\x y -> (fieldName y, x + i_fb)) [0,4..] filteredfields
+  let sc_fm = case superclass of Just x -> clFieldMap x; Nothing -> M.empty
+  -- new fields "overwrite" old ones, if they have the same name
+  let fieldmap = (M.fromList fm) `M.union` sc_fm
+  printf "fieldmap: %s @ %s\n" (show fieldmap) (toString path)
+  let new_ci = ClassInfo path cfile fieldbase fieldmap
+  let class_map' = M.insert path new_ci class_map
+  classmap2ptr class_map' >>= set_classmap
+  return new_ci