[m-rev.] diff: module initialisers/finalisers for java

Peter Wang novalazy at gmail.com
Mon Jun 22 13:32:01 AEST 2009


Branches: main

Make `:- initialise' and `:- finalise' declarations work in Java grades.
Initialisation predicates are simply called from static initialisation blocks.
Finalisation predicates work by registering methods (objects) with the
JavaInternal runtime class.  After main/2 terminates each of the registered
methods is called.

compiler/make_hlds_passes.m:
        Make add_pass_3_initialise, add_pass_3_finalise generate predicates
        for backends other than C.

compiler/mlds_to_java.m:
        Generate code to register finalisation predicates with the runtime.

        Make the generated code that calls main/2 call run the registered
        finalisers as well.

java/runtime/JavaInternal.java:
        Add code to register and call finalisers when main/2 terminates.

diff --git a/compiler/make_hlds_passes.m b/compiler/make_hlds_passes.m
index fd5a4a0..0da853c 100644
--- a/compiler/make_hlds_passes.m
+++ b/compiler/make_hlds_passes.m
@@ -1338,7 +1338,9 @@ add_pass_3_initialise(ItemInitialise, Status,
!ModuleInfo, !QualInfo,
             pred_info_get_arg_types(PredInfo, ArgTypes),
             pred_info_get_procedures(PredInfo, ProcTable),
             ProcInfos = map.values(ProcTable),
-            ExportLang = lang_c,
+            module_info_get_globals(!.ModuleInfo, Globals),
+            globals.get_target(Globals, CompilationTarget),
+            ExportLang = target_lang_to_foreign_export_lang(CompilationTarget),
             (
                 ArgTypes = [Arg1Type, Arg2Type],
                 type_is_io_state(Arg1Type),
@@ -1502,9 +1504,9 @@ add_pass_3_finalise(ItemFinalise, Status,
!ModuleInfo, !QualInfo, !Specs) :-
             pred_info_get_arg_types(PredInfo, ArgTypes),
             pred_info_get_procedures(PredInfo, ProcTable),
             ProcInfos = map.values(ProcTable),
-            % XXX We currently only support finalise declarations for the C
-            % and Erlang backends.
-            ExportLang = lang_c,
+            module_info_get_globals(!.ModuleInfo, Globals),
+            globals.get_target(Globals, CompilationTarget),
+            ExportLang = target_lang_to_foreign_export_lang(CompilationTarget),
             (
                 ArgTypes = [Arg1Type, Arg2Type],
                 type_is_io_state(Arg1Type),
@@ -1586,6 +1588,27 @@ add_pass_3_finalise(ItemFinalise, Status,
!ModuleInfo, !QualInfo, !Specs) :-
         !:Specs = [Spec | !.Specs]
     ).

+:- func target_lang_to_foreign_export_lang(compilation_target)
+    = foreign_language.
+
+target_lang_to_foreign_export_lang(CompilationTarget) = ExportLang :-
+    (
+        ( CompilationTarget = target_c
+        ; CompilationTarget = target_asm
+        ; CompilationTarget = target_x86_64
+        ),
+        ExportLang = lang_c
+    ;
+        CompilationTarget = target_erlang,
+        ExportLang = lang_erlang
+    ;
+        CompilationTarget = target_il,
+        ExportLang = lang_il
+    ;
+        CompilationTarget = target_java,
+        ExportLang = lang_java
+    ).
+
 :- pred add_pass_3_mutable(item_mutable_info::in,
     import_status::in, module_info::in, module_info::out,
     qual_info::in, qual_info::out,
diff --git a/compiler/mlds_to_java.m b/compiler/mlds_to_java.m
index 64b5a51..0f67bec 100644
--- a/compiler/mlds_to_java.m
+++ b/compiler/mlds_to_java.m
@@ -315,7 +315,7 @@ output_import(Import, !IO) :-
 output_java_src_file(ModuleInfo, Indent, MLDS, !IO) :-
     % Run further transformations on the MLDS.
     MLDS = mlds(ModuleName, AllForeignCode, Imports, Defns0,
-        InitPreds, _FinalPreds, ExportedEnums),
+        InitPreds, FinalPreds, ExportedEnums),

     % Do NOT enforce the outermost "mercury" qualifier here.  This module
     % name is compared with other module names in the MLDS, to avoid
@@ -364,6 +364,8 @@ output_java_src_file(ModuleInfo, Indent, MLDS, !IO) :-
     output_exported_enums(Indent + 1, ModuleInfo, ExportedEnums, !IO),
     io.write_string("\n// InitPreds\n", !IO),
     output_inits(Indent + 1, ModuleInfo, InitPreds, !IO),
+    io.write_string("\n// FinalPreds\n", !IO),
+    output_finals(Indent + 1, ModuleInfo, FinalPreds, !IO),
     io.write_string("\n// EnvVarNames\n", !IO),
     output_env_vars(Indent + 1, NonRttiDefns, !IO),
     output_src_end(Indent, ModuleName, !IO).
@@ -1034,6 +1036,46 @@ output_init_2(Indent, InitPred, !IO) :-

 %-----------------------------------------------------------------------------%
 %
+% Code to output module finalisers.
+%
+
+:- pred output_finals(indent::in, module_info::in, list(string)::in,
+    io::di, io::uo) is det.
+
+output_finals(Indent, _ModuleInfo, FinalPreds, !IO) :-
+    (
+        FinalPreds = []
+    ;
+        FinalPreds = [_ | _],
+        indent_line(Indent, !IO),
+        io.write_string("static {\n", !IO),
+        indent_line(Indent + 1, !IO),
+        io.write_string("jmercury.runtime.JavaInternal.register_finaliser(\n",
+            !IO),
+        indent_line(Indent + 2, !IO),
+        io.write_string("new java.lang.Runnable() {\n", !IO),
+        indent_line(Indent + 3, !IO),
+        io.write_string("public void run() {\n", !IO),
+        list.foldl(output_final_pred_call(Indent + 4), FinalPreds, !IO),
+        indent_line(Indent + 3, !IO),
+        io.write_string("}\n", !IO),
+        indent_line(Indent + 2, !IO),
+        io.write_string("}\n", !IO),
+        indent_line(Indent + 1, !IO),
+        io.write_string(");\n", !IO),
+        indent_line(Indent, !IO),
+        io.write_string("}\n", !IO)
+    ).
+
+:- pred output_final_pred_call(indent::in, string::in, io::di, io::uo) is det.
+
+output_final_pred_call(Indent, FinalPred, !IO) :-
+    indent_line(Indent, !IO),
+    io.write_string(FinalPred, !IO),
+    io.write_string("();\n", !IO).
+
+%-----------------------------------------------------------------------------%
+%
 % Code to output globals for environment variables.
 %

@@ -1138,6 +1180,9 @@ maybe_write_main_driver(Indent, ClassName, Defns, !IO) :-
         io.write_string(ClassName, !IO),
         io.write_string(".main_2_p_0();\n", !IO),
         indent_line(Indent + 1, !IO),
+        io.write_string("jmercury.runtime.JavaInternal.run_finalisers();\n",
+            !IO),
+        indent_line(Indent + 1, !IO),
         io.write_string("java.lang.System.exit", !IO),
         io.write_string("(jmercury.runtime.JavaInternal.exit_status);", !IO),
         io.nl(!IO),
diff --git a/java/runtime/JavaInternal.java b/java/runtime/JavaInternal.java
index 9c4aa1e..8434290 100644
--- a/java/runtime/JavaInternal.java
+++ b/java/runtime/JavaInternal.java
@@ -1,5 +1,5 @@
 //
-// Copyright (C) 2001-2003 The University of Melbourne.
+// Copyright (C) 2001-2003, 2009 The University of Melbourne.
 // This file may only be copied under the terms of the GNU Library General
 // Public License - see the file COPYING.LIB in the Mercury distribution.
 //
@@ -20,4 +20,17 @@ public class JavaInternal {
 	public static java.lang.String		progname;
 	public static java.lang.String[]	args;
 	public static int			exit_status;
+
+        private static java.util.List<Runnable> finalisers
+		= new java.util.ArrayList();
+
+	public static void register_finaliser(Runnable hook) {
+		finalisers.add(hook);
+	}
+
+	public static void run_finalisers() {
+		for (Runnable r : finalisers) {
+			r.run();
+		}
+	}
 }
--------------------------------------------------------------------------
mercury-reviews mailing list
Post messages to:       mercury-reviews at csse.unimelb.edu.au
Administrative Queries: owner-mercury-reviews at csse.unimelb.edu.au
Subscriptions:          mercury-reviews-request at csse.unimelb.edu.au
--------------------------------------------------------------------------



More information about the reviews mailing list