new insn: fix wrong behaviour on lazy class init
[mate.git] / Mate / ClassPool.hs
index 8788e75ab9261caa320d425cdd55d2a31a00d66e..88749995a59e7e5b95e7f7f40f73a5bb923d7a55 100644 (file)
@@ -3,6 +3,7 @@
 #include "debug.h"
 module Mate.ClassPool (
   getClassInfo,
+  classLoaded,
   getClassFile,
   getMethodTable,
   getObjectSize,
@@ -49,6 +50,7 @@ import {-# SOURCE #-} Mate.MethodPool
 import Mate.Types
 import Mate.Debug
 import Mate.GarbageAlloc
+import Mate.NativeSizes
 
 getClassInfo :: B.ByteString -> IO ClassInfo
 getClassInfo path = do
@@ -57,12 +59,17 @@ getClassInfo path = do
     Nothing -> loadAndInitClass path
     Just ci -> return ci
 
+classLoaded :: B.ByteString -> IO Bool
+classLoaded path = do
+  class_map <- getClassMap
+  return $ M.member path class_map
+
 getClassFile :: B.ByteString -> IO (Class Direct)
 getClassFile path = do
   ci <- getClassInfo path
   return $ ciFile ci
 
-getStaticFieldOffset :: B.ByteString -> B.ByteString -> IO CUInt
+getStaticFieldOffset :: B.ByteString -> B.ByteString -> IO CPtrdiff
 getStaticFieldOffset path field = do
   ci <- getClassInfo path
   return $ fromIntegral $ ciStaticMap ci M.! field
@@ -76,8 +83,8 @@ getFieldOffset path field = do
 getMethodOffset :: B.ByteString -> B.ByteString -> IO Word32
 getMethodOffset path method = do
   ci <- getClassInfo path
-  -- (4+) one slot for "interface-table-ptr"
-  return $ (+4) $ fromIntegral $ ciMethodMap ci M.! method
+  -- (+ ptrSize) one slot for "interface-table-ptr"
+  return $ (+ ptrSize) $ fromIntegral $ ciMethodMap ci M.! method
 
 getMethodTable :: B.ByteString -> IO Word32
 getMethodTable path = do
@@ -90,9 +97,9 @@ getObjectSize path = do
   -- TODO(bernhard): correct sizes for different types...
   let fsize = fromIntegral $ M.size $ ciFieldMap ci
   -- one slot for "method-table-ptr"
-  return $ (1 + fsize) * 4
+  return $ (1 + fsize) * ptrSize
 
-getStaticFieldAddr :: CUInt -> IO CUInt
+getStaticFieldAddr :: CPtrdiff -> IO CPtrdiff
 getStaticFieldAddr from = do
   trapmap <- getTrapMap
   let w32_from = fromIntegral from
@@ -189,9 +196,9 @@ loadInterface path = do
       setInterfaceMethodMap $ M.fromList sm `M.union` M.fromList mm `M.union` immap
       setInterfaceMap $ M.insert path cfile imap'
   where
-  zipbase base = zipWith (\x y -> (entry y, x + base)) [0,4..]
-  entry = getname path
-  getname p y = p `B.append` methodName y `B.append` encode (methodSignature y)
+    zipbase base = zipWith (\x y -> (entry y, x + base)) [0,4..]
+    entry = getname path
+    getname p y = p `B.append` methodName y `B.append` encode (methodSignature y)
 
 
 calculateFields :: Class Direct -> Maybe ClassInfo -> IO (FieldMap, FieldMap)
@@ -215,8 +222,8 @@ calculateFields cf superclass = do
 
     return (staticmap, fieldmap)
   where
-  zipbase :: Int32 -> [Field Direct] -> FieldMap
-  zipbase base = foldr (\(x,y) -> M.insert (fieldName y) (x + base)) M.empty . zip [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
@@ -254,16 +261,13 @@ loadAndInitClass path = do
   -- execute class initializer
   case lookupMethod "<clinit>" (ciFile ci) of
     Just m -> do
-      hmap <- parseMethod (ciFile ci) "<clinit>" $ MethodSignature [] ReturnsVoid
-      case hmap of
-        Just hmap' -> do
-          let mi = MethodInfo "<clinit>" path (methodSignature m)
-          entry <- compileBB hmap' mi
-          addMethodRef entry mi [path]
-          printfCp "executing static initializer from %s now\n" (toString path)
-          executeFuncPtr entry
-          printfCp "static initializer from %s done\n" (toString path)
-        Nothing -> error "readClass: static initializer not found (WTF?). abort"
+      rawmethod <- parseMethod (ciFile ci) "<clinit>" $ MethodSignature [] ReturnsVoid
+      let mi = MethodInfo "<clinit>" path (methodSignature m)
+      entry <- compileBB rawmethod mi
+      addMethodRef entry mi [path]
+      printfCp "executing static initializer from %s now\n" (toString path)
+      executeFuncPtr entry
+      printfCp "static initializer from %s done\n" (toString path)
     Nothing -> return ()
 
   class_map' <- getClassMap
@@ -275,23 +279,23 @@ loadAndInitClass path = do
 readClassFile :: String -> IO (Class Direct)
 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
-    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
-    printfCp "rcf: searching %s in JAR\n" (show path)
-    entry <- getEntry p path
-    case entry of
-      Just (LoadedJAR _ cls) -> return cls
-      Nothing -> rcf xs
-      _ -> error $ "readClassFile: Class \"" ++ show path ++ "\" in JAR not found. #1"
+    path = replace "." "/" path'
+    rcf :: [MClassPath] -> IO (Class Direct)
+    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
+      printfCp "rcf: searching %s in JAR\n" (show path)
+      entry <- getEntry p path
+      case entry of
+        Just (LoadedJAR _ cls) -> return cls
+        Nothing -> rcf xs
+        _ -> error $ "readClassFile: Class \"" ++ show path ++ "\" in JAR not found. #1"
 
 data MClassPath =
   Directory String |