[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