[m-dev.] diff: Runtime support for stack_layouts

Zoltan Somogyi zs at cs.mu.oz.au
Tue Oct 28 10:32:00 AEDT 1997


> runtime/calls.h:
> 	Instead of doing ASM_FIXUP_REGS as part of the call macro, do
> 	it as part of the proceed macro.
> 	As part of the call macro, the succip would always be set
> 	to the "fixup_gp" label, so it was difficult to find the
> 	caller using the succip. Using this technique, it is set
> 	correctly.
> 	(There's a small cost - with the call macro, you only did
> 	ASM_FIXUP_REGS after you returned from a non-local call, using
> 	"proceed" you do this at every call. The only way I can see
> 	to avoid this cost is to actually change the code generator
> 	so that it outputs two labels for continuations, one used
> 	for local calls, and one for non-local calls. The nonlocal
> 	label does ASM_FIXUP_REGS and falls through to the local label).

Why do you need both labels? For each call, you know whether it is
local or nonlocal.

> 
> util/mkinit.c:
> 	Add NATIVE_GC to the list of defines where we need to run
> 	the label initialization code (we use the label table, like
> 	profiling does).

I don't understand this sentence.

> Index: library/array.m
> ===================================================================
> RCS file: /home/staff/zs/imp/mercury/library/array.m,v
> retrieving revision 1.38
> diff -u -r1.38 array.m
> --- array.m	1997/09/06 18:23:36	1.38
> +++ array.m	1997/09/18 07:22:40
> @@ -244,8 +244,11 @@
>  :- pragma(c_code, "
>  
>  Define_extern_entry(mercury____Unify___array__array_1_0);
> +MR_MAKE_STACK_LAYOUT_ENTRY(mercury____Unify___array__array_1_0);
>  Define_extern_entry(mercury____Index___array__array_1_0);
> +MR_MAKE_STACK_LAYOUT_ENTRY(mercury____Index___array__array_1_0);
>  Define_extern_entry(mercury____Compare___array__array_1_0);
> +MR_MAKE_STACK_LAYOUT_ENTRY(mercury____Compare___array__array_1_0);
>  
>  #ifdef  USE_TYPE_LAYOUT
>  
> Index: library/benchmarking.m
> ===================================================================
> RCS file: /home/staff/zs/imp/mercury/library/benchmarking.m,v
> retrieving revision 1.2
> diff -u -r1.2 benchmarking.m
> --- benchmarking.m	1997/08/05 04:10:00	1.2
> +++ benchmarking.m	1997/09/12 06:41:58
> @@ -130,6 +130,9 @@
>  Define_extern_entry(mercury__benchmarking__benchmark_nondet_5_0);
>  Declare_label(mercury__benchmarking__benchmark_nondet_5_0_i1);
>  Declare_label(mercury__benchmarking__benchmark_nondet_5_0_i2);
> +MR_MAKE_STACK_LAYOUT_ENTRY(mercury__benchmarking__benchmark_nondet_5_0);
> +MR_MAKE_STACK_LAYOUT_INTERNAL(mercury__benchmarking__benchmark_nondet_5_0, 
       1);
> +MR_MAKE_STACK_LAYOUT_INTERNAL(mercury__benchmarking__benchmark_nondet_5_0, 
       2);

Why an interleaved sequence in the first fragment and a batched sequence
in the second?

std_util:
> @@ -1153,11 +1162,17 @@
>  Define_extern_entry(mercury____Unify___std_util__univ_0_0);
>  Define_extern_entry(mercury____Index___std_util__univ_0_0);
>  Define_extern_entry(mercury____Compare___std_util__univ_0_0);
> -Declare_label(mercury____Compare___std_util__univ_0_0_i1);
> +MR_MAKE_STACK_LAYOUT_ENTRY(mercury____Unify___std_util__univ_0_0);
> +MR_MAKE_STACK_LAYOUT_ENTRY(mercury____Index___std_util__univ_0_0);
> +MR_MAKE_STACK_LAYOUT_ENTRY(mercury____Compare___std_util__univ_0_0);
> +MR_MAKE_STACK_LAYOUT_INTERNAL(mercury____Compare___std_util__univ_0_0, 1);

Did you intend to delete that label declaration? If yes, why is there
a MR_MAKE_STACK_LAYOUT_INTERNAL for it?

> RCS file: /home/staff/zs/imp/mercury/runtime/Mmakefile,v
>  HDRS		= calls.h conf.h context.h \
>  		  deep_copy.h dlist.h debug.h dummy.h \
>  		  engine.h getopt.h goto.h heap.h imp.h init.h label.h \
> -		  memory.h mercury_float.h mercury_grade.h \
> +		  memory.h mercury_accurate_gc.h mercury_float.h \
>  		  mercury_string.h mercury_trace.h mercury_trail.h \
>  		  mercury_types.h misc.h \
>  		  overflow.h prof.h prof_mem.h regorder.h regs.h \
>  		  spinlock.h std.h stacks.h \
>  		  table.h tags.h timing.h type_info.h wrapper.h \
>  		  $(LIBMER_DLL_H)

It is long past time we converted this mess to use one filename per line.
Similarly for other lists below.

> Index: runtime/goto.h
> ===================================================================
> RCS file: /home/staff/zs/imp/mercury/runtime/goto.h,v
> retrieving revision 1.34
> diff -u -r1.34 goto.h
> --- goto.h	1997/10/12 05:43:52	1.34
> +++ goto.h	1997/10/23 04:54:03
> @@ -12,37 +12,46 @@
>  #include "mercury_types.h"	/* for `Code *' */
>  #include "debug.h"		/* for debuggoto() */
>  
> +#define paste(a,b) a##b
> +#define stringify(string) #string

Don't we already have these defined somewhere else?

> Index: runtime/label.c
> ===================================================================
> RCS file: /home/staff/zs/imp/mercury/runtime/label.c,v
> retrieving revision 1.22
> diff -u -r1.22 label.c
> --- label.c	1997/08/28 17:52:31	1.22
> +++ label.c	1997/10/23 04:52:30
> @@ -50,15 +50,26 @@
>  }
>  
>  Label *
> -insert_entry(const char *name, Code *addr)
> +insert_entry(const char *name, Code *addr, Word *entry_layout_info)
>  {
>  	Label	*entry;
>  
>  	do_init_entries();
>  
> +
> +#ifdef MR_USE_STACK_LAYOUTS
> +	/* 
> +	** The succip will be set to the address stored in the
> +	** layout info. For some reason, this is different to
> +	** the address passed to insert_entry
> +	*/
> +	addr = entry_layout_info[0];
> +#endif /* MR_USE_STACK_LAYOUTS */
> +
>  	entry = make(Label);
>  	entry->e_name  = name;
>  	entry->e_addr  = addr;
> +	entry->e_layout  = entry_layout_info;

The comment is weird. I don't see any setting of succip, and I don't
see why the two definitions of addr should be different. This latter
matter must be resolved before we rely on layout tables.

> Index: runtime/label.h
> ===================================================================
> RCS file: /home/staff/zs/imp/mercury/runtime/label.h,v
> retrieving revision 1.14
> diff -u -r1.14 label.h
> --- label.h	1997/07/27 15:08:24	1.14
> +++ label.h	1997/08/27 08:20:53
> @@ -6,7 +6,10 @@
>  
>  /*
>  ** label.h defines the interface to the label table, which is a pair of
> -** hash tables mapping from procedure names to addresses and vice versa.
> +** hash tables, one mapping from procedure names and the other from
> +** addresses to label information.

"one mapping from procedure names" to what?

> +** The label information includes the name, address of the code, and
> +** layout information for that label.

The name of what?

>  #ifndef	LABEL_H
> @@ -18,10 +21,11 @@
>  typedef struct s_label {
>  	const char	*e_name;   /* name of the procedure	     */
>  	Code		*e_addr;   /* address of the code	     */
> +	Word		*e_layout; /* layout info for the procedure  */
>  } Label;

It ought to be easier to write C code that works with layout tables
if you define proper C structure types for the tables.

> +/*
> +** Definitions for MR_Code_Model
> +*/
> +
> +typedef enum { MR_CODE_MODEL_DET, MR_CODE_MODEL_NONDET } MR_Code_Model;

In the compiler, code_model has three possibilities. It would be better
to invent another name for this concept. Since its main use is to specify
which stack the procedure is using, I suggest something like
MR_stack_specifier.

Avoid the use of studlycaps in type names.

> +/*
> +** Definitions for MR_LIVE_LVAL

The following code does not define MR_LIVE_LVAL.

> +** MR_LIVE_LVAL describes an lval. This includes:
> +** 	- stack slots, registers, and special lvals such as succip, hp,
> +** 	  etc.
> +**
> +** The data is encoded using an 8 bit low tag, the rest of the word is a 
> +** data field describing which stack slot number or register number.
> +**
> +**  Lval		Tag	Rest
> +**  r(Num)		 0	Num
> +**  f(Num)		 1	Num
> +**  stackvar(Num)	 2	Num
> +**  framevar(Num)	 3	Num
> +**  succip		 4
> +**  maxfr		 5
> +**  curfr		 6
> +**  hp			 7
> +**  sp			 8
> +**  unknown		 9		(The location is not known)
> +**
> +** The type MR_Lval_Type describes the different tag values.
> +**
> +*/
> +
> +typedef enum { 
> +	MR_LVAL_TYPE_R,
> +	MR_LVAL_TYPE_F,
> +	MR_LVAL_TYPE_STACKVAR,
> +	MR_LVAL_TYPE_FRAMEVAR,
> +	MR_LVAL_TYPE_SUCCIP,
> +	MR_LVAL_TYPE_MAXFR,
> +	MR_LVAL_TYPE_CURFR,
> +	MR_LVAL_TYPE_HP,
> +	MR_LVAL_TYPE_SP,
> +	MR_LVAL_TYPE_UNKNOWN 
> +} MR_Lval_Type;
> +
> +#define MR_LIVE_LVAL_TAGBITS	8

Link this to the part of the compiler that also defines these, in both
directions.

> +/*
> +** Definitions for MR_LIVE_TYPE

The following code does not define MR_LIVE_TYPE.

> +**
> +** MR_LIVE_TYPE describes a live date. This includes:
> +** 	- succip, hp, curfr, maxfr, redoip, and
> +** 	  mercury data values (vars) that reference a type and an inst.

I don't know if I would call something a "date" if it included those things
:-)

> +** The data is encoded such that low values (less than
> +** TYPELAYOUT_MAX_VARINT) represent succip, hp, etc.  Higher values
> +** are pointers to a 2 cell, containing a type_info and an instantiation
> +** represention.
> +**
> +*/

2 cell -> 2 word cell

> +typedef enum { 
> +	MR_LIVE_TYPE_FRAMEVAR,
> +	MR_LIVE_TYPE_SUCCIP,
> +	MR_LIVE_TYPE_HP,
> +	MR_LIVE_TYPE_CURFR,
> +	MR_LIVE_TYPE_MAXFR,
> +	MR_LIVE_TYPE_REDOIP,
> +	MR_LIVE_TYPE_UNWANTED 
> +} MR_Lval_Type_NonVar;

What is MR_LIVE_TYPE_FRAMEVAR? Vars may be on the det stack, and the value
of MR_LIVE_TYPE_FRAMEVAR is less than TYPELAYOUT_MAX_VARINT, so I must
be missing something.

> +typedef struct { 
> +	Word	typeinfo;
> +	Word	inst;
> +} MR_Lval_Type_Var;

This has nothing to do with type variables or lvals. I suggest
MR_var_shape_info.

Either use field names typeinfo and instinfo, or type and inst.

> +/*
> +** Macros to support hand-written C code.
> +*/
> +
> +/*
> +** Define a stack layout for a label that you know very little about.
> +** It's just a generic entry label, no useful information, except
> +** the code address for the label.
> +*/ 
> +#ifdef MR_USE_STACK_LAYOUTS
> + #define MR_MAKE_STACK_LAYOUT_ENTRY(l) 				
       	\
> + const struct mercury_data__stack_layout__##l##_struct {		\
> +	Code * f1;							\
> +	Integer f2;							\
> +	Integer f3;							\
> +	Integer f4;							\
> + } mercury_data__stack_layout__##l = {				
       	\
> +	STATIC(l),							\
> +	(Integer) -1,	/* Unknown number of stack slots */		\
> +	(Integer) -1, 	/* Unknown code model */			\
> +        (Integer) MR_LVAL_TYPE_UNKNOWN 	/* Unknown succip location */
       	\
> + };
> +#else
> + #define MR_MAKE_STACK_LAYOUT_ENTRY(l)        
> +#endif	/* MR_USE_STACK_LAYOUTS */

It should be relatively easy to do better than this, with a macro that
takes two more arguments: a stack indicator and the stack frame size.
Succip will be stored in the bottom stack slot on the det stack, and
in a fixed slot on the nondet stack.

> +/*
> +** Define a stack layout for an internal label. Need to supply the
> +** label name (l) and the entry label name (e).
> +**
> +** The only useful information in this structure is the code address
> +** and the reference to the entry for this label.
> +*/ 

This macro and the following one are very similar, so add a comment that
explains the difference.

> +/*
> +** Macros to support stack layouts.
> +*/
> +#define MR_CONT_STACK_LAYOUT_GET_LABEL_ADDRESS(s)		\
> +		((Code *) field(0, (s), 0))
> +
> +#define MR_ENTRY_STACK_LAYOUT_GET_LABEL_ADDRESS(s)		\
> +		MR_CONT_STACK_LAYOUT_GET_LABEL_ADDRESS(s)
> +
> +#define MR_CONT_STACK_LAYOUT_GET_ENTRY_LAYOUT(s)		\
> +		(field(0, (s), 1))
> +
> +#define MR_ENTRY_STACK_LAYOUT_GET_NUM_SLOTS(s)			\
> +		(field(0, (s), 1))
> +
> +#define MR_ENTRY_STACK_LAYOUT_GET_CODE_MODEL(s)			\
> +		(field(0, (s), 2))
> +
> +#define MR_ENTRY_STACK_LAYOUT_GET_SUCCIP_LOC(s)			\
> +		(field(0, (s), 3))

Wouldn't it be easier to define a C struct for these?

About the renaming of the .mod files: we should aim to have all the standard
.h files that are referenced from compiler-generated .c files to have a
mercury_ prefix. This would require the corresponding source files to also
have the prefix. The rename now would be a chance to introduce this while
minimising disruption (for a changeover period, we should support both
forms of the header file names, with one file #including the other).

Zoltan.



More information about the developers mailing list