patching: define patcher in X86CodeGen itself where possible
authorBernhard Urban <lewurm@gmail.com>
Mon, 27 Aug 2012 09:59:16 +0000 (11:59 +0200)
committerBernhard Urban <lewurm@gmail.com>
Mon, 27 Aug 2012 09:59:16 +0000 (11:59 +0200)
Mate/MethodPool.hs
Mate/MethodPool.hs-boot
Mate/Types.hs
Mate/X86CodeGen.hs
Mate/X86TrapHandling.hs

index 4a7cf7e384929223061888580ea70a877aac3840..e04b709a77f868b7912576130fc4a631692d7a42 100644 (file)
@@ -38,24 +38,14 @@ foreign import ccall "&loadLibrary"
 foreign import ccall "&printGCStats"
   printGCStatsAddr :: FunPtr (IO ())
 
-getMethodEntry :: CPtrdiff -> CPtrdiff -> IO CPtrdiff
-getMethodEntry signal_from methodtable = do
+getMethodEntry :: MethodInfo -> IO CPtrdiff
+getMethodEntry mi@(MethodInfo method cm sig) = do
   mmap <- getMethodMap
-  tmap <- getTrapMap
-  vmap <- getVirtualMap
-
-  let w32_from = fromIntegral signal_from
-  let mi = tmap M.! w32_from
-  let mi'@(MethodInfo method cm sig) =
-       case mi of
-         (StaticMethod x) -> x
-         (VirtualCall _ (MethodInfo methname _ msig) _) -> newMi methname msig
-         _ -> error "getMethodEntry: no TrapCause found. abort."
-       where newMi mn = MethodInfo mn (vmap M.! fromIntegral methodtable)
-  entryaddr <- case M.lookup mi' mmap of
+
+  entryaddr <- case M.lookup mi mmap of
     Nothing -> do
       cls <- getClassFile cm
-      printfMp $ printf "getMethodEntry(from 0x%08x): no method \"%s\" found. compile it\n" w32_from (show mi')
+      printfMp $ printf "getMethodEntry: no method \"%s\" found. compile it\n" (show mi)
       mm <- lookupMethodRecursive method sig [] cls
       case mm of
         Just (mm', clsnames, cls') -> do
@@ -81,12 +71,12 @@ getMethodEntry signal_from methodtable = do
                       symbol = sym1 ++ "__" ++ smethod ++ "__" ++ sym2
                   printfMp $ printf "native-call: symbol: %s\n" symbol
                   nf <- loadNativeFunction symbol
-                  setMethodMap $ M.insert mi' nf mmap
+                  setMethodMap $ M.insert mi nf mmap
                   return nf
               else do
                 rawmethod <- parseMethod cls' method sig
                 entry <- compileBB rawmethod (MethodInfo method (thisClass cls') sig)
-                addMethodRef entry mi' clsnames
+                addMethodRef entry mi clsnames
                 return $ fromIntegral entry
         Nothing -> error $ show method ++ " not found. abort"
     Just w32 -> return w32
index 0527cd739f25fbdfa4b03e361a31317e0ba1ba52..a1dfe4f0c134a358f9935e1b1b1d6b1afe4bfed7 100644 (file)
@@ -12,4 +12,4 @@ import Foreign.C.Types
 addMethodRef :: NativeWord -> MethodInfo -> [B.ByteString] -> IO ()
 compileBB :: RawMethod -> MethodInfo -> IO NativeWord
 executeFuncPtr :: NativeWord -> IO ()
-getMethodEntry :: CPtrdiff -> CPtrdiff -> IO CPtrdiff
+getMethodEntry :: MethodInfo -> IO CPtrdiff
index 060ffb7403e3d1e036bbec9cedbc97eab3659288..ec76a4cb7d41f5b3631b550e296ee479ba085708 100644 (file)
@@ -69,10 +69,10 @@ type TrapMap = M.Map NativeWord TrapCause
 type TrapPatcher = CPtrdiff -> CodeGen () () CPtrdiff
 
 data TrapCause
-  = StaticMethod MethodInfo -- for static calls
+  = StaticMethod TrapPatcher -- for static calls
   | VirtualCall Bool MethodInfo (IO NativeWord) -- for invoke{interface,virtual}
   | InstanceOf B.ByteString -- class name
-  | NewObject B.ByteString -- class name
+  | NewObject TrapPatcher -- class name
   | StaticField StaticFieldInfo
   | ObjectField TrapPatcher
 
index 9b39388d23941b81c6856faddccbb41a29cace8c..9abe1f4cb0ff17bd9b9ca46787cb4fe4f1ca52dc 100644 (file)
@@ -27,6 +27,7 @@ import Mate.NativeSizes
 import Mate.Types
 import Mate.Utilities
 import Mate.ClassPool
+import {-# SOURCE #-} Mate.MethodPool
 import Mate.Strings
 
 
@@ -109,12 +110,16 @@ emitFromBB cls method = do
       -- causes SIGILL. in the signal handler we patch it to the acutal call.
       -- place two nop's at the end, therefore the disasm doesn't screw up
       emit32 (0x9090ffff :: Word32); nop
+      let patcher reip = do
+            entryAddr <- liftIO $ getMethodEntry l
+            call (fromIntegral (entryAddr - (reip + 5)) :: NativeWord)
+            return reip
       -- discard arguments on stack
       let argcnt = ((if hasThis then 1 else 0) + methodGetArgsCount (methodNameTypeByIdx cls cpidx)) * ptrSize
       when (argcnt > 0) (add esp argcnt)
       -- push result on stack if method has a return value
       when (methodHaveReturnValue cls cpidx) (push eax)
-      return $ Just (calladdr, StaticMethod l)
+      return $ Just (calladdr, StaticMethod patcher)
 
     virtualCall :: Word16 -> Bool -> CodeGen e s (Maybe (Word32, TrapCause))
     virtualCall cpidx isInterface = do
@@ -210,7 +215,14 @@ emitFromBB cls method = do
       callMalloc
       -- 0x13371337 is just a placeholder; will be replaced with mtable ptr
       mov (Disp 0, eax) (0x13371337 :: Word32)
-      return $ Just (trapaddr, NewObject objname)
+      let patcher reip = do
+            objsize <- liftIO $ getObjectSize objname
+            push32 objsize
+            callMalloc
+            mtable <- liftIO $ getMethodTable objname
+            mov (Disp 0, eax) mtable
+            return reip
+      return $ Just (trapaddr, NewObject patcher)
 
     emit' insn = emit insn >> return Nothing
 
index bf4b28831a4ef44f0b07f7f69dbc6b5941ef4ed7..ecf346a2771e7249525ffadfd9d36a1ecd528efb 100644 (file)
@@ -32,21 +32,21 @@ mateHandler reip reax rebx resi = do
   tmap <- getTrapMap
   let reipw32 = fromIntegral reip
   (deleteMe, ret_nreip) <- case M.lookup reipw32 tmap of
-    (Just (StaticMethod _)) ->
-        patchWithHarpy patchStaticCall reip >>= delTrue
+    (Just (StaticMethod patcher)) ->
+        patchWithHarpy patcher reip >>= delTrue
     (Just (StaticField _))  ->
         staticFieldHandler reip >>= delTrue
     (Just (ObjectField patcher)) ->
         patchWithHarpy patcher reip >>= delTrue
     (Just (InstanceOf cn))  ->
         patchWithHarpy (`patchInstanceOf` cn) reip >>= delFalse
-    (Just (NewObject cn))   ->
-        patchWithHarpy (`patchNewObject` cn) reip >>= delTrue
-    (Just (VirtualCall False _ io_offset)) ->
-        patchWithHarpy (patchInvoke reax reax io_offset) reip
+    (Just (NewObject patcher))   ->
+        patchWithHarpy patcher reip >>= delTrue
+    (Just (VirtualCall False mi io_offset)) ->
+        patchWithHarpy (patchInvoke mi reax reax io_offset) reip
         >>= delTrue
-    (Just (VirtualCall True  _ io_offset)) ->
-        patchWithHarpy (patchInvoke rebx reax io_offset) reip
+    (Just (VirtualCall True  mi io_offset)) ->
+        patchWithHarpy (patchInvoke mi rebx reax io_offset) reip
         >>= delTrue
     Nothing -> case resi of
         0x13371234 -> return (-1) >>= delFalse
@@ -80,13 +80,6 @@ withDisasm patcher = do
   d <- disassemble
   return (reip, d)
 
-patchStaticCall :: CPtrdiff -> CodeGen e s CPtrdiff
-patchStaticCall reip = do
-  entryAddr <- liftIO $ getMethodEntry reip 0
-  call (fromIntegral (entryAddr - (reip + 5)) :: NativeWord)
-  return reip
-
-
 staticFieldHandler :: CPtrdiff -> IO CPtrdiff
 staticFieldHandler reip = do
   -- patch the offset here, first two bytes are part of the insn (opcode + reg)
@@ -104,19 +97,12 @@ patchInstanceOf reip classname = do
   mov edx mtable
   return reip
 
-patchNewObject :: CPtrdiff -> B.ByteString -> CodeGen e s CPtrdiff
-patchNewObject reip classname = do
-  objsize <- liftIO $ getObjectSize classname
-  push32 objsize
-  callMalloc
-  mtable <- liftIO $ getMethodTable classname
-  mov (Disp 0, eax) mtable
-  return reip
-
-patchInvoke :: CPtrdiff -> CPtrdiff -> IO NativeWord -> CPtrdiff -> CodeGen e s CPtrdiff
-patchInvoke method_table table2patch io_offset reip = do
+patchInvoke :: MethodInfo -> CPtrdiff -> CPtrdiff -> IO NativeWord -> CPtrdiff -> CodeGen e s CPtrdiff
+patchInvoke (MethodInfo methname _ msig)  method_table table2patch io_offset reip = do
+  vmap <- liftIO $ getVirtualMap
+  let newmi = MethodInfo methname (vmap M.! fromIntegral method_table) msig
   offset <- liftIO io_offset
-  entryAddr <- liftIO $ getMethodEntry reip method_table
+  entryAddr <- liftIO $ getMethodEntry newmi
   call32_eax (Disp offset)
   -- patch entry in table
   let call_insn = intPtrToPtr . fromIntegral $ table2patch + fromIntegral offset