[m-rev.] for review: int mutables on c#/java

Peter Wang novalazy at gmail.com
Wed Oct 27 13:57:16 AEDT 2010


Branches: main

Special case `int' mutables in C# and Java grades.
All mutables were represented with the generic `object' type, but that means
integer values require boxing/unboxing.  Since integer mutables are used to
hold counters in the source-to-source debugger (among other applications),
it is best to avoid boxing.

compiler/make_hlds_passes.m:
compiler/ml_foreign_proc_gen.m:
compiler/prog_io_mutable.m:
        As above.

compiler/prog_mutable.m:
        Update description of the mutable transformation.

diff --git a/compiler/make_hlds_passes.m b/compiler/make_hlds_passes.m
index c7af3e9..270b8ef 100644
--- a/compiler/make_hlds_passes.m
+++ b/compiler/make_hlds_passes.m
@@ -118,6 +118,7 @@
 :- import_module libs.file_util.
 :- import_module libs.globals.
 :- import_module libs.options.
+:- import_module parse_tree.builtin_lib_types.
 :- import_module parse_tree.prog_data.
 :- import_module parse_tree.prog_mode.
 :- import_module parse_tree.prog_mutable.
@@ -2334,10 +2335,10 @@ add_c_mutable_initialisation(IsConstant, IsThreadLocal, TargetMutableName,
     module_info::in, module_info::out, qual_info::in, qual_info::out,
     list(error_spec)::in, list(error_spec)::out) is det.
 
-add_csharp_java_mutable_defn(Lang, TargetMutableName, _Type, IsThreadLocal,
+add_csharp_java_mutable_defn(Lang, TargetMutableName, Type, IsThreadLocal,
         Context, !ModuleInfo, !QualInfo, !Specs) :-
     get_csharp_java_mutable_global_foreign_defn(Lang, TargetMutableName,
-        IsThreadLocal, Context, DefnBody),
+        Type, IsThreadLocal, Context, DefnBody),
     DefnPragma = pragma_foreign_code(Lang, DefnBody),
     DefnItemPragma = item_pragma_info(compiler(mutable_decl), DefnPragma,
         Context, -1),
@@ -2346,10 +2347,10 @@ add_csharp_java_mutable_defn(Lang, TargetMutableName, _Type, IsThreadLocal,
     add_item_decl_pass_2(ForeignDefn, ItemStatus0, _, !ModuleInfo, !Specs).
 
 :- pred get_csharp_java_mutable_global_foreign_defn(
-    foreign_language::in(lang_csharp_java), string::in,
+    foreign_language::in(lang_csharp_java), string::in, mer_type::in,
     mutable_thread_local::in, prog_context::in, string::out) is det.
 
-get_csharp_java_mutable_global_foreign_defn(Lang, TargetMutableName,
+get_csharp_java_mutable_global_foreign_defn(Lang, TargetMutableName, Type,
         IsThreadLocal, _Context, DefnBody) :-
     (
         Lang = lang_csharp,
@@ -2362,23 +2363,38 @@ get_csharp_java_mutable_global_foreign_defn(Lang, TargetMutableName,
             % We will probably need to use the ThreadLocal<T> class instead.
             ThreadStaticAttribute = "[System.ThreadStatic] "
         ),
+        ( Type = int_type ->
+            TypeStr = "int"
+        ;
+            TypeStr = "object"
+        ),
         DefnBody = string.append_list([ThreadStaticAttribute,
-            "static object ", TargetMutableName, ";\n"])
+            "static ", TypeStr, " ", TargetMutableName, ";\n"])
     ;
         Lang = lang_java,
         IsThreadLocal = mutable_not_thread_local,
         % Synchronization is only required for double and long values, which
         % Mercury does not expose. We could also use the volatile keyword.
         % (Java Language Specification, 2nd Ed., 17.4).
+        ( Type = int_type ->
+            TypeStr = "int"
+        ;
+            TypeStr = "java.lang.Object"
+        ),
         DefnBody = string.append_list([
-            "static java.lang.Object ", TargetMutableName, ";\n"])
+            "static ", TypeStr, " ", TargetMutableName, ";\n"])
     ;
         Lang = lang_java,
         IsThreadLocal = mutable_thread_local,
+        ( Type = int_type ->
+            TypeStr = "java.lang.Integer"
+        ;
+            TypeStr = "java.lang.Object"
+        ),
         DefnBody = string.append_list([
-            "static java.lang.ThreadLocal<java.lang.Object> ",
+            "static java.lang.ThreadLocal<", TypeStr, "> ",
             TargetMutableName,
-            " = new java.lang.InheritableThreadLocal<java.lang.Object>();\n"
+            " = new java.lang.InheritableThreadLocal<", TypeStr, ">();\n"
         ])
     ).
 
diff --git a/compiler/ml_foreign_proc_gen.m b/compiler/ml_foreign_proc_gen.m
index 13f9f30..0301fa9 100644
--- a/compiler/ml_foreign_proc_gen.m
+++ b/compiler/ml_foreign_proc_gen.m
@@ -57,6 +57,7 @@
 :- import_module libs.globals.
 :- import_module libs.options.
 :- import_module ml_backend.ml_code_util.
+:- import_module parse_tree.builtin_lib_types.
 
 :- import_module bool.
 :- import_module map.
@@ -186,7 +187,7 @@ ml_gen_nondet_pragma_foreign_proc(CodeModel, Attributes, PredId, _ProcId,
         ], HashUndefs),
 
     % Generate code to set the values of the input variables.
-    ml_gen_pragma_c_java_input_arg_list(Lang, Args, AssignInputsList, !Info),
+    ml_gen_pragma_ccsj_input_arg_list(Lang, Args, AssignInputsList, !Info),
 
     % Generate code to assign the values of the output variables.
     ml_gen_pragma_c_output_arg_list(Args, Context,
@@ -395,12 +396,12 @@ ml_gen_ordinary_pragma_csharp_java_proc(TargetLang, OrdinaryKind, Attributes,
     ),
 
     % Generate <declaration of one local variable for each arg>
-    ml_gen_pragma_java_decls(!.Info, MutableSpecial, Args, ArgDeclsList),
+    ml_gen_pragma_csharp_java_decls(!.Info, MutableSpecial, Args, ArgDeclsList),
     expect(unify(ExtraArgs, []), this_file,
         "ml_gen_ordinary_pragma_csharp_java_proc: extra args"),
 
     % Generate code to set the values of the input variables.
-    ml_gen_pragma_c_java_input_arg_list(Lang, Args, AssignInputsList, !Info),
+    ml_gen_pragma_ccsj_input_arg_list(Lang, Args, AssignInputsList, !Info),
 
     % Generate MLDS statements to assign the values of the output variables.
     ml_gen_pragma_csharp_java_output_arg_list(MutableSpecial, Args, Context,
@@ -804,7 +805,7 @@ ml_gen_ordinary_pragma_c_proc(OrdinaryKind, Attributes, PredId, _ProcId,
     ml_gen_pragma_c_decls(!.Info, Lang, Args, ArgDeclsList),
 
     % Generate code to set the values of the input variables.
-    ml_gen_pragma_c_java_input_arg_list(Lang, Args, AssignInputsList, !Info),
+    ml_gen_pragma_ccsj_input_arg_list(Lang, Args, AssignInputsList, !Info),
 
     % Generate code to assign the values of the output variables.
     ml_gen_pragma_c_output_arg_list(Args, Context,
@@ -1018,24 +1019,27 @@ ml_gen_pragma_c_decl(Info, Lang, Arg, Decl) :-
     --->    mutable_special_case
     ;       not_mutable_special_case.
 
-    % ml_gen_pragma_java_decls generates Java code to declare the arguments
-    % for a `pragma foreign_proc' declaration.
+    % ml_gen_pragma_csharp_java_decls generates C# or Java code to declare the
+    % arguments for a `pragma foreign_proc' declaration.
     %
-:- pred ml_gen_pragma_java_decls(ml_gen_info::in, mutable_special_case::in,
-    list(foreign_arg)::in, list(target_code_component)::out) is det.
+:- pred ml_gen_pragma_csharp_java_decls(ml_gen_info::in,
+    mutable_special_case::in, list(foreign_arg)::in,
+    list(target_code_component)::out) is det.
 
-ml_gen_pragma_java_decls(_, _, [], []).
-ml_gen_pragma_java_decls(Info, MutableSpecial, [Arg | Args], Decl ++ Decls) :-
-    ml_gen_pragma_java_decl(Info, MutableSpecial, Arg, Decl),
-    ml_gen_pragma_java_decls(Info, MutableSpecial, Args, Decls).
+ml_gen_pragma_csharp_java_decls(_, _, [], []).
+ml_gen_pragma_csharp_java_decls(Info, MutableSpecial, [Arg | Args],
+        Decl ++ Decls) :-
+    ml_gen_pragma_csharp_java_decl(Info, MutableSpecial, Arg, Decl),
+    ml_gen_pragma_csharp_java_decls(Info, MutableSpecial, Args, Decls).
 
-    % ml_gen_pragma_java_decl generates Java code to declare an argument
-    % of a `pragma foreign_proc' declaration.
+    % ml_gen_pragma_csharp_java_decl generates C# or Java code to declare an
+    % argument of a `pragma foreign_proc' declaration.
     %
-:- pred ml_gen_pragma_java_decl(ml_gen_info::in, mutable_special_case::in,
-    foreign_arg::in, list(target_code_component)::out) is det.
+:- pred ml_gen_pragma_csharp_java_decl(ml_gen_info::in,
+    mutable_special_case::in, foreign_arg::in,
+    list(target_code_component)::out) is det.
 
-ml_gen_pragma_java_decl(Info, MutableSpecial, Arg, Decl) :-
+ml_gen_pragma_csharp_java_decl(Info, MutableSpecial, Arg, Decl) :-
     Arg = foreign_arg(_Var, MaybeNameAndMode, Type, _BoxPolicy),
     ml_gen_info_get_module_info(Info, ModuleInfo),
     (
@@ -1048,8 +1052,11 @@ ml_gen_pragma_java_decl(Info, MutableSpecial, Arg, Decl) :-
         ;
             MutableSpecial = mutable_special_case,
             % The code for mutables is generated in the frontend.
-            % All mutable variables have the type `java.lang.Object'.
-            MLDS_Type = mlds_generic_type
+            ( Type = int_type ->
+                MLDS_Type = mlds_native_int_type
+            ;
+                MLDS_Type = mlds_generic_type
+            )
         ),
         TypeDecl = target_code_type(MLDS_Type),
         string.format(" %s;\n", [s(ArgName)], VarDeclString),
@@ -1079,25 +1086,25 @@ var_is_singleton(Name) :-
 
 %-----------------------------------------------------------------------------%
 
-    % For both C and Java.
+    % For C, C# and Java.
     %
-:- pred ml_gen_pragma_c_java_input_arg_list(foreign_language::in,
+:- pred ml_gen_pragma_ccsj_input_arg_list(foreign_language::in,
     list(foreign_arg)::in, list(target_code_component)::out,
     ml_gen_info::in, ml_gen_info::out) is det.
 
-ml_gen_pragma_c_java_input_arg_list(Lang, ArgList, AssignInputs, !Info) :-
-    list.map_foldl(ml_gen_pragma_c_java_input_arg(Lang), ArgList,
+ml_gen_pragma_ccsj_input_arg_list(Lang, ArgList, AssignInputs, !Info) :-
+    list.map_foldl(ml_gen_pragma_ccsj_input_arg(Lang), ArgList,
         AssignInputsList, !Info),
     list.condense(AssignInputsList, AssignInputs).
 
-    % ml_gen_pragma_c_input_arg generates C or Java code to assign the value of
-    % an input arg for a `pragma foreign_proc' declaration.
+    % ml_gen_pragma_c_input_arg generates C, C# or Java code to assign the
+    % value of an input arg for a `pragma foreign_proc' declaration.
     %
-:- pred ml_gen_pragma_c_java_input_arg(foreign_language::in, foreign_arg::in,
+:- pred ml_gen_pragma_ccsj_input_arg(foreign_language::in, foreign_arg::in,
     list(target_code_component)::out,
     ml_gen_info::in, ml_gen_info::out) is det.
 
-ml_gen_pragma_c_java_input_arg(Lang, ForeignArg, AssignInput, !Info) :-
+ml_gen_pragma_ccsj_input_arg(Lang, ForeignArg, AssignInput, !Info) :-
     ml_gen_info_get_module_info(!.Info, ModuleInfo),
     (
         ForeignArg = foreign_arg(Var, MaybeNameAndMode, OrigType, BoxPolicy),
@@ -1105,7 +1112,7 @@ ml_gen_pragma_c_java_input_arg(Lang, ForeignArg, AssignInput, !Info) :-
         not var_is_singleton(ArgName),
         mode_to_arg_mode(ModuleInfo, Mode, OrigType, top_in)
     ->
-        ml_gen_pragma_c_java_gen_input_arg(Lang, Var, ArgName, OrigType,
+        ml_gen_pragma_ccsj_gen_input_arg(Lang, Var, ArgName, OrigType,
             BoxPolicy, AssignInput, !Info)
     ;
         % If the variable doesn't occur in the ArgNames list,
@@ -1113,11 +1120,11 @@ ml_gen_pragma_c_java_input_arg(Lang, ForeignArg, AssignInput, !Info) :-
         AssignInput = []
     ).
 
-:- pred ml_gen_pragma_c_java_gen_input_arg(foreign_language::in, prog_var::in,
+:- pred ml_gen_pragma_ccsj_gen_input_arg(foreign_language::in, prog_var::in,
     string::in, mer_type::in, box_policy::in, list(target_code_component)::out,
     ml_gen_info::in, ml_gen_info::out) is det.
 
-ml_gen_pragma_c_java_gen_input_arg(Lang, Var, ArgName, OrigType, BoxPolicy,
+ml_gen_pragma_ccsj_gen_input_arg(Lang, Var, ArgName, OrigType, BoxPolicy,
         AssignInput, !Info) :-
     ml_variable_type(!.Info, Var, VarType),
     ml_gen_var(!.Info, Var, VarLval),
@@ -1284,10 +1291,11 @@ ml_gen_pragma_csharp_java_output_arg(MutableSpecial, ForeignArg, Context,
         ;
             MutableSpecial = mutable_special_case,
             % The code for mutables is generated in the frontend.
-            % All mutable variables have the type `java.lang.Object'
-            % so we need to cast the variable or extract the primitive
-            % value from the box.
-            Rval = ml_unop(unbox(MLDSType), ml_lval(LocalVarLval))
+            ( OrigType = int_type ->
+                Rval = ml_lval(LocalVarLval)
+            ;
+                Rval = ml_unop(unbox(MLDSType), ml_lval(LocalVarLval))
+            )
         ),
         AssignOutput = [ml_gen_assign(ArgLval, Rval, Context)]
     ;
diff --git a/compiler/prog_io_mutable.m b/compiler/prog_io_mutable.m
index e78e734..ba97e9e 100644
--- a/compiler/prog_io_mutable.m
+++ b/compiler/prog_io_mutable.m
@@ -1,6 +1,6 @@
-%-----------------------------------------------------------------------------e
+%-----------------------------------------------------------------------------%
 % vim: ft=mercury ts=4 sw=4 et
-%-----------------------------------------------------------------------------e
+%-----------------------------------------------------------------------------%
 % Copyright (C) 2008 The University of Melbourne.
 % This file may only be copied under the terms of the GNU General
 % Public License - see the file COPYING in the Mercury distribution.
diff --git a/compiler/prog_mutable.m b/compiler/prog_mutable.m
index feb6158..8ce4b2d 100644
--- a/compiler/prog_mutable.m
+++ b/compiler/prog_mutable.m
@@ -222,7 +222,7 @@
 % ===>
 %
 %   :- pragma foreign_code("Java", "
-%       static java.lang.Object mutable_<varname>;
+%       static <JType> mutable_<varname>;
 %   ").
 %
 %   :- initialise initialise_mutable_<varname>/0.
@@ -232,6 +232,8 @@
 %   initialise_mutable_<varname> :-
 %       impure set_<varname>(<initval>).
 %
+% <JType> is either `int' or `java.lang.Object' (all other types).
+%
 % Operations on mutables are defined in terms of the following two predicates.
 % They are actually "safe": by the Java specification, 32-bit variables are
 % loaded/stored atomically.  Doubles and longs may be treated as two 32-bit
@@ -254,7 +256,7 @@
 %       X = mutable_<varname>;
 %   ").
 %
-% As mutable_<varname> has the type `java.lang.Object' a cast is required
+% If 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.
 %
@@ -265,8 +267,8 @@
 % ===>
 %
 %   :- pragma foreign_code("Java", "
-%       static java.lang.ThreadLocal<java.lang.Object> mutable_<varname> =
-%           new java.lang.InheritableThreadLocal<java.lang.Object>();
+%       static java.lang.ThreadLocal<JType> mutable_<varname> =
+%           new java.lang.InheritableThreadLocal<JType>();
 %   ").
 %
 %   :- pragma foreign_proc("Java",
@@ -283,6 +285,8 @@
 %       X = mutable_<varname>.get();
 %   ").
 %
+% <JType> is `java.lang.Integer' or `java.lang.Object'.
+%
 % The above prediates are called by these predicates, again to minimise
 % differences with the C backends:
 %
@@ -303,7 +307,7 @@
 % ===>
 %
 %   :- pragma foreign_code("Java", "
-%       static java.lang.Object mutable_<varname>;
+%       static <JType> mutable_<varname>;
 %   ").
 %
 %   :- pred get_<varname>(<vartype>::out(<varinst>)) is det.

--------------------------------------------------------------------------
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