static initializer: execute it when loading the class file
authorBernhard Urban <lewurm@gmail.com>
Tue, 24 Apr 2012 15:55:55 +0000 (17:55 +0200)
committerBernhard Urban <lewurm@gmail.com>
Tue, 24 Apr 2012 15:55:55 +0000 (17:55 +0200)
unfortunately, we have a circle dependency now, hence the file
`Mate/MethodPool.hs-boot'.

.gitignore
Makefile
Mate/ClassPool.hs
Mate/MethodPool.hs
Mate/MethodPool.hs-boot [new file with mode: 0644]
tests/Static6.java [new file with mode: 0644]
tests/Static7.java [new file with mode: 0644]
tests/Static8.java [new file with mode: 0644]

index 9bca9cd415139ace7d647cdacbae4607ee2b943c..e57f06e466b5d17dd9cc07015e44cd87da6a5f0a 100644 (file)
@@ -6,3 +6,5 @@ tags
 *.swp
 *_stub.c
 *_stub.h
+*.hi-boot
+*.o-boot
index 74652f5cac55276a79e7beb7db0c38dedd20af14..bbfd256928eb30e87f552a8f30adcbe6a7c52a77 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -4,6 +4,7 @@ JAVAC := javac
 JAVA_FILES := $(wildcard tests/*.java)
 CLASS_FILES := $(JAVA_FILES:.java=.class)
 HS_FILES := $(wildcard Mate/*.hs)
+HS_BOOT := $(wildcard Mate/*.hs-boot)
 O_FILES = $(shell ls Mate/*.o) $(wildcard ffi/*.o)
 PACKAGES_ := bytestring harpy hs-java
 PACKAGES := $(addprefix -package ,$(PACKAGES_))
@@ -37,6 +38,12 @@ test: mate $(CLASS_FILES)
        @printf "should be:  0x%08x 0x%08x\n" 0x33 0x77
        ./$< tests/Static5 | grep mainresult
        @printf "should be:  0x%08x 0x%08x\n" 0x33 0x33
+       ./$< tests/Static6 | grep mainresult
+       @printf "should be:  0x%08x\n" 0x33
+       ./$< tests/Static7 | grep mainresult
+       @printf "should be:  0x%08x\n" $$((0x1337 + 0x555))
+       ./$< tests/Static8 | grep mainresult
+       @printf "should be:  0x%08x 0x%08x\n" 0x33 $$((0x1337 + 0x555))
        ./$< tests/CallConv1 | grep mainresult
        @printf "should be:  0x%08x\n" 0x1337
        ./$< tests/CallConv2 | grep mainresult
@@ -48,11 +55,11 @@ test: mate $(CLASS_FILES)
 ffi/native.o: ffi/native.c
        ghc -Wall -O2 -c $< -o $@
 
-mate: Mate.hs ffi/trap.c $(HS_FILES) ffi/native.o
+mate: Mate.hs ffi/trap.c $(HS_FILES) $(HS_BOOT) ffi/native.o
        ghc --make $(GHC_OPT) Mate.hs ffi/trap.c -o $@ $(GHC_LD)
 
 clean:
-       rm -f {Mate/,}*.hi {Mate/,ffi/,}*.o mate tests/*.class
+       rm -f {Mate/,}*.hi {Mate/,ffi/,}*.o Mate/*.{hi,o}-boot mate tests/*.class
 
 ghci: mate
        ghci $(PACKAGES) $(O_FILES) Mate.hs $(GHC_LD)
index b1618edda9c3dac1ff955ba91d790626de3b4cdb..0a4d35781b020ef7e565bd8b4c540aa151a2a9e2 100644 (file)
@@ -15,7 +15,10 @@ import Foreign.Marshal.Alloc
 import JVM.ClassFile
 import JVM.Converter
 
+import Mate.BasicBlocks
+import {-# SOURCE #-} Mate.MethodPool
 import Mate.Types
+import Mate.Utilities
 
 getClassInfo :: B.ByteString -> IO ClassInfo
 getClassInfo path = do
@@ -76,4 +79,19 @@ loadClass path = do
   let new_ci = ClassInfo path cfile fieldbase fieldmap
   let class_map' = M.insert path new_ci class_map
   classmap2ptr class_map' >>= set_classmap
-  return new_ci
+  -- execute class initializer
+  case lookupMethod "<clinit>" cfile of
+    Just m -> do
+      hmap <- parseMethod cfile "<clinit>"
+      printMapBB hmap
+      case hmap of
+        Just hmap' -> do
+          let mi = (MethodInfo "<clinit>" path (methodSignature m))
+          entry <- compileBB hmap' mi
+          addMethodRef entry mi [path]
+          printf "executing static initializer from %s now\n" (toString path)
+          executeFuncPtr entry
+          printf "static initializer from %s done\n" (toString path)
+          return new_ci
+        Nothing -> error $ "loadClass: static initializer not found (WTF?). abort"
+    Nothing -> return new_ci
index 811d1fb7cc678d084fb9d62d1dbf395dbf27b755..9c3c7275f3a197c5330d775a20d961bbe17e64a3 100644 (file)
@@ -118,9 +118,9 @@ initMethodPool = do
 
 
 addMethodRef :: Word32 -> MethodInfo -> [B.ByteString] -> IO ()
-addMethodRef entry mi@(MethodInfo mname _ msig) clsnames = do
+addMethodRef entry (MethodInfo mmname _ msig) clsnames = do
   mmap <- get_methodmap >>= ptr2mmap
-  let newmap = M.fromList $ map (\x -> ((MethodInfo mname x msig), entry)) clsnames
+  let newmap = M.fromList $ map (\x -> ((MethodInfo mmname x msig), entry)) clsnames
   let mmap' = newmap `M.union` newmap
   mmap2ptr mmap' >>= set_methodmap
 
diff --git a/Mate/MethodPool.hs-boot b/Mate/MethodPool.hs-boot
new file mode 100644 (file)
index 0000000..f17cfb4
--- /dev/null
@@ -0,0 +1,13 @@
+{-# LANGUAGE OverloadedStrings #-}
+{-# LANGUAGE ForeignFunctionInterface #-}
+module Mate.MethodPool where
+
+import Data.Binary
+import qualified Data.ByteString.Lazy as B
+
+import Mate.Types
+
+
+addMethodRef :: Word32 -> MethodInfo -> [B.ByteString] -> IO ()
+compileBB :: MapBB -> MethodInfo -> IO Word32
+executeFuncPtr :: Word32 -> IO ()
diff --git a/tests/Static6.java b/tests/Static6.java
new file mode 100644 (file)
index 0000000..49913ad
--- /dev/null
@@ -0,0 +1,19 @@
+package tests;
+
+public class Static6 {
+       public static int x;
+       public static int y;
+
+       static {
+               Static6.x = 0x11;
+               Static6.y = 0x22;
+       }
+
+       public static void main(String []args) {
+               addNumbers(); // 0x33
+       }
+
+       public static int addNumbers() {
+               return Static6.x + Static6.y;
+       }
+}
diff --git a/tests/Static7.java b/tests/Static7.java
new file mode 100644 (file)
index 0000000..d587e08
--- /dev/null
@@ -0,0 +1,16 @@
+package tests;
+
+public class Static7 extends Static6 {
+       public static int x;
+       public static int y;
+
+       static {
+               Static6.x = 0x1337;
+               Static6.y = 0x555;
+       }
+
+       public static void main(String []args) {
+               addNumbers(); // 0x188c
+               // System.out.printf("%x\n", addNumbers());
+       }
+}
diff --git a/tests/Static8.java b/tests/Static8.java
new file mode 100644 (file)
index 0000000..1359642
--- /dev/null
@@ -0,0 +1,32 @@
+package tests;
+
+public class Static8 extends Static8_local {
+       public static int x;
+       public static int y;
+
+       static {
+               Static8_local.x = 0x1337;
+               Static8_local.y = 0x555;
+       }
+
+       public static void main(String []args) {
+               Static8.addNumbers(); // 0x188c
+               // System.out.printf("%x\n", Static8.addNumbers());
+       }
+}
+
+class Static8_local {
+       public static int x;
+       public static int y;
+
+       static {
+               Static8_local.x = 0x11;
+               Static8_local.y = 0x22;
+               Static8_local.addNumbers(); // 0x33
+               // System.out.printf("%x\n", addNumbers());
+       }
+
+       public static int addNumbers() {
+               return Static8_local.x + Static8_local.y;
+       }
+}