fields: use offsets from ClassInfo in codegen
authorBernhard Urban <lewurm@gmail.com>
Wed, 25 Apr 2012 09:03:06 +0000 (11:03 +0200)
committerBernhard Urban <lewurm@gmail.com>
Wed, 25 Apr 2012 09:03:06 +0000 (11:03 +0200)
BUT:
    Couldn't match expected type `IO CUInt'
           against inferred type `CodeGen e s CUInt'

any idea how to solve this problem *without* `unsafePerformIO'?

Makefile
Mate/ClassPool.hs
Mate/Utilities.hs
Mate/X86CodeGen.hs
ffi/trap.c
tests/Instance1.java
tests/Instance2.java [new file with mode: 0644]

index 39300895ea245d08b303a8129d768184d5f3c2bf..3c004ec808a9f4e9ecdacd7b0094ffc42a6b42e3 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -50,6 +50,8 @@ test: mate $(CLASS_FILES)
        @printf "should be:  0x%08x\n" 0x1337
        ./$< tests/Instance1 | grep mainresult
        @printf "should be:  0x%08x 0x%08x\n" 0x55 0x11
+       ./$< tests/Instance2 | grep mainresult
+       @printf "should be:  0x%08x\n" 0x198
 
 %.class: %.java
        $(JAVAC) $<
index be4af60eaa80bc88bdd6de1c3bc717f153b10c62..44ff8acfa1bb19921b93c95647c0012d92a02edb 100644 (file)
@@ -3,9 +3,11 @@
 module Mate.ClassPool (
   getClassInfo,
   getClassFile,
-  getFieldAddr
+  getFieldOffset,
+  getStaticFieldAddr
   ) where
 
+import Data.Int
 import qualified Data.Map as M
 import qualified Data.Set as S
 import qualified Data.ByteString.Lazy as B
@@ -42,14 +44,14 @@ getStaticFieldOffset path field = do
   ci <- getClassInfo path
   return $ fromIntegral $ (clStaticMap ci) M.! field
 
-getFieldOffset :: B.ByteString -> B.ByteString -> IO (CUInt)
+getFieldOffset :: B.ByteString -> B.ByteString -> IO (Int32)
 getFieldOffset path field = do
   ci <- getClassInfo path
-  return $ fromIntegral $ (clFieldMap ci) M.! field
+  return $ (clFieldMap ci) M.! field
 
-foreign export ccall getFieldAddr :: CUInt -> Ptr () -> IO CUInt
-getFieldAddr :: CUInt -> Ptr () -> IO CUInt
-getFieldAddr from ptr_trapmap = do
+foreign export ccall getStaticFieldAddr :: CUInt -> Ptr () -> IO CUInt
+getStaticFieldAddr :: CUInt -> Ptr () -> IO CUInt
+getStaticFieldAddr from ptr_trapmap = do
   trapmap <- ptr2tmap ptr_trapmap
   let w32_from = fromIntegral from
   let sfi = trapmap M.! w32_from
@@ -93,8 +95,10 @@ calculateFields cf superclass = do
     -- new fields "overwrite" old ones, if they have the same name
     let staticmap = (M.fromList sm) `M.union` sc_sm
 
-    let im = zipbase 0 ifields
     let sc_im = getsupermap clFieldMap
+    -- TODO(bernhard): not efficient :-(
+    let max_off = if (M.size sc_im) > 0 then maximum $ M.elems sc_im else 0
+    let im = zipbase (max_off + 4) ifields
     -- new fields "overwrite" old ones, if they have the same name
     let fieldmap = (M.fromList im) `M.union` sc_im
 
index 2d755ccf4c3385f6ceeec382e184c99ce6abafb2..7a75466e9af87e8c8f1ee0b7051198779e3c7efc 100644 (file)
@@ -24,8 +24,12 @@ buildMethodID cls idx = MethodInfo (ntName nt) rc (ntSignature nt)
   where
   (CMethod rc nt) = (constsPool cls) M.! idx
 
-buildFieldID :: Class Resolved -> Word16 -> StaticFieldInfo
-buildFieldID cls idx = StaticFieldInfo rc (ntName fnt)
+buildStaticFieldID :: Class Resolved -> Word16 -> StaticFieldInfo
+buildStaticFieldID cls idx = StaticFieldInfo rc (ntName fnt)
+  where (CField rc fnt) = (constsPool cls) M.! idx
+
+buildFieldOffset :: Class Resolved -> Word16 -> (B.ByteString, B.ByteString)
+buildFieldOffset cls idx = (thisClass cls, ntName fnt)
   where (CField rc fnt) = (constsPool cls) M.! idx
 
 methodGetArgsCount :: Class Resolved -> Word16 -> Word32
index 3f8e6f4f7ad963f1d1283d197856dd89cda857be..57ffdff6ef9f77dc5d807efa186b53120603ae1b 100644 (file)
@@ -188,12 +188,12 @@ emitFromBB method cls hmap =  do
         pop eax
         trapaddr <- getCurrentOffset
         mov (Addr 0x00000000) eax -- it's a trap
-        return $ Just $ (trapaddr, SFI $ buildFieldID cls cpidx)
+        return $ Just $ (trapaddr, SFI $ buildStaticFieldID cls cpidx)
     emit' (GETSTATIC cpidx) = do
         trapaddr <- getCurrentOffset
         mov eax (Addr 0x00000000) -- it's a trap
         push eax
-        return $ Just $ (trapaddr, SFI $ buildFieldID cls cpidx)
+        return $ Just $ (trapaddr, SFI $ buildStaticFieldID cls cpidx)
     emit' insn = emit insn >> return Nothing
 
     emit :: J.Instruction -> CodeGen e s ()
@@ -240,11 +240,15 @@ emitFromBB method cls hmap =  do
 
     emit (GETFIELD x) = do
         pop eax -- this pointer
-        push (Disp (fromIntegral x * 4), eax) -- get field
+        let (cname, fname) = buildFieldOffset cls x
+        let offset = unsafePerformIO $ getFieldOffset cname fname
+        push (Disp (fromIntegral $ offset * 4), eax) -- get field
     emit (PUTFIELD x) = do
         pop ebx -- value to write
         pop eax -- this pointer
-        mov (Disp (fromIntegral x * 4), eax) ebx -- set field
+        let (cname, fname) = buildFieldOffset cls x
+        let offset = unsafePerformIO $ getFieldOffset cname fname
+        mov (Disp (fromIntegral $ offset * 4), eax) ebx -- set field
 
     emit IADD = do pop ebx; pop eax; add eax ebx; push eax
     emit ISUB = do pop ebx; pop eax; sub eax ebx; push eax
index 367171061b8641515dfaabb981d3871708e31af4..a2af9708299ce884c30d1fb70d8220842c9c6453 100644 (file)
@@ -17,7 +17,7 @@
 #include <asm/ucontext.h>
 
 unsigned int getMethodEntry(unsigned int, void *, void *);
-unsigned int getFieldAddr(unsigned int, void*);
+unsigned int getStaticFieldAddr(unsigned int, void*);
 
 #define NEW_MAP(prefix) \
        void* prefix ## _map = NULL; \
@@ -74,7 +74,7 @@ void staticfieldtrap(int nSignal, siginfo_t *info, void *ctx)
                printf("staticfieldtrap: something is wrong here. abort\n");
                exit(0);
        }
-       unsigned int patchme = getFieldAddr(from, trap_map);
+       unsigned int patchme = getStaticFieldAddr(from, trap_map);
 
        printf(" to_patch: 0x%08x\n", (unsigned int) to_patch);
        printf("*to_patch: 0x%08x\n", *to_patch);
index c9a90f9f49b355068ca629103594b7eb411bf508..e15505e1c554c9687d2cf8115e30ff73c585dcbf 100644 (file)
@@ -15,6 +15,7 @@ public class Instance1 {
        }
 
        public static int id(int a) {
+               // System.out.printf("0x%08x\n", a);
                return a;
        }
 }
diff --git a/tests/Instance2.java b/tests/Instance2.java
new file mode 100644 (file)
index 0000000..6f25480
--- /dev/null
@@ -0,0 +1,23 @@
+package tests;
+
+public class Instance2 extends Instance1 {
+       public int y;
+
+       public Instance2() {
+               x = 0x66;
+               y = 0x77;
+       }
+
+       public static void main(String []args) {
+               int sum = 0;
+               Instance1 a = new Instance1();
+               Instance2 b = new Instance2();
+               sum += a.x; // 0x55
+               sum += b.x; // 0x66
+               sum += b.y; // 0x77
+               a.x = 0x11; sum += a.x; // 0x11
+               b.x = 0x22; sum += b.x; // 0x22
+               b.y = 0x33; sum += b.y; // 0x33
+               Instance1.id(sum); // 0x198
+       }
+}