[m-rev.] for review: conditional structure reuse for LLDS backends
Peter Wang
novalazy at gmail.com
Wed Jan 30 16:05:24 AEDT 2008
[Pending bootchecks in more grades.]
Estimated hours taken: 15
Branches: main
Implement conditional structure reuse for LLDS backends using Boehm GC.
Verify at run time, just before reusing a dead cell, that the base address of
the cell was dynamically allocated. If not, fall back to allocating a new
object on the heap. This makes structure reuse safe without having to disable
static data.
In the simple case, the generated C code looks like this:
MR_tag_reuse_or_alloc_heap(dest, tag, addr_of_reuse_cell,
MR_tag_alloc_heap(dest, tag, count));
...assign fields...
If some of the fields are known to already have the correct values then we can
avoid assigning them. We need to handle both reuse and non-reuse cases:
MR_tag_reuse_or_alloc_heap_flag(dest, flag_reg, tag, addr_of_reuse_cell,
MR_tag_alloc_heap(dest, tag, count));
/* flag_reg is non-zero iff reuse is possible */
if (flag_reg) {
goto skip;
}
...assign fields which don't need to be assigned in reuse case...
skip:
...assign fields which must be assigned in both cases...
It may be that it is not worth the branch to avoid assigning known fields.
I haven't yet checked.
compiler/llds.m:
Extend the `incr_hp' instruction to holds information for structure
reuse.
compiler/code_info.m:
Generate a label and pass it to `var_locn_assign_cell_to_var'. The
label is only needed for the type of code shown above.
compiler/var_locn.m:
Change the code generated for cell reuse. Rather than assigning the
dead cell's address to the target lval unconditionally, generate an
`incr_hp' instruction with the reuse field filled in.
Generate code that avoids filling in known fields if possible.
Abort if we see `construct_statically(_)' in
`var_locn_assign_dynamic_cell_to_var'.
runtime/mercury_heap.h:
Add a macro to check if an address is between
`GC_least_plausible_heap_addr' and `GC_greatest_plausible_heap_addr',
which are therefore in the heap.
Add macros to conditionally reuse a cell or otherwise fall back to
allocating a new object.
compiler/llds_out.m:
Call the new macros in `mercury_heap.h' for `incr_hp' instructions
with reuse information filled in.
compiler/dupelim.m:
compiler/dupproc.m:
compiler/exprn_aux.m:
compiler/global_data.m:
compiler/jumpopt.m:
compiler/livemap.m:
compiler/llds_to_x86_64.m:
compiler/middle_rec.m:
compiler/opt_debug.m:
compiler/opt_util.m:
compiler/reassign.m:
compiler/unify_gen.m:
compiler/use_local_vars.m:
Conform to the changed `incr_hp' instruction.
Index: compiler/code_info.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/compiler/code_info.m,v
retrieving revision 1.358
diff -u -r1.358 code_info.m
--- compiler/code_info.m 29 Jan 2008 04:59:36 -0000 1.358
+++ compiler/code_info.m 30 Jan 2008 03:57:50 -0000
@@ -3677,12 +3677,13 @@
assign_cell_to_var(Var, ReserveWordAtStart, Ptag, MaybeRvals, HowToConstruct,
MaybeSize, FieldAddrs, TypeMsg, MayUseAtomic, Code, !CI) :-
+ get_next_label(Label, !CI),
get_var_locn_info(!.CI, VarLocnInfo0),
get_static_cell_info(!.CI, StaticCellInfo0),
get_module_info(!.CI, ModuleInfo),
var_locn_assign_cell_to_var(ModuleInfo, Var, ReserveWordAtStart, Ptag,
MaybeRvals, HowToConstruct, MaybeSize, FieldAddrs, TypeMsg,
- MayUseAtomic, Code, StaticCellInfo0, StaticCellInfo,
+ MayUseAtomic, Label, Code, StaticCellInfo0, StaticCellInfo,
VarLocnInfo0, VarLocnInfo),
set_static_cell_info(StaticCellInfo, !CI),
set_var_locn_info(VarLocnInfo, !CI).
Index: compiler/dupelim.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/compiler/dupelim.m,v
retrieving revision 1.92
diff -u -r1.92 dupelim.m
--- compiler/dupelim.m 11 Oct 2007 11:45:17 -0000 1.92
+++ compiler/dupelim.m 30 Jan 2008 03:57:50 -0000
@@ -344,7 +344,7 @@
Instr = restore_maxfr(Lval)
;
Instr0 = incr_hp(Lval0, MaybeTag, MaybeOffset, Rval0, Msg,
- MayUseAtomic, MaybeRegionRval0),
+ MayUseAtomic, MaybeRegionRval0, MaybeReuse0),
standardize_lval(Lval0, Lval),
standardize_rval(Rval0, Rval),
(
@@ -355,8 +355,24 @@
MaybeRegionRval0 = no,
MaybeRegionRval = MaybeRegionRval0
),
+ (
+ MaybeReuse0 = llds_reuse(ReuseRval0, MaybeFlagLval0),
+ standardize_rval(ReuseRval0, ReuseRval),
+ (
+ MaybeFlagLval0 = yes(FlagLval0),
+ standardize_lval(FlagLval0, FlagLval),
+ MaybeFlagLval = yes(FlagLval)
+ ;
+ MaybeFlagLval0 = no,
+ MaybeFlagLval = no
+ ),
+ MaybeReuse = llds_reuse(ReuseRval, MaybeFlagLval)
+ ;
+ MaybeReuse0 = no_llds_reuse,
+ MaybeReuse = no_llds_reuse
+ ),
Instr = incr_hp(Lval, MaybeTag, MaybeOffset, Rval, Msg,
- MayUseAtomic, MaybeRegionRval)
+ MayUseAtomic, MaybeRegionRval, MaybeReuse)
;
Instr0 = mark_hp(Lval0),
standardize_lval(Lval0, Lval),
@@ -635,10 +651,10 @@
)
;
InstrA = incr_hp(LvalA, MaybeTag, MaybeOffset, RvalA, Msg,
- MayUseAtomic, MaybeRegionRvalA),
+ MayUseAtomic, MaybeRegionRvalA, MaybeReuseA),
(
InstrB = incr_hp(LvalB, MaybeTag, MaybeOffset, RvalB, Msg,
- MayUseAtomic, MaybeRegionRvalB),
+ MayUseAtomic, MaybeRegionRvalB, MaybeReuseB),
most_specific_lval(LvalA, LvalB, Lval),
most_specific_rval(RvalA, RvalB, Rval),
(
@@ -650,10 +666,30 @@
MaybeRegionRvalA = no,
MaybeRegionRvalB = no,
MaybeRegionRval = no
+ ),
+ (
+ MaybeReuseA = llds_reuse(ReuseRvalA, MaybeFlagLvalA),
+ MaybeReuseB = llds_reuse(ReuseRvalB, MaybeFlagLvalB),
+ most_specific_rval(ReuseRvalA, ReuseRvalB, ReuseRval),
+ (
+ MaybeFlagLvalA = yes(FlagLvalA),
+ MaybeFlagLvalB = yes(FlagLvalB),
+ most_specific_lval(FlagLvalA, FlagLvalB, FlagLval),
+ MaybeFlagLval = yes(FlagLval)
+ ;
+ MaybeFlagLvalA = no,
+ MaybeFlagLvalB = no,
+ MaybeFlagLval = no
+ ),
+ MaybeReuse = llds_reuse(ReuseRval, MaybeFlagLval)
+ ;
+ MaybeReuseA = no_llds_reuse,
+ MaybeReuseB = no_llds_reuse,
+ MaybeReuse = no_llds_reuse
)
->
MaybeInstr = yes(incr_hp(Lval, MaybeTag, MaybeOffset, Rval,
- Msg, MayUseAtomic, MaybeRegionRval))
+ Msg, MayUseAtomic, MaybeRegionRval, MaybeReuse))
;
MaybeInstr = no
)
Index: compiler/dupproc.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/compiler/dupproc.m,v
retrieving revision 1.23
diff -u -r1.23 dupproc.m
--- compiler/dupproc.m 30 Dec 2007 08:23:37 -0000 1.23
+++ compiler/dupproc.m 30 Jan 2008 03:57:50 -0000
@@ -242,7 +242,7 @@
; Instr = arbitrary_c_code(_, _, _)
; Instr = save_maxfr(_)
; Instr = restore_maxfr(_)
- ; Instr = incr_hp(_, _, _, _, _, _, _)
+ ; Instr = incr_hp(_, _, _, _, _, _, _, _)
; Instr = mark_hp(_)
; Instr = restore_hp(_)
; Instr = free_heap(_)
Index: compiler/exprn_aux.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/compiler/exprn_aux.m,v
retrieving revision 1.86
diff -u -r1.86 exprn_aux.m
--- compiler/exprn_aux.m 23 Nov 2007 07:35:01 -0000 1.86
+++ compiler/exprn_aux.m 30 Jan 2008 03:57:50 -0000
@@ -314,19 +314,35 @@
Uinstr = restore_maxfr(Lval)
;
Uinstr0 = incr_hp(Lval0, MaybeTag, MO, Rval0, TypeCtor,
- MayUseAtomic, MaybeRegionRval0),
+ MayUseAtomic, MaybeRegionRval0, MaybeReuse0),
Transform(Lval0, Lval, !Acc),
transform_lval_in_rval(Transform, Rval0, Rval, !Acc),
(
MaybeRegionRval0 = no,
- MaybeRegionRval = MaybeRegionRval0
+ MaybeRegionRval = no
;
MaybeRegionRval0 = yes(RegionRval0),
transform_lval_in_rval(Transform, RegionRval0, RegionRval, !Acc),
MaybeRegionRval = yes(RegionRval)
),
+ (
+ MaybeReuse0 = no_llds_reuse,
+ MaybeReuse = no_llds_reuse
+ ;
+ MaybeReuse0 = llds_reuse(ReuseRval0, MaybeFlagLval0),
+ transform_lval_in_rval(Transform, ReuseRval0, ReuseRval, !Acc),
+ (
+ MaybeFlagLval0 = no,
+ MaybeFlagLval = no
+ ;
+ MaybeFlagLval0 = yes(FlagLval0),
+ Transform(FlagLval0, FlagLval, !Acc),
+ MaybeFlagLval = yes(FlagLval)
+ ),
+ MaybeReuse = llds_reuse(ReuseRval, MaybeFlagLval)
+ ),
Uinstr = incr_hp(Lval, MaybeTag, MO, Rval, TypeCtor,
- MayUseAtomic, MaybeRegionRval)
+ MayUseAtomic, MaybeRegionRval, MaybeReuse)
;
Uinstr0 = mark_hp(Lval0),
Transform(Lval0, Lval, !Acc),
Index: compiler/global_data.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/compiler/global_data.m,v
retrieving revision 1.35
diff -u -r1.35 global_data.m
--- compiler/global_data.m 11 Oct 2007 11:45:17 -0000 1.35
+++ compiler/global_data.m 30 Jan 2008 03:57:51 -0000
@@ -936,7 +936,7 @@
Instr = restore_maxfr(Lval)
;
Instr0 = incr_hp(Lval0, MaybeTag, MaybeOffset, SizeRval0, Prof,
- Atomic, MaybeRegion0),
+ Atomic, MaybeRegion0, MaybeReuse0),
Lval = remap_lval(Remap, Lval0),
SizeRval = remap_rval(Remap, SizeRval0),
(
@@ -947,8 +947,24 @@
MaybeRegion0 = no,
MaybeRegion = no
),
+ (
+ MaybeReuse0 = llds_reuse(Reuse0, MaybeFlag0),
+ Reuse = remap_rval(Remap, Reuse0),
+ (
+ MaybeFlag0 = yes(Flag0),
+ Flag = remap_lval(Remap, Flag0),
+ MaybeFlag = yes(Flag)
+ ;
+ MaybeFlag0 = no,
+ MaybeFlag = no
+ ),
+ MaybeReuse = llds_reuse(Reuse, MaybeFlag)
+ ;
+ MaybeReuse0 = no_llds_reuse,
+ MaybeReuse = no_llds_reuse
+ ),
Instr = incr_hp(Lval, MaybeTag, MaybeOffset, SizeRval, Prof,
- Atomic, MaybeRegion)
+ Atomic, MaybeRegion, MaybeReuse)
;
Instr0 = mark_hp(Lval0),
Lval = remap_lval(Remap, Lval0),
Index: compiler/jumpopt.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/compiler/jumpopt.m,v
retrieving revision 1.109
diff -u -r1.109 jumpopt.m
--- compiler/jumpopt.m 30 Dec 2007 08:23:44 -0000 1.109
+++ compiler/jumpopt.m 30 Jan 2008 03:57:51 -0000
@@ -828,7 +828,7 @@
; Uinstr0 = mark_ticket_stack(_)
; Uinstr0 = mark_hp(_)
; Uinstr0 = free_heap(_)
- ; Uinstr0 = incr_hp(_, _, _, _, _, _, _)
+ ; Uinstr0 = incr_hp(_, _, _, _, _, _, _, _)
; Uinstr0 = restore_hp(_)
; Uinstr0 = init_sync_term(_, _)
),
Index: compiler/livemap.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/compiler/livemap.m,v
retrieving revision 1.91
diff -u -r1.91 livemap.m
--- compiler/livemap.m 30 Dec 2007 08:23:45 -0000 1.91
+++ compiler/livemap.m 30 Jan 2008 03:57:51 -0000
@@ -248,7 +248,8 @@
Uinstr0 = restore_maxfr(Lval),
livemap.make_live_in_rval(lval(Lval), !Livevals)
;
- Uinstr0 = incr_hp(Lval, _, _, Rval, _, _, MaybeRegionRval),
+ Uinstr0 = incr_hp(Lval, _, _, SizeRval, _, _, MaybeRegionRval,
+ MaybeReuse),
% Make dead the variable assigned, but make any variables
% needed to access it live. Make the variables in the size
@@ -258,15 +259,29 @@
% common. This is why doing the deletion first works.
svset.delete(Lval, !Livevals),
- opt_util.lval_access_rvals(Lval, Rvals0),
+ opt_util.lval_access_rvals(Lval, Rvals),
+ livemap.make_live_in_rvals(Rvals, !Livevals),
+ livemap.make_live_in_rval(SizeRval, !Livevals),
(
- MaybeRegionRval = no,
- Rvals = [Rval | Rvals0]
+ MaybeRegionRval = no
;
MaybeRegionRval = yes(RegionRval),
- Rvals = [Rval, RegionRval | Rvals0]
+ livemap.make_live_in_rval(RegionRval, !Livevals)
),
- livemap.make_live_in_rvals(Rvals, !Livevals)
+ (
+ MaybeReuse = no_llds_reuse
+ ;
+ MaybeReuse = llds_reuse(ReuseRval, MaybeFlagLval),
+ livemap.make_live_in_rval(ReuseRval, !Livevals),
+ (
+ MaybeFlagLval = no
+ ;
+ MaybeFlagLval = yes(FlagLval),
+ svset.delete(FlagLval, !Livevals),
+ opt_util.lval_access_rvals(FlagLval, FlagRvals),
+ livemap.make_live_in_rvals(FlagRvals, !Livevals)
+ )
+ )
;
Uinstr0 = mark_hp(Lval),
svset.delete(Lval, !Livevals),
Index: compiler/llds.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/compiler/llds.m,v
retrieving revision 1.358
diff -u -r1.358 llds.m
--- compiler/llds.m 23 Jan 2008 11:44:46 -0000 1.358
+++ compiler/llds.m 30 Jan 2008 03:57:51 -0000
@@ -326,9 +326,9 @@
% lval was saved with save_maxfr.
; incr_hp(lval, maybe(tag), maybe(int), rval, string,
- may_use_atomic_alloc, maybe(rval))
+ may_use_atomic_alloc, maybe(rval), llds_reuse)
% incr_hp(Target, MaybeTag, MaybeOffset, SizeRval, TypeMsg,
- % MayUseAtomicAlloc, MaybeRegionId)
+ % MayUseAtomicAlloc, MaybeRegionId, MaybeReuse)
%
% Get a memory block of a size given by SizeRval and put its
% address in Target, possibly after incrementing it by Offset words
@@ -339,7 +339,11 @@
% of the Boehm gc allocator calls. If MaybeRegionId =
% yes(RegionId), then the block should be allocated in the region
% identified by RegionId (i.e. in the region whose header RegionId
- % points to).
+ % points to). If MaybeReuse = llds_reuse(ReuseRval,
+ % MaybeFlagLval), then we should try to reuse the cell ReuseRval
+ % for the block. If MaybeFlagLval = yes(FlagLval) then FlagLval
+ % needs to be set to true or false indicate whether reuse was
+ % really possible.
; mark_hp(lval)
% Tell the heap sub-system to store a marker (for later use in
@@ -620,6 +624,14 @@
---> det_stack_proc
; nondet_stack_proc.
+:- type llds_reuse
+ ---> no_llds_reuse
+ ; llds_reuse(
+ rval, % The cell to reuse.
+ maybe(lval) % An optional lval to set to indicate
+ % whether cell reuse was actually possible.
+ ).
+
% Procedures defined by nondet pragma C codes must have some way of
% preserving information after a success, so that when control
% backtracks to the procedure, the C code knows what to do.
Index: compiler/llds_out.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/compiler/llds_out.m,v
retrieving revision 1.323
diff -u -r1.323 llds_out.m
--- compiler/llds_out.m 23 Jan 2008 11:44:46 -0000 1.323
+++ compiler/llds_out.m 30 Jan 2008 03:57:53 -0000
@@ -1959,8 +1959,8 @@
output_lval_decls(Lval, !DeclSet, !IO).
output_instr_decls(_, restore_maxfr(Lval), !DeclSet, !IO) :-
output_lval_decls(Lval, !DeclSet, !IO).
-output_instr_decls(_, incr_hp(Lval, _Tag, _, Rval, _, _, MaybeRegionRval),
- !DeclSet, !IO) :-
+output_instr_decls(_, incr_hp(Lval, _Tag, _, Rval, _, _, MaybeRegionRval,
+ MaybeReuse), !DeclSet, !IO) :-
output_lval_decls(Lval, !DeclSet, !IO),
output_rval_decls(Rval, !DeclSet, !IO),
(
@@ -1968,6 +1968,18 @@
output_rval_decls(RegionRval, !DeclSet, !IO)
;
MaybeRegionRval = no
+ ),
+ (
+ MaybeReuse = llds_reuse(ReuseRval, MaybeFlagLval),
+ output_rval_decls(ReuseRval, !DeclSet, !IO),
+ (
+ MaybeFlagLval = yes(FlagLval),
+ output_lval_decls(FlagLval, !DeclSet, !IO)
+ ;
+ MaybeFlagLval = no
+ )
+ ;
+ MaybeReuse = no_llds_reuse
).
output_instr_decls(_, mark_hp(Lval), !DeclSet, !IO) :-
output_lval_decls(Lval, !DeclSet, !IO).
@@ -2418,136 +2430,54 @@
output_lval(Lval, !IO),
io.write_string(");\n", !IO).
-output_instruction(incr_hp(Lval, MaybeTag, MaybeOffset, Rval, TypeMsg,
- MayUseAtomicAlloc, MaybeRegionRval), ProfInfo, !IO) :-
+output_instruction(incr_hp(Lval, MaybeTag, MaybeOffset, SizeRval, TypeMsg,
+ MayUseAtomicAlloc, MaybeRegionRval, MaybeReuse), ProfInfo, !IO) :-
+ io.write_string("\t", !IO),
(
- MaybeRegionRval = yes(RegionRval),
- (
- MaybeTag = no,
- io.write_string("\tMR_alloc_in_region(", !IO),
- output_lval_as_word(Lval, !IO)
- ;
- MaybeTag = yes(Tag),
- io.write_string("\tMR_tag_alloc_in_region(", !IO),
- output_lval_as_word(Lval, !IO),
- io.write_string(", ", !IO),
- output_tag(Tag, !IO)
- ),
- io.write_string(", ", !IO),
- output_rval(RegionRval, !IO),
- io.write_string(", ", !IO),
- output_rval_as_type(Rval, word, !IO),
- io.write_string(");\n", !IO)
+ MaybeReuse = no_llds_reuse,
+ output_incr_hp_no_reuse(Lval, MaybeTag, MaybeOffset, SizeRval,
+ TypeMsg, MayUseAtomicAlloc, MaybeRegionRval, ProfInfo, !IO)
;
- MaybeRegionRval = no,
- globals.io_lookup_bool_option(profile_memory, ProfMem, !IO),
+ MaybeReuse = llds_reuse(ReuseRval, MaybeFlagLval),
(
- ProfMem = yes,
+ MaybeTag = no,
(
- MaybeTag = no,
- (
- MayUseAtomicAlloc = may_not_use_atomic_alloc,
- io.write_string("\tMR_offset_incr_hp_msg(", !IO)
- ;
- MayUseAtomicAlloc = may_use_atomic_alloc,
- io.write_string("\tMR_offset_incr_hp_atomic_msg(", !IO)
- ),
- output_lval_as_word(Lval, !IO)
- ;
- MaybeTag = yes(Tag),
- (
- MayUseAtomicAlloc = may_not_use_atomic_alloc,
- io.write_string("\tMR_tag_offset_incr_hp_msg(", !IO)
- ;
- MayUseAtomicAlloc = may_use_atomic_alloc,
- io.write_string(
- "\tMR_tag_offset_incr_hp_atomic_msg(", !IO)
- ),
+ MaybeFlagLval = yes(FlagLval),
+ io.write_string("MR_reuse_or_alloc_heap_flag(", !IO),
output_lval_as_word(Lval, !IO),
io.write_string(", ", !IO),
- output_tag(Tag, !IO)
- ),
- io.write_string(", ", !IO),
- (
- MaybeOffset = no,
- io.write_string("0, ", !IO)
+ output_lval_as_word(FlagLval, !IO)
;
- MaybeOffset = yes(Offset),
- io.write_int(Offset, !IO),
- io.write_string(", ", !IO)
- ),
- output_rval_as_type(Rval, word, !IO),
- io.write_string(", ", !IO),
- ProfInfo = CallerLabel - _,
- output_label(CallerLabel, !IO),
- io.write_string(", """, !IO),
- c_util.output_quoted_string(TypeMsg, !IO),
- io.write_string(""");\n", !IO)
- ;
- ProfMem = no,
- (
- MaybeTag = no,
- (
- MaybeOffset = yes(_),
- (
- MayUseAtomicAlloc = may_not_use_atomic_alloc,
- io.write_string("\tMR_offset_incr_hp(", !IO)
- ;
- MayUseAtomicAlloc = may_use_atomic_alloc,
- io.write_string("\tMR_offset_incr_hp_atomic(", !IO)
- )
- ;
- MaybeOffset = no,
- (
- MayUseAtomicAlloc = may_not_use_atomic_alloc,
- io.write_string("\tMR_alloc_heap(", !IO)
- ;
- MayUseAtomicAlloc = may_use_atomic_alloc,
- io.write_string("\tMR_alloc_heap_atomic(", !IO)
- )
- ),
+ MaybeFlagLval = no,
+ io.write_string("MR_reuse_or_alloc_heap(", !IO),
output_lval_as_word(Lval, !IO)
- ;
- MaybeTag = yes(Tag),
- (
- MaybeOffset = yes(_),
- (
- MayUseAtomicAlloc = may_not_use_atomic_alloc,
- io.write_string("\tMR_tag_offset_incr_hp(", !IO)
- ;
- MayUseAtomicAlloc = may_use_atomic_alloc,
- io.write_string(
- "\tMR_tag_offset_incr_hp_atomic(", !IO)
- ),
- output_lval_as_word(Lval, !IO),
- io.write_string(", ", !IO),
- output_tag(Tag, !IO)
- ;
- MaybeOffset = no,
- (
- MayUseAtomicAlloc = may_not_use_atomic_alloc,
- io.write_string("\tMR_tag_alloc_heap(", !IO)
- ;
- MayUseAtomicAlloc = may_use_atomic_alloc,
- io.write_string("\tMR_tag_alloc_heap_atomic(", !IO)
- ),
- output_lval_as_word(Lval, !IO),
- io.write_string(", ", !IO),
- io.write_int(Tag, !IO)
- )
- ),
- io.write_string(", ", !IO),
+ )
+ ;
+ MaybeTag = yes(Tag),
(
- MaybeOffset = yes(Offset),
- io.write_int(Offset, !IO),
- io.write_string(", ", !IO)
+ MaybeFlagLval = yes(FlagLval),
+ io.write_string("MR_tag_reuse_or_alloc_heap_flag(", !IO),
+ output_lval_as_word(Lval, !IO),
+ io.write_string(", ", !IO),
+ output_tag(Tag, !IO),
+ io.write_string(", ", !IO),
+ output_lval_as_word(FlagLval, !IO)
;
- MaybeOffset = no
- ),
- output_rval_as_type(Rval, word, !IO),
- io.write_string(");\n", !IO)
- )
- ).
+ MaybeFlagLval = no,
+ io.write_string("MR_tag_reuse_or_alloc_heap(", !IO),
+ output_lval_as_word(Lval, !IO),
+ io.write_string(", ", !IO),
+ output_tag(Tag, !IO)
+ )
+ ),
+ io.write_string(", ", !IO),
+ output_rval(ReuseRval, !IO),
+ io.write_string(", ", !IO),
+ output_incr_hp_no_reuse(Lval, MaybeTag, MaybeOffset, SizeRval,
+ TypeMsg, MayUseAtomicAlloc, MaybeRegionRval, ProfInfo, !IO),
+ io.write_string(")", !IO)
+ ),
+ io.write_string(";\n", !IO).
output_instruction(mark_hp(Lval), _, !IO) :-
io.write_string("\tMR_mark_hp(", !IO),
@@ -2768,6 +2698,141 @@
output_label_as_code_addr(Label, !IO),
io.write_string(");\n", !IO).
+:- pred output_incr_hp_no_reuse(lval::in, maybe(tag)::in, maybe(int)::in,
+ rval::in, string::in, may_use_atomic_alloc::in, maybe(rval)::in,
+ pair(label, set_tree234(label))::in, io::di, io::uo) is det.
+
+output_incr_hp_no_reuse(Lval, MaybeTag, MaybeOffset, Rval, TypeMsg,
+ MayUseAtomicAlloc, MaybeRegionRval, ProfInfo, !IO) :-
+ (
+ MaybeRegionRval = yes(RegionRval),
+ (
+ MaybeTag = no,
+ io.write_string("MR_alloc_in_region(", !IO),
+ output_lval_as_word(Lval, !IO)
+ ;
+ MaybeTag = yes(Tag),
+ io.write_string("MR_tag_alloc_in_region(", !IO),
+ output_lval_as_word(Lval, !IO),
+ io.write_string(", ", !IO),
+ output_tag(Tag, !IO)
+ ),
+ io.write_string(", ", !IO),
+ output_rval(RegionRval, !IO),
+ io.write_string(", ", !IO),
+ output_rval_as_type(Rval, word, !IO),
+ io.write_string(")", !IO)
+ ;
+ MaybeRegionRval = no,
+ globals.io_lookup_bool_option(profile_memory, ProfMem, !IO),
+ (
+ ProfMem = yes,
+ (
+ MaybeTag = no,
+ (
+ MayUseAtomicAlloc = may_not_use_atomic_alloc,
+ io.write_string("MR_offset_incr_hp_msg(", !IO)
+ ;
+ MayUseAtomicAlloc = may_use_atomic_alloc,
+ io.write_string("MR_offset_incr_hp_atomic_msg(", !IO)
+ ),
+ output_lval_as_word(Lval, !IO)
+ ;
+ MaybeTag = yes(Tag),
+ (
+ MayUseAtomicAlloc = may_not_use_atomic_alloc,
+ io.write_string("MR_tag_offset_incr_hp_msg(", !IO)
+ ;
+ MayUseAtomicAlloc = may_use_atomic_alloc,
+ io.write_string(
+ "MR_tag_offset_incr_hp_atomic_msg(", !IO)
+ ),
+ output_lval_as_word(Lval, !IO),
+ io.write_string(", ", !IO),
+ output_tag(Tag, !IO)
+ ),
+ io.write_string(", ", !IO),
+ (
+ MaybeOffset = no,
+ io.write_string("0, ", !IO)
+ ;
+ MaybeOffset = yes(Offset),
+ io.write_int(Offset, !IO),
+ io.write_string(", ", !IO)
+ ),
+ output_rval_as_type(Rval, word, !IO),
+ io.write_string(", ", !IO),
+ ProfInfo = CallerLabel - _,
+ output_label(CallerLabel, !IO),
+ io.write_string(", """, !IO),
+ c_util.output_quoted_string(TypeMsg, !IO),
+ io.write_string(""")", !IO)
+ ;
+ ProfMem = no,
+ (
+ MaybeTag = no,
+ (
+ MaybeOffset = yes(_),
+ (
+ MayUseAtomicAlloc = may_not_use_atomic_alloc,
+ io.write_string("MR_offset_incr_hp(", !IO)
+ ;
+ MayUseAtomicAlloc = may_use_atomic_alloc,
+ io.write_string("MR_offset_incr_hp_atomic(", !IO)
+ )
+ ;
+ MaybeOffset = no,
+ (
+ MayUseAtomicAlloc = may_not_use_atomic_alloc,
+ io.write_string("MR_alloc_heap(", !IO)
+ ;
+ MayUseAtomicAlloc = may_use_atomic_alloc,
+ io.write_string("MR_alloc_heap_atomic(", !IO)
+ )
+ ),
+ output_lval_as_word(Lval, !IO)
+ ;
+ MaybeTag = yes(Tag),
+ (
+ MaybeOffset = yes(_),
+ (
+ MayUseAtomicAlloc = may_not_use_atomic_alloc,
+ io.write_string("MR_tag_offset_incr_hp(", !IO)
+ ;
+ MayUseAtomicAlloc = may_use_atomic_alloc,
+ io.write_string(
+ "MR_tag_offset_incr_hp_atomic(", !IO)
+ ),
+ output_lval_as_word(Lval, !IO),
+ io.write_string(", ", !IO),
+ output_tag(Tag, !IO)
+ ;
+ MaybeOffset = no,
+ (
+ MayUseAtomicAlloc = may_not_use_atomic_alloc,
+ io.write_string("MR_tag_alloc_heap(", !IO)
+ ;
+ MayUseAtomicAlloc = may_use_atomic_alloc,
+ io.write_string("MR_tag_alloc_heap_atomic(", !IO)
+ ),
+ output_lval_as_word(Lval, !IO),
+ io.write_string(", ", !IO),
+ io.write_int(Tag, !IO)
+ )
+ ),
+ io.write_string(", ", !IO),
+ (
+ MaybeOffset = yes(Offset),
+ io.write_int(Offset, !IO),
+ io.write_string(", ", !IO)
+ ;
+ MaybeOffset = no
+ ),
+ output_rval_as_type(Rval, word, !IO),
+ io.write_string(")", !IO)
+ )
+ ).
+
% Our stacks grow upwards in that new stack frames have higher addresses
% than old stack frames, but within in each stack frame, we compute the
% address of stackvar N or framevar N by *subtracting* N from the address
Index: compiler/llds_to_x86_64.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/compiler/llds_to_x86_64.m,v
retrieving revision 1.10
diff -u -r1.10 llds_to_x86_64.m
--- compiler/llds_to_x86_64.m 30 Dec 2007 08:23:47 -0000 1.10
+++ compiler/llds_to_x86_64.m 30 Jan 2008 03:57:53 -0000
@@ -323,13 +323,20 @@
instr_to_x86_64(!RegMap, restore_maxfr(_), Instr) :-
Instr = [x86_64_comment("<<restore_maxfr>>")].
instr_to_x86_64(!RegMap,
- incr_hp(Lval, Tag0, Words0, Rval, _, _, MaybeRegionRval), Instrs) :-
+ incr_hp(Lval, Tag0, Words0, Rval, _, _, MaybeRegionRval,
+ MaybeReuse), Instrs) :-
(
MaybeRegionRval = no
;
MaybeRegionRval = yes(_),
unexpected(this_file, "instr_to_x86_64: encounter a region variable")
),
+ (
+ MaybeReuse = no_llds_reuse
+ ;
+ MaybeReuse = llds_reuse(_, _),
+ unexpected(this_file, "instr_to_x86_64: encounter a reuse variable")
+ ),
transform_rval(!RegMap, Rval, Res0, Res1),
transform_lval(!RegMap, Lval, Res2, Res3),
(
Index: compiler/middle_rec.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/compiler/middle_rec.m,v
retrieving revision 1.133
diff -u -r1.133 middle_rec.m
--- compiler/middle_rec.m 30 Dec 2007 08:23:48 -0000 1.133
+++ compiler/middle_rec.m 30 Jan 2008 03:57:53 -0000
@@ -525,8 +525,8 @@
find_used_registers_lval(Lval, !Used).
find_used_registers_instr(restore_maxfr(Lval), !Used) :-
find_used_registers_lval(Lval, !Used).
-find_used_registers_instr(incr_hp(Lval, _, _, Rval, _, _, MaybeRegionRval),
- !Used) :-
+find_used_registers_instr(incr_hp(Lval, _, _, Rval, _, _, MaybeRegionRval,
+ MaybeReuse), !Used) :-
find_used_registers_lval(Lval, !Used),
find_used_registers_rval(Rval, !Used),
(
@@ -534,6 +534,18 @@
find_used_registers_rval(RegionRval, !Used)
;
MaybeRegionRval = no
+ ),
+ (
+ MaybeReuse = llds_reuse(ReuseRval, MaybeFlagLval),
+ find_used_registers_rval(ReuseRval, !Used),
+ (
+ MaybeFlagLval = yes(FlagLval),
+ find_used_registers_lval(FlagLval, !Used)
+ ;
+ MaybeFlagLval = no
+ )
+ ;
+ MaybeReuse = no_llds_reuse
).
find_used_registers_instr(mark_hp(Lval), !Used) :-
find_used_registers_lval(Lval, !Used).
Index: compiler/opt_debug.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/compiler/opt_debug.m,v
retrieving revision 1.204
diff -u -r1.204 opt_debug.m
--- compiler/opt_debug.m 23 Jan 2008 11:44:46 -0000 1.204
+++ compiler/opt_debug.m 30 Jan 2008 03:57:53 -0000
@@ -793,7 +793,7 @@
Str = "restore_maxfr(" ++ dump_lval(yes(ProcLabel), Lval) ++ ")"
;
Instr = incr_hp(Lval, MaybeTag, MaybeOffset, Size, _, MayUseAtomic,
- MaybeRegionRval),
+ MaybeRegionRval, MaybeReuse),
(
MaybeTag = no,
T_str = "no"
@@ -815,10 +815,27 @@
MaybeRegionRval = yes(RegionRval),
Region_str = dump_rval(no, RegionRval)
),
+ (
+ MaybeReuse = no_llds_reuse,
+ Reuse_str = "no",
+ Flag_str = "no"
+ ;
+ MaybeReuse = llds_reuse(ReuseRval, MaybeFlagLval),
+ Reuse_str = dump_rval(no, ReuseRval),
+ (
+ MaybeFlagLval = no,
+ Flag_str = "no"
+ ;
+ MaybeFlagLval = yes(FlagLval),
+ Flag_str = dump_lval(yes(ProcLabel), FlagLval)
+ )
+ ),
Str = "incr_hp(" ++ dump_lval(yes(ProcLabel), Lval) ++ ", " ++
T_str ++ ", " ++ O_str ++ ", " ++
dump_rval(yes(ProcLabel), Size) ++ ", " ++
- dump_may_use_atomic(MayUseAtomic) ++ ", " ++ Region_str ++ ")"
+ dump_may_use_atomic(MayUseAtomic) ++ ", " ++
+ Region_str ++ ", " ++
+ Reuse_str ++ ", " ++ Flag_str ++ ")"
;
Instr = mark_hp(Lval),
Str = "mark_hp(" ++ dump_lval(yes(ProcLabel), Lval) ++ ")"
Index: compiler/opt_util.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/compiler/opt_util.m,v
retrieving revision 1.168
diff -u -r1.168 opt_util.m
--- compiler/opt_util.m 30 Dec 2007 08:23:52 -0000 1.168
+++ compiler/opt_util.m 30 Jan 2008 03:57:54 -0000
@@ -685,7 +685,7 @@
( Uinstr = comment(_)
; Uinstr = livevals(_)
; Uinstr = if_val(_, _)
- ; Uinstr = incr_hp(_, _, _, _, _, _, _)
+ ; Uinstr = incr_hp(_, _, _, _, _, _, _, _)
; Uinstr = mark_hp(_)
; Uinstr = restore_hp(_)
; Uinstr = free_heap(_)
@@ -815,7 +815,8 @@
Between = [Instr0 | Between0]
)
;
- Uinstr0 = incr_hp(Lval, _, _, Rval, _, _, MaybeRegionRval),
+ Uinstr0 = incr_hp(Lval, _, _, Rval, _, _, MaybeRegionRval,
+ MaybeReuse),
lval_refers_stackvars(Lval) = no,
rval_refers_stackvars(Rval) = no,
(
@@ -824,6 +825,18 @@
;
MaybeRegionRval = no
),
+ (
+ MaybeReuse = llds_reuse(ReuseRval, MaybeFlagLval),
+ rval_refers_stackvars(ReuseRval) = no,
+ (
+ MaybeFlagLval = yes(FlagLval),
+ lval_refers_stackvars(FlagLval) = no
+ ;
+ MaybeFlagLval = no
+ )
+ ;
+ MaybeReuse = no_llds_reuse
+ ),
no_stackvars_til_decr_sp(Instrs0, FrameSize, Between0, Remain),
Between = [Instr0 | Between0]
;
@@ -904,16 +917,31 @@
Uinstr = restore_maxfr(Lval),
Refers = lval_refers_stackvars(Lval)
;
- Uinstr = incr_hp(Lval, _, _, Rval, _, _, MaybeRegionRval),
- Refers0 = bool.or(
- lval_refers_stackvars(Lval),
- rval_refers_stackvars(Rval)),
- (
- MaybeRegionRval = no,
- Refers = Refers0
- ;
- MaybeRegionRval = yes(RegionRval),
- Refers = bool.or(Refers0, rval_refers_stackvars(RegionRval))
+ Uinstr = incr_hp(Lval, _, _, Rval, _, _, MaybeRegionRval,
+ MaybeReuse),
+ some [!Refers] (
+ !:Refers = bool.or(
+ lval_refers_stackvars(Lval),
+ rval_refers_stackvars(Rval)),
+ (
+ MaybeRegionRval = yes(RegionRval),
+ bool.or(rval_refers_stackvars(RegionRval), !Refers)
+ ;
+ MaybeRegionRval = no
+ ),
+ (
+ MaybeReuse = llds_reuse(ReuseRval, MaybeFlagLval),
+ bool.or(rval_refers_stackvars(ReuseRval), !Refers),
+ (
+ MaybeFlagLval = yes(FlagLval),
+ bool.or(lval_refers_stackvars(FlagLval), !Refers)
+ ;
+ MaybeFlagLval = no
+ )
+ ;
+ MaybeReuse = no_llds_reuse
+ ),
+ Refers = !.Refers
)
;
Uinstr = mark_hp(Lval),
@@ -1063,7 +1091,7 @@
can_instr_branch_away(if_val(_, _)) = yes.
can_instr_branch_away(save_maxfr(_)) = no.
can_instr_branch_away(restore_maxfr(_)) = no.
-can_instr_branch_away(incr_hp(_, _, _, _, _, _, _)) = no.
+can_instr_branch_away(incr_hp(_, _, _, _, _, _, _, _)) = no.
can_instr_branch_away(mark_hp(_)) = no.
can_instr_branch_away(restore_hp(_)) = no.
can_instr_branch_away(free_heap(_)) = no.
@@ -1142,7 +1170,7 @@
can_instr_fall_through(if_val(_, _)) = yes.
can_instr_fall_through(save_maxfr(_)) = yes.
can_instr_fall_through(restore_maxfr(_)) = yes.
-can_instr_fall_through(incr_hp(_, _, _, _, _, _, _)) = yes.
+can_instr_fall_through(incr_hp(_, _, _, _, _, _, _, _)) = yes.
can_instr_fall_through(mark_hp(_)) = yes.
can_instr_fall_through(restore_hp(_)) = yes.
can_instr_fall_through(free_heap(_)) = yes.
@@ -1193,7 +1221,7 @@
can_use_livevals(if_val(_, _), yes).
can_use_livevals(save_maxfr(_), no).
can_use_livevals(restore_maxfr(_), no).
-can_use_livevals(incr_hp(_, _, _, _, _, _, _), no).
+can_use_livevals(incr_hp(_, _, _, _, _, _, _, _), no).
can_use_livevals(mark_hp(_), no).
can_use_livevals(restore_hp(_), no).
can_use_livevals(free_heap(_), no).
@@ -1263,7 +1291,7 @@
instr_labels_2(if_val(_, Addr), [], [Addr]).
instr_labels_2(save_maxfr(_), [], []).
instr_labels_2(restore_maxfr(_), [], []).
-instr_labels_2(incr_hp(_, _, _, _, _, _, _), [], []).
+instr_labels_2(incr_hp(_, _, _, _, _, _, _, _), [], []).
instr_labels_2(mark_hp(_), [], []).
instr_labels_2(restore_hp(_), [], []).
instr_labels_2(free_heap(_), [], []).
@@ -1331,7 +1359,7 @@
).
possible_targets(save_maxfr(_), [], []).
possible_targets(restore_maxfr(_), [], []).
-possible_targets(incr_hp(_, _, _, _, _, _, _), [], []).
+possible_targets(incr_hp(_, _, _, _, _, _, _, _), [], []).
possible_targets(mark_hp(_), [], []).
possible_targets(restore_hp(_), [], []).
possible_targets(free_heap(_), [], []).
@@ -1422,14 +1450,31 @@
instr_rvals_and_lvals(if_val(Rval, _), [Rval], []).
instr_rvals_and_lvals(save_maxfr(Lval), [], [Lval]).
instr_rvals_and_lvals(restore_maxfr(Lval), [], [Lval]).
-instr_rvals_and_lvals(incr_hp(Lval, _, _, Rval, _, _, MaybeRegionRval),
- Rvals, [Lval]) :-
- (
- MaybeRegionRval = yes(RegionRval),
- Rvals = [Rval, RegionRval]
- ;
- MaybeRegionRval = no,
- Rvals = [Rval]
+instr_rvals_and_lvals(incr_hp(Lval, _, _, SizeRval, _, _, MaybeRegionRval,
+ MaybeReuse), Rvals, Lvals) :-
+ some [!Rvals, !Lvals] (
+ !:Rvals = [SizeRval],
+ !:Lvals = [Lval],
+ (
+ MaybeRegionRval = yes(RegionRval),
+ !:Rvals = [RegionRval | !.Rvals]
+ ;
+ MaybeRegionRval = no
+ ),
+ (
+ MaybeReuse = llds_reuse(ReuseRval, MaybeFlagLval),
+ !:Rvals = [ReuseRval | !.Rvals],
+ (
+ MaybeFlagLval = yes(FlagLval),
+ !:Lvals = [FlagLval | !.Lvals]
+ ;
+ MaybeFlagLval = no
+ )
+ ;
+ MaybeReuse = no_llds_reuse
+ ),
+ Rvals = !.Rvals,
+ Lvals = !.Lvals
).
instr_rvals_and_lvals(mark_hp(Lval), [], [Lval]).
instr_rvals_and_lvals(restore_hp(Rval), [Rval], []).
@@ -1579,7 +1624,8 @@
count_temps_lval(Lval, !R, !F).
count_temps_instr(restore_maxfr(Lval), !R, !F) :-
count_temps_lval(Lval, !R, !F).
-count_temps_instr(incr_hp(Lval, _, _, Rval, _, _, MaybeRegionRval), !R, !F) :-
+count_temps_instr(incr_hp(Lval, _, _, Rval, _, _, MaybeRegionRval,
+ MaybeReuse), !R, !F) :-
count_temps_lval(Lval, !R, !F),
count_temps_rval(Rval, !R, !F),
(
@@ -1587,6 +1633,18 @@
count_temps_rval(RegionRval, !R, !F)
;
MaybeRegionRval = no
+ ),
+ (
+ MaybeReuse = llds_reuse(ReuseRval, MaybeFlagLval),
+ count_temps_rval(ReuseRval, !R, !F),
+ (
+ MaybeFlagLval = yes(FlagLval),
+ count_temps_lval(FlagLval, !R, !F)
+ ;
+ MaybeFlagLval = no
+ )
+ ;
+ MaybeReuse = no_llds_reuse
).
count_temps_instr(mark_hp(Lval), !R, !F) :-
count_temps_lval(Lval, !R, !F).
@@ -1845,16 +1903,31 @@
TouchRval = touches_nondet_ctrl_rval(Rval),
bool.or(TouchLval, TouchRval, Touch)
;
- Uinstr = incr_hp(Lval, _, _, Rval, _, _, MaybeRegionRval),
- Touch0 = bool.or(
- touches_nondet_ctrl_lval(Lval),
- touches_nondet_ctrl_rval(Rval)),
- (
- MaybeRegionRval = yes(RegionRval),
- Touch = bool.or(Touch0, touches_nondet_ctrl_rval(RegionRval))
- ;
- MaybeRegionRval = no,
- Touch = Touch0
+ Uinstr = incr_hp(Lval, _, _, Rval, _, _, MaybeRegionRval,
+ MaybeReuse),
+ some [!Touch] (
+ !:Touch = bool.or(
+ touches_nondet_ctrl_lval(Lval),
+ touches_nondet_ctrl_rval(Rval)),
+ (
+ MaybeRegionRval = yes(RegionRval),
+ bool.or(touches_nondet_ctrl_rval(RegionRval), !Touch)
+ ;
+ MaybeRegionRval = no
+ ),
+ (
+ MaybeReuse = llds_reuse(ReuseRval, MaybeFlagLval),
+ bool.or(touches_nondet_ctrl_rval(ReuseRval), !Touch),
+ (
+ MaybeFlagLval = yes(FlagLval),
+ bool.or(touches_nondet_ctrl_lval(FlagLval), !Touch)
+ ;
+ MaybeFlagLval = no
+ )
+ ;
+ MaybeReuse = no_llds_reuse
+ ),
+ Touch = !.Touch
)
;
Uinstr = mark_hp(Lval),
@@ -2028,7 +2101,7 @@
count_incr_hp_2([], !N).
count_incr_hp_2([llds_instr(Uinstr0, _) | Instrs], !N) :-
- ( Uinstr0 = incr_hp(_, _, _, _, _, _, _) ->
+ ( Uinstr0 = incr_hp(_, _, _, _, _, _, _, _) ->
!:N = !.N + 1
;
true
@@ -2221,7 +2294,7 @@
Uinstr = restore_maxfr(Lval)
;
Uinstr0 = incr_hp(Lval0, MaybeTag, MO, Rval0, Msg, Atomic,
- MaybeRegionRval0),
+ MaybeRegionRval0, MaybeReuse0),
(
ReplData = yes,
replace_labels_lval(Lval0, Lval, ReplMap),
@@ -2233,15 +2306,32 @@
;
MaybeRegionRval0 = no,
MaybeRegionRval = MaybeRegionRval0
+ ),
+ (
+ MaybeReuse0 = llds_reuse(ReuseRval0, MaybeFlagLval0),
+ replace_labels_rval(ReuseRval0, ReuseRval, ReplMap),
+ (
+ MaybeFlagLval0 = yes(FlagLval0),
+ replace_labels_lval(FlagLval0, FlagLval, ReplMap),
+ MaybeFlagLval = yes(FlagLval)
+ ;
+ MaybeFlagLval0 = no,
+ MaybeFlagLval = no
+ ),
+ MaybeReuse = llds_reuse(ReuseRval, MaybeFlagLval)
+ ;
+ MaybeReuse0 = no_llds_reuse,
+ MaybeReuse = no_llds_reuse
)
;
ReplData = no,
Lval = Lval0,
Rval = Rval0,
- MaybeRegionRval = MaybeRegionRval0
+ MaybeRegionRval = MaybeRegionRval0,
+ MaybeReuse = MaybeReuse0
),
Uinstr = incr_hp(Lval, MaybeTag, MO, Rval, Msg, Atomic,
- MaybeRegionRval)
+ MaybeRegionRval, MaybeReuse)
;
Uinstr0 = mark_hp(Lval0),
(
Index: compiler/reassign.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/compiler/reassign.m,v
retrieving revision 1.26
diff -u -r1.26 reassign.m
--- compiler/reassign.m 11 Oct 2007 11:45:20 -0000 1.26
+++ compiler/reassign.m 30 Jan 2008 03:57:54 -0000
@@ -225,7 +225,7 @@
!:RevInstrs = [Instr0 | !.RevInstrs],
clobber_dependents(hp, !KnownContentsMap, !DepLvalMap)
;
- Uinstr0 = incr_hp(Target, _, _, _, _, _, _),
+ Uinstr0 = incr_hp(Target, _, _, _, _, _, _, _),
!:RevInstrs = [Instr0 | !.RevInstrs],
clobber_dependents(Target, !KnownContentsMap, !DepLvalMap),
clobber_dependents(hp, !KnownContentsMap, !DepLvalMap)
Index: compiler/unify_gen.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/compiler/unify_gen.m,v
retrieving revision 1.186
diff -u -r1.186 unify_gen.m
--- compiler/unify_gen.m 30 Dec 2007 08:24:01 -0000 1.186
+++ compiler/unify_gen.m 30 Jan 2008 03:57:54 -0000
@@ -662,7 +662,7 @@
"get number of arguments"),
llds_instr(incr_hp(NewClosure, no, no,
binop(int_add, lval(NumOldArgs), NumNewArgsPlusThree_Rval),
- "closure", NewClosureMayUseAtomic, no),
+ "closure", NewClosureMayUseAtomic, no, no_llds_reuse),
"allocate new closure"),
llds_instr(assign(field(yes(0), lval(NewClosure), Zero),
lval(field(yes(0), OldClosure, Zero))),
Index: compiler/use_local_vars.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/compiler/use_local_vars.m,v
retrieving revision 1.37
diff -u -r1.37 use_local_vars.m
--- compiler/use_local_vars.m 23 Nov 2007 07:35:32 -0000 1.37
+++ compiler/use_local_vars.m 30 Jan 2008 03:57:56 -0000
@@ -178,7 +178,7 @@
Uinstr0 = assign(ToLval, _FromRval)
;
Uinstr0 = incr_hp(ToLval, _MaybeTag, _SizeRval, _MO, _Type,
- _Atomic, _)
+ _Atomic, _, _)
),
base_lval_worth_replacing(NumRealRRegs, ToLval),
MaybeMore = no
@@ -484,11 +484,11 @@
this_file, "substitute_lval_in_defn: mismatch in assign"),
Uinstr = assign(NewLval, FromRval)
; Uinstr0 = incr_hp(ToLval, MaybeTag, SizeRval, MO, Type,
- MayUseAtomic, MaybeRegionRval) ->
+ MayUseAtomic, MaybeRegionRval, MaybeReuse) ->
expect(unify(ToLval, OldLval),
this_file, "substitute_lval_in_defn: mismatch in incr_hp"),
Uinstr = incr_hp(NewLval, MaybeTag, SizeRval, MO, Type,
- MayUseAtomic, MaybeRegionRval)
+ MayUseAtomic, MaybeRegionRval, MaybeReuse)
; Uinstr0 = foreign_proc_code(D, Comps0, MCM, FNL, FL, FOL, NF, S, MD) ->
substitute_lval_in_defn_components(OldLval, NewLval, Comps0, Comps,
0, NumSubsts),
@@ -605,7 +605,7 @@
Uinstr0 = keep_assign(_, _),
exprn_aux.substitute_lval_in_instr(OldLval, NewLval, !Instr, !N)
;
- ( Uinstr0 = incr_hp(Lval, _, _, _, _, _, _)
+ ( Uinstr0 = incr_hp(Lval, _, _, _, _, _, _, _)
; Uinstr0 = save_maxfr(Lval)
; Uinstr0 = mark_hp(Lval)
),
Index: compiler/var_locn.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/compiler/var_locn.m,v
retrieving revision 1.57
diff -u -r1.57 var_locn.m
--- compiler/var_locn.m 29 Jan 2008 04:59:45 -0000 1.57
+++ compiler/var_locn.m 30 Jan 2008 03:57:56 -0000
@@ -167,7 +167,7 @@
var_locn_info::in, var_locn_info::out) is det.
% var_locn_assign_cell_to_var(ModuleInfo, Var, ReserveWordAtStart, Ptag,
- % MaybeRvals, MaybeSize, FieldAddrs, TypeMsg, MayUseAtomic, Code,
+ % MaybeRvals, MaybeSize, FieldAddrs, TypeMsg, MayUseAtomic, Label, Code,
% !StaticCellInfo, !VarLocnInfo):
%
% Generates code to assign to Var a pointer, tagged by Ptag, to the cell
@@ -180,12 +180,12 @@
% of whether it is allocated statically or dynamically), and initialize
% this word with the value determined by SizeVal. (NOTE: ReserveWordAtStart
% and MaybeSize should not be yes / yes(_), because that will cause an
- % obvious conflict.)
+ % obvious conflict.) Label can be used in the generated code if necessary.
%
:- pred var_locn_assign_cell_to_var(module_info::in, prog_var::in, bool::in,
tag::in, list(maybe(rval))::in, how_to_construct::in,
maybe(term_size_value)::in, list(int)::in, string::in,
- may_use_atomic_alloc::in, code_tree::out,
+ may_use_atomic_alloc::in, label::in, code_tree::out,
static_cell_info::in, static_cell_info::out,
var_locn_info::in, var_locn_info::out) is det.
@@ -811,7 +811,7 @@
var_locn_assign_cell_to_var(ModuleInfo, Var, ReserveWordAtStart, Ptag,
MaybeRvals0, HowToConstruct, MaybeSize, FieldAddrs, TypeMsg,
- MayUseAtomic, Code, !StaticCellInfo, !VLI) :-
+ MayUseAtomic, Label, Code, !StaticCellInfo, !VLI) :-
(
MaybeSize = yes(SizeSource),
(
@@ -846,17 +846,17 @@
;
var_locn_assign_dynamic_cell_to_var(ModuleInfo, Var,
ReserveWordAtStart, Ptag, MaybeRvals, HowToConstruct,
- MaybeOffset, TypeMsg, MayUseAtomic, Code, !VLI)
+ MaybeOffset, TypeMsg, MayUseAtomic, Label, Code, !VLI)
).
:- pred var_locn_assign_dynamic_cell_to_var(module_info::in, prog_var::in,
bool::in, tag::in, list(maybe(rval))::in, how_to_construct::in,
- maybe(int)::in, string::in, may_use_atomic_alloc::in, code_tree::out,
- var_locn_info::in, var_locn_info::out) is det.
+ maybe(int)::in, string::in, may_use_atomic_alloc::in, label::in,
+ code_tree::out, var_locn_info::in, var_locn_info::out) is det.
var_locn_assign_dynamic_cell_to_var(ModuleInfo, Var, ReserveWordAtStart, Ptag,
- Vector, HowToConstruct, MaybeOffset, TypeMsg, MayUseAtomic, Code,
- !VLI) :-
+ Vector, HowToConstruct, MaybeOffset, TypeMsg, MayUseAtomic, Label,
+ Code, !VLI) :-
check_var_is_unknown(!.VLI, Var),
select_preferred_reg_or_stack_check(!.VLI, Var, Lval),
@@ -879,138 +879,219 @@
TotalOffset = MaybeOffset,
TotalSize = Size
),
- % This must appear before the call to `save_reused_cell_fields', otherwise
- % `save_reused_cell_fields' won't know not to use Lval as a temporary
- % register (if Lval is a register).
- var_locn_set_magic_var_location(Var, Lval, !VLI),
(
- HowToConstruct = construct_in_region(RegionVar),
- var_locn_produce_var(ModuleInfo, RegionVar, RegionRval,
- RegionVarCode, !VLI),
- MaybeRegionRval = yes(RegionRval),
- LldsComment = "Allocating region for ",
- CellCode = node([
- llds_instr(
- incr_hp(Lval, yes(Ptag), TotalOffset,
- const(llconst_int(TotalSize)), TypeMsg, MayUseAtomic,
- MaybeRegionRval), LldsComment ++ VarName)
- ]),
- SetupReuseCode = empty,
- TempRegs = []
+ MaybeOffset = yes(Offset),
+ StartOffset = -Offset
;
- % XXX We should probably throw an exception if we find
- % construct_statically here.
- ( HowToConstruct = construct_statically(_)
- ; HowToConstruct = construct_dynamically
+ MaybeOffset = no,
+ StartOffset = 0
+ ),
+ % This must appear before the call to `save_reused_cell_fields' in the
+ % reused_cell case, otherwise `save_reused_cell_fields' won't know not to
+ % use Lval as a temporary register (if Lval is a register).
+ var_locn_set_magic_var_location(Var, Lval, !VLI),
+ (
+ (
+ HowToConstruct = construct_in_region(RegionVar),
+ var_locn_produce_var(ModuleInfo, RegionVar, RegionRval,
+ RegionVarCode, !VLI),
+ MaybeRegionRval = yes(RegionRval),
+ MaybeReuse = no_llds_reuse,
+ LldsComment = "Allocating region for "
+ ;
+ HowToConstruct = construct_dynamically,
+ RegionVarCode = empty,
+ MaybeRegionRval = no,
+ LldsComment = "Allocating heap for "
+ ;
+ HowToConstruct = construct_statically(_),
+ unexpected(this_file,
+ "var_locn_assign_dynamic_cell_to_var: construct_statically")
),
+ assign_all_cell_args(ModuleInfo, Vector, yes(Ptag), lval(Lval),
+ StartOffset, ArgsCode, !VLI),
SetupReuseCode = empty,
- RegionVarCode = empty,
- MaybeRegionRval = no,
- LldsComment = "Allocating heap for ",
- CellCode = node([
- llds_instr(
- incr_hp(Lval, yes(Ptag), TotalOffset,
- const(llconst_int(TotalSize)), TypeMsg, MayUseAtomic,
- MaybeRegionRval), LldsComment ++ VarName)
- ]),
- TempRegs = []
+ MaybeReuse = no_llds_reuse
;
HowToConstruct = reuse_cell(CellToReuse),
- CellToReuse = cell_to_reuse(ReuseVar, _ReuseConsId, _),
- var_locn_produce_var(ModuleInfo, ReuseVar, ReuseRval, ReuseVarCode,
- !VLI),
- ( ReuseRval = lval(ReuseLval0) ->
- ReuseLval = ReuseLval0
- ;
- unexpected(this_file,
- "var_locn_produce_var: reused cell not an lval")
- ),
+ LldsComment = "Reusing cell on heap for ",
+ assign_reused_cell_to_var(ModuleInfo, Lval, Ptag, Vector, CellToReuse,
+ StartOffset, Label, MaybeReuse, SetupReuseCode, ArgsCode, !VLI),
+ MaybeRegionRval = no,
+ RegionVarCode = empty
+ ),
+ CellCode = node([
+ llds_instr(
+ incr_hp(Lval, yes(Ptag), TotalOffset,
+ const(llconst_int(TotalSize)), TypeMsg, MayUseAtomic,
+ MaybeRegionRval, MaybeReuse),
+ LldsComment ++ VarName)
+ ]),
+ Code = tree_list([SetupReuseCode, CellCode, RegionVarCode, ArgsCode]).
- % Save any variables which are available only in the reused cell into
- % temporary registers.
- save_reused_cell_fields(ModuleInfo, ReuseVar, ReuseLval, SaveArgsCode,
- TempRegs, !VLI),
- SetupReuseCode = tree(ReuseVarCode, SaveArgsCode),
+:- pred assign_reused_cell_to_var(module_info::in, lval::in, tag::in,
+ list(maybe(rval))::in, cell_to_reuse::in, int::in, label::in,
+ llds_reuse::out, code_tree::out, code_tree::out,
+ var_locn_info::in, var_locn_info::out) is det.
- % XXX optimise the stripping of the tag when the tags are the same or
- % the old tag is known, as we do in the high level backend
- LldsComment = "Reusing cell on heap for ",
- CellCode = node([
- llds_instr(
- assign(Lval,
- mkword(Ptag,
- unop(strip_tag, lval(ReuseLval)))),
- LldsComment ++ VarName)
- ]),
+assign_reused_cell_to_var(ModuleInfo, Lval, Ptag, Vector, CellToReuse,
+ StartOffset, Label, MaybeReuse, SetupReuseCode, ArgsCode, !VLI) :-
+ CellToReuse = cell_to_reuse(ReuseVar, _ReuseConsId, NeedsUpdates0),
+ var_locn_produce_var(ModuleInfo, ReuseVar, ReuseRval, ReuseVarCode, !VLI),
+ ( ReuseRval = lval(ReuseLval0) ->
+ ReuseLval = ReuseLval0
+ ;
+ unexpected(this_file,
+ "var_locn_assign_reused_cell_to_var: reused cell not an lval")
+ ),
- RegionVarCode = empty
+ % Save any variables which are available only in the reused cell into
+ % temporary registers.
+ save_reused_cell_fields(ModuleInfo, ReuseVar, ReuseLval, SaveArgsCode,
+ TempRegs0, !VLI),
+ SetupReuseCode = tree(ReuseVarCode, SaveArgsCode),
+
+ % If it's possible to avoid some field assignments, we'll need an extra
+ % temporary register to record whether we actually are reusing a structure
+ % or if a new object was allocated.
+ ( list.member(does_not_need_update, NeedsUpdates0) ->
+ var_locn_acquire_reg(FlagReg, !VLI),
+ MaybeFlag = yes(FlagReg),
+ TempRegs = [FlagReg | TempRegs0]
+ ;
+ MaybeFlag = no,
+ TempRegs = TempRegs0
),
- (
- MaybeOffset = yes(Offset),
- StartOffset = -Offset
+
+ % XXX optimise the stripping of the tag when the tags are the same or
+ % the old tag is known, as we do in the high level backend
+ MaybeReuse = llds_reuse(unop(strip_tag, lval(ReuseLval)), MaybeFlag),
+
+ % NeedsUpdates0 can be shorter than Vector due to extra fields.
+ Padding = list.length(Vector) - list.length(NeedsUpdates0),
+ ( Padding >= 0 ->
+ NeedsUpdates = list.duplicate(Padding, needs_update) ++ NeedsUpdates0
;
- MaybeOffset = no,
- StartOffset = 0
+ unexpected(this_file,
+ "var_locn_assign_reused_cell_to_var: Padding < 0")
),
- % XXX with structure reuse we don't necessarily have to assign all fields
- assign_cell_args(ModuleInfo, Vector, yes(Ptag), lval(Lval), StartOffset,
- ArgsCode, !VLI),
- list.foldl(var_locn_release_reg, TempRegs, !VLI),
- Code = tree_list([SetupReuseCode, CellCode, RegionVarCode, ArgsCode]).
-:- pred assign_cell_args(module_info::in, list(maybe(rval))::in,
+ (
+ MaybeFlag = yes(FlagLval),
+ assign_some_cell_args(ModuleInfo, Vector, NeedsUpdates, yes(Ptag),
+ lval(Lval), StartOffset, CannotSkipArgsCode, CanSkipArgsCode,
+ !VLI),
+ ArgsCode = tree_list([
+ node([
+ llds_instr(if_val(lval(FlagLval), code_label(Label)),
+ "skip some field assignments")
+ ]),
+ CanSkipArgsCode,
+ node([
+ llds_instr(label(Label),
+ "past skipped field assignments")
+ ]),
+ CannotSkipArgsCode
+ ])
+ ;
+ MaybeFlag = no,
+ assign_all_cell_args(ModuleInfo, Vector, yes(Ptag), lval(Lval),
+ StartOffset, ArgsCode, !VLI)
+ ),
+
+ list.foldl(var_locn_release_reg, TempRegs, !VLI).
+
+:- pred assign_all_cell_args(module_info::in, list(maybe(rval))::in,
maybe(tag)::in, rval::in, int::in, code_tree::out,
var_locn_info::in, var_locn_info::out) is det.
-assign_cell_args(_, [], _, _, _, empty, !VLI).
-assign_cell_args(ModuleInfo, [MaybeRval0 | MaybeRvals0], Ptag, Base, Offset,
+assign_all_cell_args(_, [], _, _, _, empty, !VLI).
+assign_all_cell_args(ModuleInfo, [MaybeRval | MaybeRvals], Ptag, Base, Offset,
Code, !VLI) :-
(
- MaybeRval0 = yes(Rval0),
- Target = field(Ptag, Base, const(llconst_int(Offset))),
+ MaybeRval = yes(Rval),
+ assign_cell_arg(ModuleInfo, Rval, Ptag, Base, Offset, ThisCode, !VLI)
+ ;
+ MaybeRval = no,
+ ThisCode = empty
+ ),
+ assign_all_cell_args(ModuleInfo, MaybeRvals, Ptag, Base, Offset + 1,
+ RestCode, !VLI),
+ Code = tree(ThisCode, RestCode).
+
+:- pred assign_some_cell_args(module_info::in, list(maybe(rval))::in,
+ list(needs_update)::in, maybe(tag)::in, rval::in, int::in, code_tree::out,
+ code_tree::out, var_locn_info::in, var_locn_info::out) is det.
+
+assign_some_cell_args(_, [], [], _, _, _, empty, empty, !VLI).
+assign_some_cell_args(ModuleInfo,
+ [MaybeRval | MaybeRvals], [NeedsUpdate | NeedsUpdates],
+ Ptag, Base, Offset, CannotSkipArgsCode, CanSkipArgsCode, !VLI) :-
+ (
+ MaybeRval = yes(Rval),
+ assign_cell_arg(ModuleInfo, Rval, Ptag, Base, Offset, ThisCode, !VLI)
+ ;
+ MaybeRval = no,
+ ThisCode = empty
+ ),
+ assign_some_cell_args(ModuleInfo, MaybeRvals, NeedsUpdates, Ptag, Base,
+ Offset + 1, RestCannotSkipArgsCode, RestCanSkipArgsCode, !VLI),
+ (
+ NeedsUpdate = needs_update,
+ CannotSkipArgsCode = tree(ThisCode, RestCannotSkipArgsCode),
+ CanSkipArgsCode = RestCanSkipArgsCode
+ ;
+ NeedsUpdate = does_not_need_update,
+ CannotSkipArgsCode = RestCannotSkipArgsCode,
+ CanSkipArgsCode = tree(ThisCode, RestCanSkipArgsCode)
+ ).
+
+assign_some_cell_args(_, [], [_ | _], _, _, _, _, _, !VLI) :-
+ unexpected(this_file, "assign_some_cell_args: mismatch lists").
+assign_some_cell_args(_, [_ | _], [], _, _, _, _, _, !VLI) :-
+ unexpected(this_file, "assign_some_cell_args: mismatch lists").
+
+:- pred assign_cell_arg(module_info::in, rval::in, maybe(tag)::in, rval::in,
+ int::in, code_tree::out, var_locn_info::in, var_locn_info::out) is det.
+
+assign_cell_arg(ModuleInfo, Rval0, Ptag, Base, Offset, Code, !VLI) :-
+ Target = field(Ptag, Base, const(llconst_int(Offset))),
+ (
+ Rval0 = var(Var),
+ find_var_availability(!.VLI, Var, no, Avail),
(
- Rval0 = var(Var),
- find_var_availability(!.VLI, Var, no, Avail),
- (
- Avail = available(Rval),
- EvalCode = empty
- ;
- Avail = needs_materialization,
- materialize_var(ModuleInfo, Var, no, no, [], Rval, EvalCode,
- !VLI)
- ),
- var_locn_get_vartypes(!.VLI, VarTypes),
- map.lookup(VarTypes, Var, Type),
- ( is_dummy_argument_type(ModuleInfo, Type) ->
- AssignCode = empty
- ;
- add_additional_lval_for_var(Var, Target, !VLI),
- get_var_name(!.VLI, Var, VarName),
- Comment = "assigning from " ++ VarName,
- AssignCode = node([llds_instr(assign(Target, Rval), Comment)])
- )
- ;
- Rval0 = const(_),
- EvalCode = empty,
- Comment = "assigning field from const",
- AssignCode = node([llds_instr(assign(Target, Rval0), Comment)])
+ Avail = available(Rval),
+ EvalCode = empty
;
- ( Rval0 = mkword(_, _)
- ; Rval0 = binop(_, _, _)
- ; Rval0 = unop(_, _)
- ; Rval0 = lval(_)
- ; Rval0 = mem_addr(_)
- ),
- unexpected(this_file, "assign_cell_args: unknown rval")
+ Avail = needs_materialization,
+ materialize_var(ModuleInfo, Var, no, no, [], Rval, EvalCode,
+ !VLI)
),
- ThisCode = tree(EvalCode, AssignCode)
+ var_locn_get_vartypes(!.VLI, VarTypes),
+ map.lookup(VarTypes, Var, Type),
+ ( is_dummy_argument_type(ModuleInfo, Type) ->
+ AssignCode = empty
+ ;
+ add_additional_lval_for_var(Var, Target, !VLI),
+ get_var_name(!.VLI, Var, VarName),
+ Comment = "assigning from " ++ VarName,
+ AssignCode = node([llds_instr(assign(Target, Rval), Comment)])
+ )
;
- MaybeRval0 = no,
- ThisCode = empty
+ Rval0 = const(_),
+ EvalCode = empty,
+ Comment = "assigning field from const",
+ AssignCode = node([llds_instr(assign(Target, Rval0), Comment)])
+ ;
+ ( Rval0 = mkword(_, _)
+ ; Rval0 = binop(_, _, _)
+ ; Rval0 = unop(_, _)
+ ; Rval0 = lval(_)
+ ; Rval0 = mem_addr(_)
+ ),
+ unexpected(this_file, "assign_cell_args: unknown rval")
),
- assign_cell_args(ModuleInfo, MaybeRvals0, Ptag, Base, Offset + 1, RestCode,
- !VLI),
- Code = tree(ThisCode, RestCode).
+ Code = tree(EvalCode, AssignCode).
% Save any variables which depend on the ReuseLval into temporary
% registers so that they are available after ReuseLval is clobbered.
Index: runtime/mercury_heap.h
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/runtime/mercury_heap.h,v
retrieving revision 1.39
diff -u -r1.39 mercury_heap.h
--- runtime/mercury_heap.h 21 Aug 2007 06:22:04 -0000 1.39
+++ runtime/mercury_heap.h 30 Jan 2008 03:58:00 -0000
@@ -33,7 +33,7 @@
#include "mercury_context.h" /* for min_heap_reclamation_point() */
#include "mercury_heap_profile.h" /* for MR_record_allocation() */
#include "mercury_deep_profiling.h" /* for MR_current_call_site_dynamic */
-#include "mercury_std.h" /* for MR_EXTERN_INLINE */
+#include "mercury_std.h" /* for MR_EXTERN_INLINE */
#include "mercury_reg_workarounds.h" /* for MR_memcpy */
#include "mercury_debug.h" /* for MR_debugtagoffsetincrhp* */
#ifdef MR_HIGHLEVEL_CODE
@@ -47,6 +47,8 @@
#ifdef MR_BOEHM_GC
#define GC_I_HIDE_POINTERS
#include "gc.h"
+ #include "gc_mark.h" /* for GC_least_plausible_heap_addr */
+ /* GC_greatest_plausible_heap_addr */
#endif
#endif
@@ -396,6 +398,59 @@
/***************************************************************************/
/*
+** Macros to implement structure reuse, conditioned on whether the structure
+** to reuse is really dynamically allocated. If not, fall back to allocating
+** a new object on the heap.
+*/
+
+#define MR_reuse_or_alloc_heap(dest, reuse, fallback_alloc) \
+ MR_tag_reuse_or_alloc_heap((dest), 0, (reuse), (fallback_alloc))
+
+#define MR_reuse_or_alloc_heap_flag(dest, flag, reuse, fallback_alloc) \
+ MR_tag_reuse_or_alloc_heap((dest), 0, (flag), (reuse), \
+ (fallback_alloc))
+
+#define MR_tag_reuse_or_alloc_heap(dest, tag, reuse, fallback_alloc) \
+ do { \
+ MR_bool dummy; \
+ MR_tag_reuse_or_alloc_heap_flag((dest), (tag), dummy, \
+ (reuse), (fallback_alloc)); \
+ (void) dummy; \
+ } while (0)
+
+#ifdef MR_BOEHM_GC
+
+ #define MR_in_heap_range(addr) \
+ ((void *) (addr) >= GC_least_plausible_heap_addr && \
+ (void *) (addr) < GC_greatest_plausible_heap_addr) \
+
+#else /* ! MR_BOEHM_GC */
+
+ /*
+ ** We don't have any way to check whether `addr' is dynamically allocated,
+ ** so just assume that it is. For this to be safe `--static-ground-terms'
+ ** needs to be disabled.
+ */
+ #define MR_in_heap_range(addr) (MR_TRUE)
+
+#endif /* ! MR_BOEHM_GC */
+
+#define MR_tag_reuse_or_alloc_heap_flag(dest, tag, flag, reuse_addr, \
+ fallback_alloc) \
+ do { \
+ MR_Word tmp = (reuse_addr); \
+ if (MR_in_heap_range(tmp)) { \
+ (dest) = (MR_Word) MR_mkword((tag), tmp); \
+ (flag) = MR_TRUE; \
+ } else { \
+ (fallback_alloc); \
+ (flag) = MR_FALSE; \
+ } \
+ } while (0)
+
+/***************************************************************************/
+
+/*
** Macros to box/unbox types declared with `pragma foreign_type'.
*/
--------------------------------------------------------------------------
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