strings: put every String from the constantpool in a Map
authorBernhard Urban <lewurm@gmail.com>
Thu, 26 Apr 2012 08:39:10 +0000 (10:39 +0200)
committerBernhard Urban <lewurm@gmail.com>
Thu, 26 Apr 2012 09:42:01 +0000 (11:42 +0200)
because the spec requires that every constant string
has the same address.

w0000t @ "Hello World" :-)

Makefile
Mate/MethodPool.hs
Mate/Strings.hs [new file with mode: 0644]
Mate/Types.hs
Mate/X86CodeGen.hs
ffi/native.c
ffi/trap.c
tests/Native3.java [new file with mode: 0644]

index 2b4182d46c57c28e13e35a28701e2d9884639e1d..57f77e22d94bfed98ea4d0633fc7522559283fc2 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -60,6 +60,8 @@ test: mate $(CLASS_FILES)
        @printf "should be:  0x%08x 0x%08x\n" 0x1337 0x1337
        ./$< tests/Native2 | grep "printstream"
        @printf "should be:   0x%08x\n" 0x1337
+       ./$< tests/Native2 | grep "Hello World"
+       @printf "should be: %s" "Hello World"
 
 %.class: %.java
        $(JAVAC) $<
index e1eb1214323e989ec09f944a9d6bf0252391d119..0e146a103031c214997b81950efc5e22917017ba 100644 (file)
@@ -65,7 +65,8 @@ getMethodEntry signal_from methodtable = do
                     return $ fromIntegral entry
                   Nothing -> error $ (show method) ++ " not found. abort"
               True -> do
-                let symbol = (replace "/" "_" $ toString cm) ++ "__" ++ (toString method) ++ "__" ++ (replace "(" "_" (replace ")" "_" $ toString $ encode sig))
+                -- TODO(bernhard): cleaner please... *do'h*
+                let symbol = (replace "/" "_" $ toString cm) ++ "__" ++ (toString method) ++ "__" ++ (replace ";" "_" $ replace "/" "_" $ replace "(" "_" (replace ")" "_" $ toString $ encode sig))
                 printf "native-call: symbol: %s\n" symbol
                 nf <- loadNativeFunction symbol
                 let w32_nf = fromIntegral nf
@@ -120,6 +121,7 @@ initMethodPool = do
   tmap2ptr M.empty >>= set_trapmap
   classmap2ptr M.empty >>= set_classmap
   virtualmap2ptr M.empty >>= set_virtualmap
+  stringsmap2ptr M.empty >>= set_stringsmap
 
 
 addMethodRef :: Word32 -> MethodInfo -> [B.ByteString] -> IO ()
diff --git a/Mate/Strings.hs b/Mate/Strings.hs
new file mode 100644 (file)
index 0000000..2867bad
--- /dev/null
@@ -0,0 +1,41 @@
+{-# LANGUAGE OverloadedStrings #-}
+{-# LANGUAGE ForeignFunctionInterface #-}
+module Mate.Strings (
+  getUniqueStringAddr
+  ) where
+
+import Data.Word
+import qualified Data.Map as M
+import qualified Data.ByteString.Lazy as B
+import qualified Data.ByteString.Internal as BI
+import Text.Printf
+
+import Foreign.Ptr
+import Foreign.ForeignPtr
+import Foreign.Marshal.Array
+
+import Mate.Types
+
+
+getUniqueStringAddr :: B.ByteString -> IO Word32
+getUniqueStringAddr str = do
+  smap <- get_stringsmap >>= ptr2stringsmap
+  case M.lookup str smap of
+    Nothing -> do
+      addr <- allocateJavaString str
+      let smap' = M.insert str addr smap
+      stringsmap2ptr smap' >>= set_stringsmap
+      return addr
+    Just addr -> return addr
+
+-- TOOD(bernhard): quite hackish
+allocateJavaString :: B.ByteString -> IO Word32
+allocateJavaString str = do
+  let strlen = fromIntegral $ B.length str
+  let str_unpacked = (map fromIntegral $ B.unpack str) :: [Word8]
+  arr <- newArray str_unpacked
+  newstr <- BI.create strlen (\x -> BI.memcpy x arr (fromIntegral strlen))
+  let (newstrptr, _, _) = BI.toForeignPtr newstr
+  let w32_ptr = fromIntegral $ ptrToIntPtr $ unsafeForeignPtrToPtr newstrptr
+  printf "new str ptr: 0x%08x\n" w32_ptr
+  return w32_ptr
index 8977143ca1e2b540860e780fe14d17dc86a0518c..7f193251302a288c57d84fe967a4be606c29c60e 100644 (file)
@@ -49,6 +49,10 @@ type ClassMap = M.Map B.ByteString ClassInfo
 
 type FieldMap = M.Map B.ByteString Int32
 
+-- java strings are allocated once, therefore we
+-- use a hashmap to store the address for a String
+type StringsMap = M.Map B.ByteString Word32
+
 -- map "methodtable addr" to "classname"
 -- we need that to identify the actual type
 -- on the invokevirtual insn
@@ -123,6 +127,12 @@ foreign import ccall "get_virtualmap"
 foreign import ccall "set_virtualmap"
   set_virtualmap :: Ptr () -> IO ()
 
+foreign import ccall "get_stringsmap"
+  get_stringsmap :: IO (Ptr ())
+
+foreign import ccall "set_stringsmap"
+  set_stringsmap :: Ptr () -> IO ()
+
 -- TODO(bernhard): make some typeclass magic 'n stuff
 mmap2ptr :: MMap -> IO (Ptr ())
 mmap2ptr mmap = do
@@ -155,3 +165,12 @@ virtualmap2ptr cmap = do
 
 ptr2virtualmap :: Ptr () -> IO VirtualMap
 ptr2virtualmap vmap = deRefStablePtr $ ((castPtrToStablePtr vmap) :: StablePtr cmap)
+
+
+stringsmap2ptr :: StringsMap -> IO (Ptr ())
+stringsmap2ptr cmap = do
+  ptr_cmap <- newStablePtr cmap
+  return $ castStablePtrToPtr ptr_cmap
+
+ptr2stringsmap :: Ptr () -> IO StringsMap
+ptr2stringsmap vmap = deRefStablePtr $ ((castPtrToStablePtr vmap) :: StablePtr cmap)
index 2db7a979a0ad5730748325ccdca3b4ad3a1b7ba9..15616f59007fbadab8693327488b13dcb16c5092 100644 (file)
@@ -26,6 +26,8 @@ import Mate.BasicBlocks
 import Mate.Types
 import Mate.Utilities
 import Mate.ClassPool
+import Mate.Strings
+
 
 foreign import ccall "dynamic"
    code_int :: FunPtr (CInt -> CInt -> IO CInt) -> (CInt -> CInt -> IO CInt)
@@ -268,6 +270,12 @@ emitFromBB method cls hmap =  do
         pop eax
         mov (Disp (cArgs x), ebp) eax
 
+    emit (LDC1 x) = emit (LDC2 $ fromIntegral x)
+    emit (LDC2 x) = do
+        let value = case (constsPool cls) M.! x of
+                      (CString s) -> unsafePerformIO $ getUniqueStringAddr s
+                      _ -> error $ "LDCI... missing impl."
+        push value
     emit (GETFIELD x) = do
         pop eax -- this pointer
         let (cname, fname) = buildFieldOffset cls x
index 25c159adef1b840672eb888f2e93833a30e81c3b..a9aa2277ce021f5295dff0846775a2262a7637b8 100644 (file)
@@ -19,3 +19,8 @@ void java_io_PrintStream__printf___I_V(int a)
 {
        printf("printstream: 0x%08x\n", a);
 }
+
+void java_io_PrintStream__println___Ljava_lang_String__V(const char *a)
+{
+       printf("%s\n", a);
+}
index 9d70492cb2b292eb12f7c7935acd62655f478a65..7871757811bf71128f1c29a814002cf3f8bf21f1 100644 (file)
@@ -39,6 +39,7 @@ NEW_MAP(method)
 NEW_MAP(trap)
 NEW_MAP(class)
 NEW_MAP(virtual)
+NEW_MAP(strings)
 
 
 void mainresult(unsigned int a)
diff --git a/tests/Native3.java b/tests/Native3.java
new file mode 100644 (file)
index 0000000..60916e6
--- /dev/null
@@ -0,0 +1,7 @@
+package tests;
+
+public class Native3 {
+       public static void main(String []args) {
+               System.out.println("Hello World");
+       }
+}