mirror of
https://github.com/Mercury-Language/mercury.git
synced 2025-12-09 10:52:24 +00:00
Until now, we have supported two variants of trailing grades, those that use a
fixed-size trail (.tr) and those that use trail segments (.trseg). This change
removes support for fixed sized trails, and renames the .trseg grade component
to .tr. The .trseg grade now acts a synonym for .tr; it is deprecated, since we
intend to eventually delete it. Until then, the behavior of the old .tr grade
component should be available, though to developers only, by compiling the
whole system with EXTRA_CFLAGS = -DMR_USE_FIXED_SIZE_TRAIL.
runtime/mercury_conf_param.h:
Delete the MR_TRAIL_SEGMENTS macro. Its effect is now implied by
MR_USE_TRAIL, unless a new macro, MR_USE_FIXED_SIZE_TRAIL, is defined.
Developers can use this new macro to disable trail segments, should the
need for doing that arise.
runtime/mercury_grade.h:
Add a new macro that defines a binary compatibility version number for
trailing; use that in the grade part for trailing.
Use "_trfix" or "_trseg" as the prefix of the trailing part of the
MR_GRADE_VAR depending on if MR_USE_FIXED_SIZE_TRAIL is defined or
not.
runtime/mercury_trail.[ch]:
runtime/mercury_context.h:
Enable trail segments by default, only disabling them if
MR_USE_FIXED_SIZE_TRAIL is enabled.
runtime/mercury_wrapper.c:
trace/mercury_trace_cmd_developer.c:
Conform to the above changes.
compiler/compile_target_code.m:
Do not pass options for trail segments to the C compiler.
compiler/compute_grade.m:
Treat trseg as a synonym for tr.
compiler/options.m:
Deprecate --trail-segments.
grade_lib/grade_spec.m:
grade_lib/grade_string.m:
grade_lib/grade_structure.m:
grade_lib/grade_vars.m:
grade_lib/try_all_grade_structs.m:
grade_lib/var_value_names.m:
Remove the trseg component.
scripts/canonical_grade.sh-subr:
scripts/init_grade_options.sh-subr:
scripts/mgnuc.in:
scripts/parse_grade_options.sh-subr:
Remove support for the --trail-segments option.
doc/user_guide.texi:
Update the documentation for the --trail-segments.
Comment out the documentation of the --trail-size and --trail-size-kwords
runtime options; they are no longer useful to non-developers.
NEWS:
Announce this change.
288 lines
8.0 KiB
C
288 lines
8.0 KiB
C
// vim: ts=4 sw=4 expandtab ft=c
|
|
|
|
// Copyright (C) 1997-2000, 2006-2008, 2011 The University of Melbourne.
|
|
// Copyright (C) 2015-2016, 2018 The Mercury team.
|
|
// This file is distributed under the terms specified in COPYING.LIB.
|
|
|
|
// mercury_trail.c - code for the Mercury trail.
|
|
//
|
|
// The trail is used to record values that need to be restored on backtracking.
|
|
|
|
#include "mercury_imp.h"
|
|
#include "mercury_trail.h"
|
|
#include "mercury_memory.h"
|
|
#include "mercury_memory_handlers.h"
|
|
#include "mercury_misc.h"
|
|
|
|
#ifdef MR_USE_TRAIL
|
|
|
|
#if !defined(MR_THREAD_SAFE)
|
|
MR_MemoryZone *MR_trail_zone;
|
|
MR_TrailEntry *MR_trail_ptr_var;
|
|
|
|
#if !defined(MR_USE_FIXED_SIZE_TRAIL)
|
|
MR_MemoryZones *MR_prev_trail_zones;
|
|
#endif
|
|
|
|
MR_Unsigned MR_ticket_counter_var = 1;
|
|
MR_Unsigned MR_ticket_high_water_var = 1;
|
|
#endif
|
|
|
|
#if !defined(MR_USE_FIXED_SIZE_TRAIL)
|
|
static void
|
|
MR_pop_trail_segment(void);
|
|
#endif
|
|
|
|
static void
|
|
MR_reset_trail_zone(void);
|
|
|
|
void
|
|
MR_untrail_to(MR_TrailEntry *old_trail_ptr, MR_untrail_reason reason)
|
|
{
|
|
MR_TrailEntry *tr_ptr;
|
|
MR_TrailEntry *tr_base;
|
|
|
|
// Not needed, since MR_trail_ptr is never a real reg:
|
|
// MR_restore_transient_registers();
|
|
tr_ptr = MR_trail_ptr;
|
|
|
|
switch (reason) {
|
|
case MR_solve:
|
|
case MR_commit:
|
|
|
|
// Just handle the function trail entries.
|
|
tr_base = MR_TRAIL_BASE;
|
|
while (tr_ptr != old_trail_ptr) {
|
|
tr_ptr--;
|
|
if (MR_get_trail_entry_kind(tr_ptr) == MR_func_entry) {
|
|
(*MR_get_trail_entry_untrail_func(tr_ptr))(
|
|
MR_get_trail_entry_datum(tr_ptr), reason);
|
|
}
|
|
|
|
// When we are using trail segments it is possible that
|
|
// `old_trail_ptr' is not a location on the current trail segment.
|
|
// We need to walk backwards through all the previous segments
|
|
// (invoking function trail entries as we go) until we find it.
|
|
|
|
#if !defined(MR_USE_FIXED_SIZE_TRAIL)
|
|
if (tr_ptr == tr_base
|
|
&& tr_ptr != old_trail_ptr)
|
|
{
|
|
MR_MemoryZones *prev_zones;
|
|
MR_MemoryZone *zone;
|
|
|
|
prev_zones = MR_PREV_TRAIL_ZONES;
|
|
zone = prev_zones->MR_zones_head;
|
|
tr_ptr = (MR_TrailEntry *) zone->MR_zone_end;
|
|
|
|
while (tr_ptr != old_trail_ptr) {
|
|
tr_ptr--;
|
|
if (MR_get_trail_entry_kind(tr_ptr) == MR_func_entry) {
|
|
(*MR_get_trail_entry_untrail_func(tr_ptr))(
|
|
MR_get_trail_entry_datum(tr_ptr), reason);
|
|
}
|
|
|
|
if (tr_ptr == (MR_TrailEntry *) zone->MR_zone_min
|
|
&& tr_ptr != old_trail_ptr)
|
|
{
|
|
prev_zones = prev_zones->MR_zones_tail;
|
|
zone = prev_zones->MR_zones_head;
|
|
tr_ptr = (MR_TrailEntry *) zone->MR_zone_end;
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
#endif
|
|
}
|
|
// NB. We do _not_ reset the trail pointer here. Doing so would be
|
|
// unsafe, for `mdi' modes, because we may still need to restore
|
|
// the value if/when we backtrack to a choicepoint prior to the one
|
|
// we are cutting away.
|
|
|
|
break;
|
|
|
|
case MR_undo:
|
|
case MR_exception:
|
|
case MR_retry:
|
|
// Handle both function and value trail entries.
|
|
tr_base = MR_TRAIL_BASE;
|
|
while (tr_ptr != old_trail_ptr) {
|
|
tr_ptr--;
|
|
if (MR_get_trail_entry_kind(tr_ptr) == MR_func_entry) {
|
|
(*MR_get_trail_entry_untrail_func(tr_ptr))(
|
|
MR_get_trail_entry_datum(tr_ptr), reason);
|
|
} else {
|
|
*MR_get_trail_entry_address(tr_ptr) =
|
|
MR_get_trail_entry_value(tr_ptr);
|
|
}
|
|
#if !defined(MR_USE_FIXED_SIZE_TRAIL)
|
|
if (tr_ptr == tr_base
|
|
&& tr_ptr != old_trail_ptr)
|
|
{
|
|
MR_pop_trail_segment();
|
|
tr_ptr = MR_trail_ptr;
|
|
tr_base = MR_TRAIL_BASE;
|
|
}
|
|
#endif
|
|
}
|
|
|
|
MR_trail_ptr = tr_ptr;
|
|
// Not needed, since MR_trail_ptr is never a real reg:
|
|
// MR_save_transient_registers();
|
|
break;
|
|
|
|
default:
|
|
MR_fatal_error("unknown MR_untrail_reason");
|
|
}
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////
|
|
|
|
MR_Unsigned
|
|
MR_num_trail_entries(void)
|
|
{
|
|
MR_Unsigned n_entries = 0;
|
|
|
|
#if !defined(MR_USE_FIXED_SIZE_TRAIL)
|
|
MR_MemoryZones *list;
|
|
MR_MemoryZone *zone;
|
|
|
|
list = MR_PREV_TRAIL_ZONES;
|
|
while (list != NULL) {
|
|
zone = list->MR_zones_head;
|
|
n_entries += (MR_TrailEntry *) zone->MR_zone_end
|
|
- (MR_TrailEntry *) zone->MR_zone_min;
|
|
list = list->MR_zones_tail;
|
|
}
|
|
#endif // ! MR_USE_FIXED_SIZE_TRAIL
|
|
|
|
n_entries += MR_trail_ptr - MR_TRAIL_BASE;
|
|
|
|
return n_entries;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////
|
|
|
|
void
|
|
MR_reset_trail(void)
|
|
{
|
|
#if !defined(MR_USE_FIXED_SIZE_TRAIL)
|
|
while (MR_PREV_TRAIL_ZONES != NULL) {
|
|
MR_reset_trail_zone();
|
|
MR_pop_trail_segment();
|
|
}
|
|
#endif
|
|
|
|
MR_reset_trail_zone();
|
|
|
|
#if defined(MR_CONSERVATIVE_GC)
|
|
MR_clear_zone_for_GC(MR_TRAIL_ZONE, MR_trail_ptr);
|
|
#endif
|
|
|
|
MR_ticket_counter = 1;
|
|
MR_ticket_high_water = 1;
|
|
}
|
|
|
|
static void
|
|
MR_reset_trail_zone(void) {
|
|
|
|
MR_TrailEntry *tr_ptr;
|
|
MR_TrailEntry *tr_base;
|
|
|
|
tr_ptr = MR_trail_ptr;
|
|
tr_base = MR_TRAIL_BASE;
|
|
|
|
while (tr_ptr != tr_base) {
|
|
tr_ptr--;
|
|
if (MR_get_trail_entry_kind(tr_ptr) == MR_func_entry) {
|
|
(*MR_get_trail_entry_untrail_func(tr_ptr))(
|
|
MR_get_trail_entry_datum(tr_ptr), MR_gc);
|
|
}
|
|
}
|
|
MR_trail_ptr = tr_base;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////
|
|
|
|
#if !defined(MR_USE_FIXED_SIZE_TRAIL)
|
|
void
|
|
MR_new_trail_segment(void)
|
|
{
|
|
|
|
MR_MemoryZones *list;
|
|
MR_MemoryZone *new_zone;
|
|
MR_TrailEntry *old_trail_ptr;
|
|
|
|
old_trail_ptr = MR_trail_ptr;
|
|
|
|
// We perform explicit overflow checks so redzones just waste space.
|
|
|
|
new_zone = MR_create_or_reuse_zone("trail_segment", MR_trail_size, 0,
|
|
0, MR_default_handler);
|
|
|
|
list = MR_GC_malloc_uncollectable_attrib(sizeof(MR_MemoryZones),
|
|
MR_ALLOC_SITE_RUNTIME);
|
|
|
|
#if defined(MR_DEBUG_TRAIL_SEGMENTS)
|
|
printf("create new trail segment: old zone: %p, old trail_ptr %p\n",
|
|
MR_TRAIL_ZONE, MR_trail_ptr);
|
|
#endif
|
|
|
|
list->MR_zones_head = MR_TRAIL_ZONE;
|
|
list->MR_zones_tail = MR_PREV_TRAIL_ZONES;
|
|
MR_PREV_TRAIL_ZONES = list;
|
|
MR_TRAIL_ZONE = new_zone;
|
|
MR_trail_ptr = (MR_TrailEntry *) MR_TRAIL_ZONE->MR_zone_min;
|
|
|
|
#if defined(MR_DEBUG_TRAIL_SEGMENTS)
|
|
printf("create new trail segment: new zone: %p, new trail_ptr %p\n",
|
|
MR_TRAIL_ZONE, MR_trail_ptr);
|
|
#endif
|
|
}
|
|
|
|
static void
|
|
MR_pop_trail_segment(void)
|
|
{
|
|
|
|
MR_MemoryZones *list;
|
|
|
|
#if defined(MR_DEBUG_TRAIL_SEGMENTS)
|
|
printf("restore old trail segment: old zone %p, old trail_ptr %p\n",
|
|
MR_TRAIL_ZONE, MR_trail_ptr);
|
|
#endif
|
|
|
|
MR_release_zone(MR_TRAIL_ZONE);
|
|
|
|
list = MR_PREV_TRAIL_ZONES;
|
|
MR_TRAIL_ZONE = list->MR_zones_head;
|
|
MR_PREV_TRAIL_ZONES = list->MR_zones_tail;
|
|
MR_trail_ptr = (MR_TrailEntry *) MR_TRAIL_ZONE->MR_zone_end;
|
|
MR_GC_free(list);
|
|
|
|
#if defined(MR_DEBUG_TRAIL_SEGMENTS)
|
|
printf("restore old trail segment: new zone %p, new trail_ptr %p\n",
|
|
MR_TRAIL_ZONE, MR_trail_ptr);
|
|
#endif
|
|
}
|
|
|
|
MR_Unsigned
|
|
MR_num_trail_segments(void)
|
|
{
|
|
MR_Unsigned n_segments = 1;
|
|
MR_MemoryZones *list;
|
|
|
|
list = MR_PREV_TRAIL_ZONES;
|
|
while (list != NULL) {
|
|
n_segments++;
|
|
list = list->MR_zones_tail;
|
|
}
|
|
|
|
return n_segments;
|
|
}
|
|
|
|
#endif // ! MR_USE_FIXED_SIZE_TRAIL
|
|
|
|
#endif // MR_USE_TRAIL
|
|
|
|
////////////////////////////////////////////////////////////////////////////
|