[m-rev.] diff: support thread-local mutables on java

Peter Wang novalazy at gmail.com
Wed Sep 2 17:12:57 AEST 2009


Branches: main

compiler/make_hlds_passes.m:
        Support `thread_local' mutables on Java backend.

        Add some newlines in generated code for mutables.

compiler/prog_mutable.m:
        Update documentation.

java/runtime/JavaInternal.java:
        Avoid a warning.

diff --git a/compiler/make_hlds_passes.m b/compiler/make_hlds_passes.m
index 1a84c3d..73b22d2 100644
--- a/compiler/make_hlds_passes.m
+++ b/compiler/make_hlds_passes.m
@@ -1665,8 +1665,9 @@ add_pass_3_mutable(ItemMutable, Status,
!ModuleInfo, !QualInfo, !Specs) :-

             % Add foreign_code item that defines the global variable used to
             % implement the mutable.
+            IsThreadLocal = mutable_var_thread_local(MutAttrs),
             add_java_mutable_defn(TargetMutableName, Type, IsConstant,
-                Context, !ModuleInfo, !QualInfo, !Specs),
+                IsThreadLocal, Context, !ModuleInfo, !QualInfo, !Specs),

             % Add all the predicates related to mutables.
             add_java_mutable_preds(ItemMutable, TargetMutableName,
@@ -1940,7 +1941,7 @@
add_c_java_constant_mutable_access_preds(TargetMutableName,
         [pragma_var(X, "X", out_mode(Inst), BoxPolicy)],
         ProgVarSet,
         InstVarSet,
-        fc_impl_ordinary("X = " ++ TargetMutableName ++ ";", yes(Context))
+        fc_impl_ordinary("X = " ++ TargetMutableName ++ ";\n", yes(Context))
     ),
     ConstantGetItemPragma = item_pragma_info(compiler(mutable_decl),
         ConstantGetForeignProc, Context, -1),
@@ -1956,7 +1957,7 @@
add_c_java_constant_mutable_access_preds(TargetMutableName,
         [pragma_var(X, "X", in_mode(Inst), BoxPolicy)],
         ProgVarSet,
         InstVarSet,
-        fc_impl_ordinary(TargetMutableName ++ " = X;", yes(Context))
+        fc_impl_ordinary(TargetMutableName ++ " = X;\n", yes(Context))
     ),
     ConstantSetItemPragma = item_pragma_info(compiler(mutable_decl),
         ConstantSetForeignProc, Context, -1),
@@ -2044,11 +2045,11 @@
add_c_mutable_primitive_preds(TargetMutableName, ModuleName,
MutableName,
     varset.new_named_var(varset.init, "X", X, ProgVarSet),
     (
         IsThreadLocal = mutable_not_thread_local,
-        UnsafeGetCode = "X = " ++ TargetMutableName ++ ";"
+        UnsafeGetCode = "X = " ++ TargetMutableName ++ ";\n"
     ;
         IsThreadLocal = mutable_thread_local,
         UnsafeGetCode = "MR_get_thread_local_mutable(" ++
-            TypeName ++ ", X, " ++ TargetMutableName ++ ");"
+            TypeName ++ ", X, " ++ TargetMutableName ++ ");\n"
     ),
     UnsafeGetForeignProc = pragma_foreign_proc(UnsafeGetAttrs,
         mutable_unsafe_get_pred_sym_name(ModuleName, MutableName),
@@ -2095,11 +2096,11 @@
add_c_mutable_primitive_preds(TargetMutableName, ModuleName,
MutableName,
     ),
     (
         IsThreadLocal = mutable_not_thread_local,
-        SetCode = TargetMutableName ++ "= X;"
+        SetCode = TargetMutableName ++ " = X;\n"
     ;
         IsThreadLocal = mutable_thread_local,
         SetCode = "MR_set_thread_local_mutable(" ++
-            TypeName ++ ", X, " ++ TargetMutableName ++ ");"
+            TypeName ++ ", X, " ++ TargetMutableName ++ ");\n"
     ),
     UnsafeSetForeignProc = pragma_foreign_proc(UnsafeSetAttrs,
         mutable_unsafe_set_pred_sym_name(ModuleName, MutableName),
@@ -2297,37 +2298,48 @@ add_c_mutable_initialisation(IsConstant,
IsThreadLocal, TargetMutableName,
     % mutable.
     %
 :- pred add_java_mutable_defn(string::in, mer_type::in, bool::in,
-    prog_context::in, module_info::in, module_info::out,
-    qual_info::in, qual_info::out, list(error_spec)::in, list(error_spec)::out)
-    is det.
+    mutable_thread_local::in, prog_context::in,
+    module_info::in, module_info::out, qual_info::in, qual_info::out,
+    list(error_spec)::in, list(error_spec)::out) is det.

-add_java_mutable_defn(TargetMutableName, Type, IsConstant,
+add_java_mutable_defn(TargetMutableName, Type, IsConstant, IsThreadLocal,
         Context, !ModuleInfo, !QualInfo, !Specs) :-
     get_java_mutable_global_foreign_defn(!.ModuleInfo, Type,
-        TargetMutableName, IsConstant, Context, ForeignDefn),
+        TargetMutableName, IsConstant, IsThreadLocal, Context, ForeignDefn),
     ItemStatus0 = item_status(status_local, may_be_unqualified),
     add_item_decl_pass_2(ForeignDefn, ItemStatus0, _, !ModuleInfo, !Specs).

 :- pred get_java_mutable_global_foreign_defn(module_info::in, mer_type::in,
-    string::in, bool::in, prog_context::in, item::out) is det.
+    string::in, bool::in, mutable_thread_local::in, prog_context::in,
+    item::out) is det.

 get_java_mutable_global_foreign_defn(_ModuleInfo, _Type, TargetMutableName,
-        IsConstant, Context, DefnItem) :-
+        IsConstant, IsThreadLocal, Context, DefnItem) :-
     MutableMutexVarName = mutable_mutex_var_name(TargetMutableName),

-    % Constant mutables do not require mutexes as their values are never
-    % updated.
+    (
+        IsThreadLocal = mutable_not_thread_local,
     (
         IsConstant = yes,
         LockDefn = []
     ;
         IsConstant = no,
         LockDefn = ["static final java.lang.Object ", MutableMutexVarName,
-            " = new Object();\n"]
+                " = new java.lang.Object();\n"]
     ),
-
     DefnBody = string.append_list([
-        "static java.lang.Object ", TargetMutableName, ";\n" | LockDefn]),
+            "static java.lang.Object ", TargetMutableName, ";\n" | LockDefn])
+    ;
+        IsThreadLocal = mutable_thread_local,
+        % Primitive type parameters are not allowed so we must used their boxed
+        % counterparts.
+        DefnBody = string.append_list([
+            "static java.lang.ThreadLocal<java.lang.Object> ",
+            TargetMutableName,
+            " = new java.lang.InheritableThreadLocal<java.lang.Object>();\n"
+        ])
+    ),
+
     DefnPragma = pragma_foreign_code(lang_java, DefnBody),
     DefnItemPragma = item_pragma_info(compiler(mutable_decl), DefnPragma,
         Context, -1),
@@ -2383,8 +2395,8 @@ add_java_mutable_preds(ItemMutable, TargetMutableName,
     % Add the foreign clauses for the mutable's primitive access and
     % locking predicates.
     %
-:- pred add_java_mutable_primitive_preds(string::in, module_name::in,
string::in,
-    mutable_var_attributes::in, pragma_foreign_proc_attributes::in,
+:- pred add_java_mutable_primitive_preds(string::in, module_name::in,
+    string::in, mutable_var_attributes::in, pragma_foreign_proc_attributes::in,
     mer_inst::in, box_policy::in,
     prog_context::in, import_status::in, import_status::out,
     module_info::in, module_info::out, qual_info::in, qual_info::out,
@@ -2393,15 +2405,23 @@ add_java_mutable_preds(ItemMutable, TargetMutableName,
 add_java_mutable_primitive_preds(TargetMutableName, ModuleName, MutableName,
         MutAttrs, Attrs, Inst, BoxPolicy,
         Context, !Status, !ModuleInfo, !QualInfo, !Specs) :-
+    IsThreadLocal = mutable_var_thread_local(MutAttrs),
+
     % Construct the semipure get predicate.

     set_purity(purity_semipure, Attrs, GetAttrs0),
     set_thread_safe(proc_thread_safe, GetAttrs0, GetAttrs),
     varset.new_named_var(varset.init, "X", X, ProgVarSet),
     MutableMutexVarName = mutable_mutex_var_name(TargetMutableName),
+    (
+        IsThreadLocal = mutable_not_thread_local,
     GetCode =
         "\tsynchronized (" ++ MutableMutexVarName ++ ") {\n" ++
-        "\t\tX = " ++ TargetMutableName ++ ";\n\t}\n",
+            "\t\tX = " ++ TargetMutableName ++ ";\n\t}\n"
+    ;
+        IsThreadLocal = mutable_thread_local,
+        GetCode = "\tX = " ++ TargetMutableName ++ ".get();\n"
+    ),
     GetForeignProc = pragma_foreign_proc(GetAttrs,
         mutable_unsafe_get_pred_sym_name(ModuleName, MutableName),
         pf_predicate,
@@ -2431,8 +2451,14 @@
add_java_mutable_primitive_preds(TargetMutableName, ModuleName,
MutableName,
         % This is just a dummy value.
         TrailCode = ""
     ),
+    (
+        IsThreadLocal = mutable_not_thread_local,
     SetCode = "\tsynchronized (" ++ MutableMutexVarName ++ ") {\n" ++
-        "\t\t" ++ TargetMutableName ++ "= X;\n\t}\n",
+            "\t\t" ++ TargetMutableName ++ " = X;\n\t}\n"
+    ;
+        IsThreadLocal = mutable_thread_local,
+        SetCode = "\t" ++ TargetMutableName ++ ".set(X);\n"
+    ),
     SetForeignProc = pragma_foreign_proc(SetAttrs,
         mutable_unsafe_set_pred_sym_name(ModuleName, MutableName),
         pf_predicate,
diff --git a/compiler/prog_mutable.m b/compiler/prog_mutable.m
index 9c96f5a..5d67513 100644
--- a/compiler/prog_mutable.m
+++ b/compiler/prog_mutable.m
@@ -222,7 +222,7 @@
 % ===>
 %
 %   :- pragma foreign_code("Java", "
-%       static <JavaType> mutable_<varname>;
+%       static java.lang.Object mutable_<varname>;
 %       static final java.lang.Object mutable_<varname>_lock = new Object();
 %   ").
 %
@@ -259,6 +259,35 @@
 %       }
 %   ").
 %
+% As mutable_<varname> has the type `java.lang.Object' a cast is required
+% after the code above, to cast X to the correct type.  This is handled by
+% the MLDS code generator.
+%
+% For thread-local mutables the transformation is as follows:
+%
+%   :- mutable(<varname>, <vartype>, <initvalue>, <varinst>, [attributes]).
+%
+% ===>
+%
+%   :- pragma foreign_code("Java", "
+%       static java.lang.ThreadLocal<java.lang.Object> mutable_<varname> =
+%           new java.lang.InheritableThreadLocal<java.lang.Object>();
+%   ").
+%
+%   :- pragma foreign_proc("Java",
+%       unsafe_set_<varname)(X::in(<varinst>)),
+%       [will_not_call_mercury, thread_safe],
+%   "
+%       mutable_<varname>.set(X);
+%   ").
+%
+%   :- pragma foreign_proc("Java",
+%       unsafe_get_varname(X::out(<varinst>)),
+%       [promise_semipure, will_not_call_mercury, thread_safe],
+%   "
+%       X = mutable_<varname>.get();
+%   ").
+%
 % The above prediates are called by these predicates, again to minimise
 % differences with the C backends:
 %
@@ -279,7 +308,7 @@
 % ===>
 %
 %   :- pragma foreign_code("Java", "
-%       static <JavaType> mutable_<varname>;
+%       static java.lang.Object mutable_<varname>;
 %   ").
 %
 %   :- pred get_<varname>(<vartype>::out(<varinst>)) is det.
diff --git a/java/runtime/JavaInternal.java b/java/runtime/JavaInternal.java
index 8434290..6ead6af 100644
--- a/java/runtime/JavaInternal.java
+++ b/java/runtime/JavaInternal.java
@@ -22,7 +22,7 @@ public class JavaInternal {
 	public static int			exit_status;

         private static java.util.List<Runnable> finalisers
-		= new java.util.ArrayList();
+		= new java.util.ArrayList<Runnable>();

 	public static void register_finaliser(Runnable hook) {
 		finalisers.add(hook);
--------------------------------------------------------------------------
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