maxlocals: store it in new data type RawMethod, with MapBB & Co
[mate.git] / Mate / ClassPool.hs
index 0844ea5efa3e96f7655517a20ac59ad4ead29241..ae6ce4450def203be66630d80ec23e7aa3b07aff 100644 (file)
@@ -1,6 +1,5 @@
 {-# LANGUAGE CPP #-}
 {-# LANGUAGE OverloadedStrings #-}
-{-# LANGUAGE ForeignFunctionInterface #-}
 #include "debug.h"
 module Mate.ClassPool (
   getClassInfo,
@@ -20,7 +19,9 @@ import Data.Word
 import Data.Binary
 import qualified Data.Map as M
 import qualified Data.Set as S
+import Data.List
 import qualified Data.ByteString.Lazy as B
+import Data.String.Utils
 import Control.Monad
 
 #ifdef DEBUG
@@ -96,9 +97,10 @@ getStaticFieldAddr from = do
   trapmap <- getTrapMap
   let w32_from = fromIntegral from
   let sfi = trapmap M.! w32_from
+  setTrapMap $ M.delete w32_from trapmap
   case sfi of
-    (SFI (StaticFieldInfo cls field)) -> getStaticFieldOffset cls field
-    _ -> error "getFieldAddr: no trapInfo. abort"
+    (StaticField (StaticFieldInfo cls field)) -> getStaticFieldOffset cls field
+    _ -> error "getFieldAddr: no TrapCause found. abort"
 
 -- interface + method + signature plz!
 getInterfaceMethodOffset :: B.ByteString -> B.ByteString -> B.ByteString -> IO Word32
@@ -113,43 +115,47 @@ getInterfaceMethodOffset ifname meth sig = do
 
 readClass :: B.ByteString -> IO ClassInfo
 readClass path = do
-  cfile <- readClassFile $ toString path
+  class_map' <- getClassMap
+  case M.lookup path class_map' of
+    Just cm -> return cm
+    Nothing -> do
+      cfile <- readClassFile $ toString path
 #ifdef DBG_CLASS
-  dumpClass cfile
+      dumpClass cfile
 #endif
-  -- load all interfaces, which are implemented by this class
-  sequence_ [ loadInterface i | i <- interfaces cfile ]
-  superclass <- if path /= "java/lang/Object"
-      then do
-        sc <- readClass $ superClass cfile
-        return $ Just sc
-      else return Nothing
-
-  (staticmap, fieldmap) <- calculateFields cfile superclass
-  (methodmap, mbase) <- calculateMethodMap cfile superclass
-  immap <- getInterfaceMethodMap
-
-  -- allocate interface offset table for this class
-  -- TODO(bernhard): we have some duplicates in immap (i.e. some
-  --                 entries have the same offset), so we could
-  --                 save some memory here.
-  iftable <- mallocClassData ((4*) $ M.size immap)
-  let w32_iftable = fromIntegral $ ptrToIntPtr iftable :: Word32
-  -- store interface-table at offset 0 in method-table
-  pokeElemOff (intPtrToPtr $ fromIntegral mbase) 0 w32_iftable
-  printfCp "staticmap: %s @ %s\n" (show staticmap) (toString path)
-  printfCp "fieldmap:  %s @ %s\n" (show fieldmap) (toString path)
-  printfCp "methodmap: %s @ %s\n" (show methodmap) (toString path)
-  printfCp "mbase: 0x%08x\n" mbase
-  printfCp "interfacemethod: %s @ %s\n" (show immap) (toString path)
-  printfCp "iftable: 0x%08x\n" w32_iftable
-  virtual_map <- getVirtualMap
-  setVirtualMap $ M.insert mbase path virtual_map
+      -- load all interfaces, which are implemented by this class
+      sequence_ [ loadInterface i | i <- interfaces cfile ]
+      superclass <- if path /= "java/lang/Object"
+          then do
+            sc <- readClass $ superClass cfile
+            return $ Just sc
+          else return Nothing
+
+      (staticmap, fieldmap) <- calculateFields cfile superclass
+      (methodmap, mbase) <- calculateMethodMap cfile superclass
+      immap <- getInterfaceMethodMap
 
-  class_map <- getClassMap
-  let new_ci = ClassInfo path cfile staticmap fieldmap methodmap mbase False
-  setClassMap $ M.insert path new_ci class_map
-  return new_ci
+      -- allocate interface offset table for this class
+      -- TODO(bernhard): we have some duplicates in immap (i.e. some
+      --                 entries have the same offset), so we could
+      --                 save some memory here.
+      iftable <- mallocClassData ((4*) $ M.size immap)
+      let w32_iftable = fromIntegral $ ptrToIntPtr iftable :: Word32
+      -- store interface-table at offset 0 in method-table
+      pokeElemOff (intPtrToPtr $ fromIntegral mbase) 0 w32_iftable
+      printfCp "staticmap: %s @ %s\n" (show staticmap) (toString path)
+      printfCp "fieldmap:  %s @ %s\n" (show fieldmap) (toString path)
+      printfCp "methodmap: %s @ %s\n" (show methodmap) (toString path)
+      printfCp "mbase: 0x%08x\n" mbase
+      printfCp "interfacemethod: %s @ %s\n" (show immap) (toString path)
+      printfCp "iftable: 0x%08x\n" w32_iftable
+      virtual_map <- getVirtualMap
+      setVirtualMap $ M.insert mbase path virtual_map
+
+      class_map <- getClassMap
+      let new_ci = ClassInfo path cfile staticmap fieldmap methodmap mbase False
+      setClassMap $ M.insert path new_ci class_map
+      return new_ci
 
 
 loadInterface :: B.ByteString -> IO ()
@@ -192,25 +198,25 @@ calculateFields :: Class Direct -> Maybe ClassInfo -> IO (FieldMap, FieldMap)
 calculateFields cf superclass = do
     -- TODO(bernhard): correct sizes. int only atm
 
-    let (sfields, ifields) = span (S.member ACC_STATIC . fieldAccessFlags) (classFields cf)
+    let (sfields, ifields) = partition (S.member ACC_STATIC . fieldAccessFlags) (classFields cf)
 
-    staticbase <- mallocClassData $ fromIntegral (length sfields) * 4
-    let i_sb = fromIntegral $ ptrToIntPtr staticbase
-    let sm = zipbase i_sb sfields
     let sc_sm = getsupermap superclass ciStaticMap
+    staticbase <- mallocClassData $ fromIntegral (length sfields) * 4
+    let sm = zipbase (fromIntegral $ ptrToIntPtr staticbase) sfields
     -- new fields "overwrite" old ones, if they have the same name
-    let staticmap = M.fromList sm `M.union` sc_sm
+    let staticmap = sm `M.union` sc_sm
 
     let sc_im = getsupermap superclass ciFieldMap
     -- "+ 4" for the method table pointer
     let max_off = (4+) $ fromIntegral $ M.size sc_im * 4
     let im = zipbase max_off ifields
     -- new fields "overwrite" old ones, if they have the same name
-    let fieldmap = M.fromList im `M.union` sc_im
+    let fieldmap = im `M.union` sc_im
 
     return (staticmap, fieldmap)
   where
-  zipbase base = zipWith (\x y -> (fieldName y, x + base)) [0,4..]
+  zipbase :: Int32 -> [Field Direct] -> FieldMap
+  zipbase base = foldr (\(x,y) -> M.insert (fieldName y) (x + base)) M.empty . zip [0,4..]
 
 -- helper
 getsupermap :: Maybe ClassInfo -> (ClassInfo -> FieldMap) -> FieldMap
@@ -248,11 +254,11 @@ loadAndInitClass path = do
   -- execute class initializer
   case lookupMethod "<clinit>" (ciFile ci) of
     Just m -> do
-      hmap <- parseMethod (ciFile ci) "<clinit>"
-      case hmap of
-        Just hmap' -> do
+      method <- parseMethod (ciFile ci) "<clinit>" $ MethodSignature [] ReturnsVoid
+      case method of
+        Just rawmethod -> do
           let mi = MethodInfo "<clinit>" path (methodSignature m)
-          entry <- compileBB hmap' mi
+          entry <- compileBB rawmethod mi
           addMethodRef entry mi [path]
           printfCp "executing static initializer from %s now\n" (toString path)
           executeFuncPtr entry
@@ -267,17 +273,20 @@ loadAndInitClass path = do
 
 
 readClassFile :: String -> IO (Class Direct)
-readClassFile path = readIORef classPaths >>= rcf
+readClassFile path' = readIORef classPaths >>= rcf
   where
+  path = replace "." "/" path'
   rcf :: [MClassPath] -> IO (Class Direct)
-  rcf [] = error $ "readClassFile: Class \"" ++ (show path) ++ "\" not found."
-  rcf ((Directory pre):xs) = do
+  rcf [] = error $ "readClassFile: Class \"" ++ show path ++ "\" not found."
+  rcf (Directory pre:xs) = do
     let cf = pre ++ path ++ ".class"
+    printfCp "rcf: searching @ %s for %s\n" (show pre) (show path)
     b <- doesFileExist cf
     if b
       then parseClassFile cf
       else rcf xs
-  rcf ((JAR p):xs) = do
+  rcf (JAR p:xs) = do
+    printfCp "rcf: searching %s in JAR\n" (show path)
     entry <- getEntry p path
     case entry of
       Just (LoadedJAR _ cls) -> return cls