[m-rev.] for review: Add constant structure support to Java backend

Paul Bone paul at bone.id.au
Wed Jan 29 14:26:30 AEDT 2014


For review by anyone.

Branches: master, version-14.01-branch

It's not critical that this be put on the release branch, but it'd be nice.
It may improve performance but not by much more than 1%.  (Tested using
on MCit's product ODASE.)

---

Add constant structure support to Java backend

This change enables constant structure support for the Java backend for the
structures introduced by the polymorphism pass.

compiler/const_struct.m:
compiler/ml_unify_gen.m:
    Enable constant structure support

java/runtime/TypeInfo_Struct.java:
    Add a constructor to the TypeInfo structure for Java.  This constructor
    has the interface expected by the polymorphism code.

    Never expect to be passed the arity to the varargs constructor.

compiler/polymorphism.m:
compiler/ml_unify_gen.m:
    Change how we avoid creating TypeInfos with an explicit arity for Java

    We never specify the arity for a TypeInfo_Struct in a Java grade.  There
    are two reasons: this is a little difficult to handle due to overloading
    rules and it is not necessary.

    This is handled by removing these arguments in the MLDS backend.
    However, the current solution does not work when we create TypeInfos as
    constant structures.  Therefore this change removes the special case
    from the MLDS backend and instead never creates the arity arguments
    during the polymorphism pass.  rtti_to_mlds.m didn't need updating as it
    already had the correct behaviour.

compiler/rtti_to_mlds.m:
    Update a comment.
---
 compiler/const_struct.m           | 65 +++++++++++++++++-----------
 compiler/ml_unify_gen.m           | 91 ++++++---------------------------------
 compiler/polymorphism.m           | 43 +++++++++++++++---
 compiler/rtti_to_mlds.m           |  4 +-
 java/runtime/TypeInfo_Struct.java | 25 ++++++++---
 5 files changed, 108 insertions(+), 120 deletions(-)

diff --git a/compiler/const_struct.m b/compiler/const_struct.m
index a9def75..812ad15 100644
--- a/compiler/const_struct.m
+++ b/compiler/const_struct.m
@@ -1,7 +1,7 @@
 %-----------------------------------------------------------------------------%
 % vim: ft=mercury ts=4 sw=4 et
 %-----------------------------------------------------------------------------%
-% Copyright (C) 2012 The University of Melbourne.
+% Copyright (C) 2012, 2014 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.
 %-----------------------------------------------------------------------------%
@@ -137,30 +137,8 @@ const_struct_db_init(Globals, Db) :-
             globals.get_tags_method(Globals, Tags),
             (
                 Tags = tags_low,
-                globals.lookup_bool_option(Globals, enable_const_struct,
-                    OptionEnabled),
-                PolyEnabled = OptionEnabled,
-
-                globals.get_trace_level(Globals, TraceLevel),
-                globals.get_trace_suppress(Globals, TraceSuppress),
-                Bodies = trace_needs_proc_body_reps(TraceLevel, TraceSuppress),
-                (
-                    Bodies = no,
-                    GroundTermEnabled = OptionEnabled
-                ;
-                    Bodies = yes,
-                    % We generate representations of procedure bodies for the
-                    % declarative debugger and for the profiler. When
-                    % traverse_primitives in browser/declarative_tree.m
-                    % looks for the Nth argument of variable X and X is built
-                    % with a unification such as X = ground_term_const(...),
-                    % it crashes. It should be taught not to do that,
-                    % but in the meantime, we prevent the situation from
-                    % arising in the first place. (We never look for the
-                    % original sources of type infos and typeclass infos,
-                    % so we can use constant structures for them.)
-                    GroundTermEnabled = no
-                )
+                can_enable_const_struct(Globals, PolyEnabled,
+                    GroundTermEnabled)
             ;
                 ( Tags = tags_high
                 ; Tags = tags_none
@@ -174,9 +152,12 @@ const_struct_db_init(Globals, Db) :-
             GroundTermEnabled = no
         )
     ;
+        Target = target_java,
+        can_enable_const_struct(Globals, PolyEnabled, _GroundTermEnabled),
+        GroundTermEnabled = no
+    ;
         ( Target = target_il
         ; Target = target_csharp
-        ; Target = target_java
         ; Target = target_x86_64
         ; Target = target_erlang
         ),
@@ -186,6 +167,38 @@ const_struct_db_init(Globals, Db) :-
     Db = const_struct_db(PolyEnabled, GroundTermEnabled, 0,
         map.init, map.init, map.init, map.init).
 
+    % Test if constant structures are enabled for polymorphism structures
+    % and from ground term contexts.  The latter is only enabled if tracing
+    % does not require procedure bodies to be preserved.  The caller must
+    % also check if the compilation grade supports constant structures.
+    %
+:- pred can_enable_const_struct(globals::in, bool::out, bool::out) is det.
+
+can_enable_const_struct(Globals, PolyEnabled, GroundTermEnabled) :-
+    globals.lookup_bool_option(Globals, enable_const_struct,
+        OptionEnabled),
+    PolyEnabled = OptionEnabled,
+
+    globals.get_trace_level(Globals, TraceLevel),
+    globals.get_trace_suppress(Globals, TraceSuppress),
+    Bodies = trace_needs_proc_body_reps(TraceLevel, TraceSuppress),
+    (
+        Bodies = no,
+        GroundTermEnabled = OptionEnabled
+    ;
+        Bodies = yes,
+        % We generate representations of procedure bodies for the
+        % declarative debugger and for the profiler. When
+        % traverse_primitives in browser/declarative_tree.m looks for the
+        % Nth argument of variable X and X is built with a unification such
+        % as X = ground_term_const(...), it crashes. It should be taught not
+        % to do that, but in the meantime, we prevent the situation from
+        % arising in the first place. (We never look for the original
+        % sources of type infos and typeclass infos, so we can use constant
+        % structures for them.)
+        GroundTermEnabled = no
+    ).
+
 lookup_insert_const_struct(ConstStruct, ConstNum, !Db) :-
     const_struct_db_get_poly_enabled(!.Db, Enabled),
     (
diff --git a/compiler/ml_unify_gen.m b/compiler/ml_unify_gen.m
index aafe9f4..1f766b9 100644
--- a/compiler/ml_unify_gen.m
+++ b/compiler/ml_unify_gen.m
@@ -1,7 +1,7 @@
 %-----------------------------------------------------------------------------%
 % vim: ft=mercury ts=4 sw=4 et
 %-----------------------------------------------------------------------------%
-% Copyright (C) 1999-2012 The University of Melbourne.
+% Copyright (C) 1999-2012, 2014 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.
 %-----------------------------------------------------------------------------%
@@ -679,18 +679,8 @@ ml_gen_new_object(MaybeConsId, MaybeCtorName, Tag, ExplicitSecTag, Var,
 
 ml_gen_new_object_dynamically(MaybeConsId, MaybeCtorName, MaybeTag,
         ExplicitSecTag, _Var, VarLval, VarType, MLDS_Type,
-        ExtraRvals, ExtraTypes, ArgVars0, ArgTypes0, ArgModes0, TakeAddr,
+        ExtraRvals, ExtraTypes, ArgVars, ArgTypes, ArgModes, TakeAddr,
         Context, Statements, !Info) :-
-    % Fixup type_info_cell_constructor argument lists for the Java backend.
-    % (See the documention of the callee for an explanation.)
-    ml_gen_info_get_target(!.Info, Target),
-    maybe_fixup_type_info_cell_constructor_args(Target, MaybeConsId,
-        ArgVars0, ArgVars),
-    maybe_fixup_type_info_cell_constructor_args(Target, MaybeConsId,
-        ArgTypes0, ArgTypes),
-    maybe_fixup_type_info_cell_constructor_args(Target, MaybeConsId,
-        ArgModes0, ArgModes),
-
     % Find out the types of the constructor arguments and generate rvals
     % for them (boxing/unboxing if needed).
     ml_gen_var_list(!.Info, ArgVars, ArgLvals),
@@ -770,19 +760,12 @@ ml_gen_new_object_dynamically(MaybeConsId, MaybeCtorName, MaybeTag,
 
 ml_gen_new_object_statically(MaybeConsId, MaybeCtorName, MaybeTag,
         Var, VarLval, VarType, MLDS_Type, ExtraRvals, ExtraTypes,
-        ArgVars0, ArgTypes0, Context, Statements, !Info) :-
+        ArgVars, ArgTypes, Context, Statements, !Info) :-
     % Find out the types of the constructor arguments.
     ml_gen_info_get_module_info(!.Info, ModuleInfo),
     ml_gen_info_get_high_level_data(!.Info, HighLevelData),
     ml_gen_info_get_target(!.Info, Target),
 
-    % Fixup type_info_cell_constructor argument lists for the Java backend.
-    % (See the documention of the callee for an explanation.)
-    maybe_fixup_type_info_cell_constructor_args(Target, MaybeConsId,
-        ArgVars0, ArgVars),
-    maybe_fixup_type_info_cell_constructor_args(Target, MaybeConsId,
-        ArgTypes0, ArgTypes),
-
     get_maybe_cons_id_arg_types(ModuleInfo, MaybeConsId, ArgTypes, VarType,
         ConsArgTypes, ConsArgWidths),
 
@@ -870,60 +853,6 @@ ml_gen_new_object_statically(MaybeConsId, MaybeCtorName, MaybeTag,
     AssignStatement = ml_gen_assign(VarLval, Rval, Context),
     Statements = [AssignStatement].
 
-    % Fixup the arguments of type_info_cell_constructors to conform
-    % to what the Java version of the runtime expects.
-    %
-    % For the Java backend we need to treat type_info_cell_constructors with a
-    % variable arity type_ctor specially. polymorphism.m generates these so
-    % that the second argument is an integer giving the arity of the type_ctor,
-    % but there is no corresponding constructor with an integer argument in
-    % the TypeInfo_Struct class in the Java version of the runtime.
-    % Having such a constructor would cause problems with restrictions on
-    % overloading in Java. (In any case, it is unnecessary since the arity
-    % can be obtained from the length of the array holding the remaining
-    % arguments.)
-    %
-    % The job of this predicate is to remove the arity argument from the
-    % argument list of a type_info_cell_constructor if we are compiling to
-    % Java and we have a varaible arity type_ctor.
-    %
-    % NOTE: this code needs to kept consistent with:
-    %
-    %       compiler/rtti_to_mods.gen_type_info_defn/6
-    %       java/runtime/TypeInfo_Struct.java
-    %
-    % XXX it might be better to modify polymoprhism.m so that it never
-    % inserts the arity argument in the first place.
-    %
-:- pred maybe_fixup_type_info_cell_constructor_args(compilation_target::in,
-    maybe(cons_id)::in, list(T)::in, list(T)::out) is det.
-
-maybe_fixup_type_info_cell_constructor_args(Target, MaybeConsId, !Args) :-
-    ( Target = target_java ->
-        (
-            MaybeConsId = no
-        ;
-            MaybeConsId = yes(ConsId),
-            (
-                ConsId = type_info_cell_constructor(TypeCtor),
-                ( type_ctor_is_higher_order(TypeCtor, _, _, _)
-                ; type_ctor_is_tuple(TypeCtor)
-                )
-            ->
-                ( !.Args = [TypeInfoCtorArg, _ArityArg | OtherArgs] ->
-                    !:Args = [TypeInfoCtorArg | OtherArgs]
-                ;
-                    unexpected($module, $pred,
-                        "misformed type_info_cell_constructor args")
-                )
-            ;
-                true
-            )
-        )
-    ;
-        true
-    ).
-
 :- pred ml_gen_new_object_reuse_cell(maybe(cons_id)::in, maybe(ctor_name)::in,
     mlds_tag::in, maybe(mlds_tag)::in, bool::in,
     prog_var::in, mlds_lval::in, mer_type::in, mlds_type::in,
@@ -3044,14 +2973,20 @@ ml_gen_const_static_compound(Info, ConstNum, Type, MLDS_Type, ConsId, ConsTag,
     ),
     HighLevelData = Info ^ mcsi_high_level_data,
     (
-        HighLevelData = yes,
-        unexpected($module, $pred, "HighLevelData NYI")
-    ;
-        HighLevelData = no,
+        (
+            HighLevelData = no
+        ;
+            HighLevelData = yes,
+            Target = target_java
+        )
+    ->
         assoc_list.from_corresponding_lists(Args, ConsArgWidths,
             ArgConsArgWidths),
         ml_gen_const_struct_args(Info, !.ConstStructMap,
             ArgConsArgWidths, ArgRvals1, !GlobalData)
+    ;
+        unexpected($file, $pred,
+            "Constant structures are not supported for this grade")
     ),
     pack_args(ml_shift_combine_rval, ConsArgWidths, ArgRvals1, ArgRvals,
         unit, _, unit, _),
diff --git a/compiler/polymorphism.m b/compiler/polymorphism.m
index 13f24ae..3765d88 100644
--- a/compiler/polymorphism.m
+++ b/compiler/polymorphism.m
@@ -1,7 +1,7 @@
 %-----------------------------------------------------------------------------%
 % vim: ft=mercury ts=4 sw=4 et
 %-----------------------------------------------------------------------------%
-% Copyright (C) 1995-2012 The University of Melbourne.
+% Copyright (C) 1995-2012, 2014 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.
 %-----------------------------------------------------------------------------%
@@ -3280,7 +3280,8 @@ polymorphism_construct_type_info(Type, TypeCtor, TypeArgs, TypeCtorIsVarArity,
     %
     %   TypeInfoVar = type_info(TypeCtorVar, ArgTypeInfoVars...)
     %
-    % However, if TypeCtorIsVarArity is true, then it will be of the form
+    % However, if TypeCtorIsVarArity is true and we are not compiling for
+    % the Java backend, then it will be of the form
     %
     %   TypeInfoVar = type_info(TypeCtorVar, Arity, ArgTypeInfoVars...)
     %
@@ -3294,11 +3295,39 @@ polymorphism_construct_type_info(Type, TypeCtor, TypeArgs, TypeCtorIsVarArity,
     % The returned Var will be bound to the type_info cell of Type if such
     % a cell had to be allocated, and to the type_ctor_info of Type's only
     % type constructor if it didn't.
+    %
+    % NOTE: the special handling for the java backend must be kept
+    % conisistent with:
+    %   rtti_to_mlds.gen_type_info_defn/6
+    %   java/runtime/TypeInfo_Struct.java
+
+    % Determine if we need to explicitly pass the arity
+    (
+        TypeCtorIsVarArity = no,
+        PassArity = no
+    ;
+        TypeCtorIsVarArity = yes,
+        poly_info_get_module_info(!.Info, ModuleInfo),
+        module_info_get_globals(ModuleInfo, Globals),
+        get_target(Globals, Target),
+        (
+            Target = target_java,
+            PassArity = no
+        ;
+            ( Target = target_c
+            ; Target = target_il
+            ; Target = target_csharp
+            ; Target = target_x86_64
+            ; Target = target_erlang
+            ),
+            PassArity = yes
+        )
+    ),
 
     (
         % Unfortunately, if the type's type constructor has variable arity,
         % we cannot use a one-cell representation for that type.
-        TypeCtorIsVarArity = no,
+        PassArity = no,
         ArgTypeInfoVarsMCAs = []
     ->
         % We do not need a second cell for a separate typeinfo; we will use
@@ -3332,7 +3361,7 @@ polymorphism_construct_type_info(Type, TypeCtor, TypeArgs, TypeCtorIsVarArity,
             list.map(get_inst_of_const_struct_arg(ConstStructDb0),
                 ArgTypeInfoConstArgs, ArgTypeInfoInsts),
             (
-                TypeCtorIsVarArity = yes,
+                PassArity = yes,
                 list.length(ArgTypeInfoVarsMCAs, ActualArity),
                 ArityConstArg = csa_constant(int_const(ActualArity), int_type),
                 ArityInst = bound(shared, inst_test_results_fgtc,
@@ -3341,7 +3370,7 @@ polymorphism_construct_type_info(Type, TypeCtor, TypeArgs, TypeCtorIsVarArity,
                     [TypeCtorConstArg, ArityConstArg | ArgTypeInfoConstArgs],
                 StructArgInsts = [TypeCtorInst, ArityInst | ArgTypeInfoInsts]
             ;
-                TypeCtorIsVarArity = no,
+                PassArity = no,
                 StructConstArgs = [TypeCtorConstArg | ArgTypeInfoConstArgs],
                 StructArgInsts = [TypeCtorInst | ArgTypeInfoInsts]
             ),
@@ -3391,7 +3420,7 @@ polymorphism_construct_type_info(Type, TypeCtor, TypeArgs, TypeCtorIsVarArity,
         ;
             assoc_list.keys(ArgTypeInfoVarsMCAs, ArgTypeInfoVars),
             (
-                TypeCtorIsVarArity = yes,
+                PassArity = yes,
                 list.length(ArgTypeInfoVars, ActualArity),
                 get_poly_const(ActualArity, ArityVar, ArityGoals, !Info),
                 % The call get_poly_const may (and probably will) allocate
@@ -3408,7 +3437,7 @@ polymorphism_construct_type_info(Type, TypeCtor, TypeArgs, TypeCtorIsVarArity,
                 ExtraGoals = TypeCtorGoals ++ ArityGoals ++ ArgTypeInfoGoals
                     ++ [TypeInfoGoal]
             ;
-                TypeCtorIsVarArity = no,
+                PassArity = no,
                 init_type_info_var(Type, [TypeCtorVar | ArgTypeInfoVars],
                     no, Var, TypeInfoGoal,
                     VarSet1, VarSet, VarTypes1, VarTypes,
diff --git a/compiler/rtti_to_mlds.m b/compiler/rtti_to_mlds.m
index 80f3139..cbb04f4 100644
--- a/compiler/rtti_to_mlds.m
+++ b/compiler/rtti_to_mlds.m
@@ -1,7 +1,7 @@
 %-----------------------------------------------------------------------------%
 % vim: ft=mercury ts=4 sw=4 et
 %-----------------------------------------------------------------------------%
-% Copyright (C) 2001-2012 The University of Melbourne.
+% Copyright (C) 2001-2012, 2014 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.
 %-----------------------------------------------------------------------------%
@@ -470,7 +470,7 @@ gen_type_info_defn(ModuleInfo, RttiTypeInfo, Name, RttiId, !GlobalData) :-
                 %
                 % NOTE: this needs to be kept consistent with
                 %
-                %   ml_unify_gen.maybe_fixup_type_info_cell_constructor_args/4
+                %   polymorphism.polymorphism_construct_type_info/10
                 %   java/runtime/TypeInfo_Struct.java
                 %
                 % as well as the code for handling pseudo type-infos below.
diff --git a/java/runtime/TypeInfo_Struct.java b/java/runtime/TypeInfo_Struct.java
index 20524f4..e3a3162 100644
--- a/java/runtime/TypeInfo_Struct.java
+++ b/java/runtime/TypeInfo_Struct.java
@@ -1,5 +1,5 @@
 //
-// Copyright (C) 2001-2004, 2011 The University of Melbourne.
+// Copyright (C) 2001-2004, 2011, 2014 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.
 //
@@ -83,23 +83,34 @@ public class TypeInfo_Struct extends PseudoTypeInfo
 		for (int i = 0; i < as.length; i++) {
 			ptis[i] = (PseudoTypeInfo) as[i];
 		}
-                init(tc, ptis);
+		init(tc, ptis);
 	}
 
-	// XXX untested guess
 	// We don't have a version of this constructor that also takes the arity
 	// as an argument (as we do with the init method above), e.g.
 	//
 	//  public TypeInfo_Struct(TypeInfo_Struct ti, int artiy, Object... as)
 	//
 	// because such overloadings are not allowed under Java 1.7.  (Previous
-	// versions of Java incorrectly allowed them.)
+	// versions of Java incorrectly allowed them.)  This is okay because
+	// init above simply checks the number of items in the array to
+	// determine the arity.
+	//
 	// If you change this you will also need to update the code in
-	// compiler/rtti_to_mlds.m.
+	// compiler/rtti_to_mlds.m and compiler/polymorphism.m
 	//
-	public TypeInfo_Struct(TypeInfo_Struct ti, Object... as)
+	public TypeInfo_Struct(Object a1, Object... as)
 	{
-		init(ti.type_ctor, as);
+		if (a1 instanceof TypeInfo_Struct) {
+			TypeInfo_Struct ti = (TypeInfo_Struct)a1;
+			init(ti.type_ctor, as);
+		} else if (a1 instanceof TypeCtorInfo_Struct) {
+			init((TypeCtorInfo_Struct)a1, as);
+		} else {
+			throw new ClassCastException(
+				"Couldn't cast argument to a TypeInfo or " +
+				"TypeCtorInfo");
+		}
 	}
 
 	// XXX a temp hack just to get things to run
-- 
1.8.5.3




More information about the reviews mailing list