new insn: fix wrong behaviour on lazy class init
authorBernhard Urban <lewurm@gmail.com>
Fri, 17 Aug 2012 17:21:45 +0000 (19:21 +0200)
committerBernhard Urban <lewurm@gmail.com>
Fri, 17 Aug 2012 15:47:30 +0000 (17:47 +0200)
TODO:
- invokevirtual
- invokeinterface

Mate/ClassPool.hs
Mate/Types.hs
Mate/X86CodeGen.hs
Mate/X86TrapHandling.hs
tests/Instance5.java [new file with mode: 0644]

index e6c5bfef8d333b2650755be78844b47021ff8809..88749995a59e7e5b95e7f7f40f73a5bb923d7a55 100644 (file)
@@ -3,6 +3,7 @@
 #include "debug.h"
 module Mate.ClassPool (
   getClassInfo,
+  classLoaded,
   getClassFile,
   getMethodTable,
   getObjectSize,
@@ -58,6 +59,11 @@ 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
index 65c8546dc9b4429971430cac5a904c2b562b0a61..831744ab27e1c0d96e162cd16fe6de4707b86dc2 100644 (file)
@@ -41,6 +41,7 @@ data TrapCause =
   VirtualMethod Bool MethodInfo | -- for virtual calls
   InterfaceMethod Bool MethodInfo | -- for interface calls
   InstanceOf B.ByteString | -- class name
+  NewObject B.ByteString | -- class name
   StaticField StaticFieldInfo deriving Show
 
 data StaticFieldInfo = StaticFieldInfo {
index f1f9969da9237e802697d7890eeffa923993d577..ffdc83d8b2021d6f7e8639c38fc6257feb9b4072 100644 (file)
@@ -192,6 +192,16 @@ emitFromBB cls method = do
       push eax
       forceRegDump
       return $ Just (trapaddr, InstanceOf $ buildClassID cls cpidx)
+    emit' (NEW objidx) = do
+      let objname = buildClassID cls objidx
+      trapaddr <- getCurrentOffset
+      -- place something like `push $objsize' instead
+      emit32 (0x9090ffff :: Word32) >> emit8 (0x90 :: Word8)
+      callMalloc
+      -- 0x13371337 is just a placeholder; will be replaced with mtable ptr
+      mov (Disp 0, eax) (0x13371337 :: Word32)
+      return $ Just (trapaddr, NewObject objname)
+
     emit' insn = emit insn >> return Nothing
 
     emit :: J.Instruction -> CodeGen e s ()
@@ -245,15 +255,7 @@ emitFromBB cls method = do
       pop ebx -- length
       mov (Disp 0, eax) ebx -- store length at offset 0
       push eax -- push ref again
-    emit (NEW objidx) = do
-      let objname = buildClassID cls objidx
-      amount <- liftIO $ getObjectSize objname
-      push (amount :: Word32)
-      callMalloc
-      -- TODO(bernhard): save reference somewhere for GC
-      -- set method table pointer
-      mtable <- liftIO $ getMethodTable objname
-      mov (Disp 0, eax) mtable
+
     emit (CHECKCAST _) = nop -- TODO(bernhard): ...
     emit ATHROW = -- TODO(bernhard): ...
         emit32 (0xffffffff :: Word32)
index 325f7928c44eb82401d32a44b957ad9a416336ea..493a3ceaf1b1a3a4a45c2d29bcacbeb6034a7a2e 100644 (file)
@@ -26,6 +26,7 @@ data TrapType =
   | VirtualMethodCall Bool
   | InterfaceMethodCall Bool
   | InstanceOfMiss B.ByteString
+  | NewObjectTrap B.ByteString
   | NoKnownTrap String
 
 getTrapType :: TrapMap -> CPtrdiff -> CPtrdiff -> TrapType
@@ -34,6 +35,7 @@ getTrapType tmap signal_from from2 =
     (Just (StaticMethod _)) -> StaticMethodCall
     (Just (StaticField _)) -> StaticFieldAccess
     (Just (InstanceOf cn)) -> InstanceOfMiss cn
+    (Just (NewObject cn)) -> NewObjectTrap cn
     (Just _) -> NoKnownTrap "getTrapMap: doesn't happen"
     -- maybe we've a hit on the second `from' value
     Nothing -> case M.lookup (fromIntegral from2) tmap of
@@ -51,6 +53,7 @@ mateHandler eip eax ebx esp esi = do
     StaticMethodCall  -> staticCallHandler eip
     StaticFieldAccess -> staticFieldHandler eip
     (InstanceOfMiss cn) -> instanceOfMissHandler eip cn
+    (NewObjectTrap cn) -> newObjectHandler eip cn
     VirtualMethodCall imm8   -> invokeHandler eax eax esp imm8
     InterfaceMethodCall imm8 -> invokeHandler eax ebx esp imm8
     NoKnownTrap err ->
@@ -105,6 +108,22 @@ instanceOfMissHandler eip classname = do
       return eip
     else error "instanceOfMissHandler: something is wrong here. abort.\n"
 
+newObjectHandler :: CPtrdiff -> B.ByteString -> IO CPtrdiff
+newObjectHandler eip classname = do
+  let push_insn_ptr = intPtrToPtr (fromIntegral eip) :: Ptr CUChar
+  let push_imm_ptr = intPtrToPtr (fromIntegral (eip + 1)) :: Ptr CPtrdiff
+  let mov_imm_ptr = intPtrToPtr (fromIntegral (eip + 16)) :: Ptr CPtrdiff
+  checkMe <- peek mov_imm_ptr
+  if checkMe == 0x13371337
+    then do
+      objsize <- getObjectSize classname
+      mtable <- getMethodTable classname
+      poke push_insn_ptr 0x68 -- push_imm insn
+      poke push_imm_ptr (fromIntegral objsize)
+      poke mov_imm_ptr (fromIntegral mtable)
+      return eip
+    else error "newObjectHandler: something is wrong here. abort.\n"
+
 invokeHandler :: CPtrdiff -> CPtrdiff -> CPtrdiff -> Bool -> IO CPtrdiff
 invokeHandler method_table table2patch esp imm8 = do
   -- table2patch: note, that can be a method-table or a interface-table
diff --git a/tests/Instance5.java b/tests/Instance5.java
new file mode 100644 (file)
index 0000000..d3f3fb8
--- /dev/null
@@ -0,0 +1,19 @@
+package tests;
+
+public class Instance5 {
+       public static void main(String []args) {
+               int i_am_null = 0;
+               if (i_am_null > 0) {
+                       new Instance5_notload();
+                       System.out.printf("loaded notload stuff o_O\n");
+               } else {
+                       System.out.printf("Nothing to do here\n");
+               }
+       }
+}
+
+class Instance5_notload {
+       static {
+               System.out.printf("sup, I'm Instance5_notload\n");
+       }
+}