mirror of
https://github.com/Mercury-Language/mercury.git
synced 2025-12-17 06:47:17 +00:00
Estimated hours taken: 0.5 Branches: main Avoid warnings about lvalue casts being deprecated in non .gc grades. compiler/mercury_deep_copy.c: When assigning to MR_hp do so through MR_hp_word, rather than via MR_hp (which shouldn't be used as an lvalue).
198 lines
5.3 KiB
C
198 lines
5.3 KiB
C
/*
|
|
** Copyright (C) 1997-2006 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.
|
|
*/
|
|
|
|
/*
|
|
** This module defines the MR_deep_copy() functions.
|
|
**
|
|
** Deep copy is used for a number of different purposes. Each variant
|
|
** has the same basic control structure, but differs in how memory
|
|
** is allocated, or whether forwarding pointers are left behind.
|
|
*/
|
|
|
|
#include "mercury_imp.h"
|
|
#include "mercury_deep_copy.h"
|
|
#include "mercury_type_info.h"
|
|
#include "mercury_ho_call.h"
|
|
#include "mercury_layout_util.h"
|
|
#include "mercury_memory.h"
|
|
#include "mercury_accurate_gc.h"
|
|
|
|
/*
|
|
** MR_deep_copy(): see mercury_deep_copy.h for documentation.
|
|
*/
|
|
|
|
#undef in_range
|
|
#define in_range(X) (lower_limit == NULL || \
|
|
((X) >= lower_limit && (X) <= upper_limit))
|
|
|
|
#undef copy
|
|
#define copy MR_deep_copy
|
|
|
|
#undef copy_arg
|
|
#define copy_arg MR_deep_copy_arg
|
|
|
|
#undef copy_type_info
|
|
#define copy_type_info MR_deep_copy_type_info
|
|
|
|
#undef copy_pseudo_type_info
|
|
#define copy_pseudo_type_info MR_deep_copy_pseudo_type_info
|
|
|
|
#undef copy_typeclass_info
|
|
#define copy_typeclass_info MR_deep_copy_typeclass_info
|
|
|
|
#undef if_forwarding_pointer
|
|
#define if_forwarding_pointer(Data, ACTION)
|
|
|
|
#undef leave_forwarding_pointer
|
|
#define leave_forwarding_pointer(Data, Offset, NewData)
|
|
|
|
#undef found_out_of_range_pointer
|
|
#define found_out_of_range_pointer(Data)
|
|
|
|
#include "mercury_deep_copy_body.h"
|
|
|
|
/*
|
|
** agc_deep_copy(): see mercury_deep_copy.h for documentation.
|
|
*/
|
|
#ifdef MR_NATIVE_GC
|
|
|
|
/* in_range() is true iff X is in the from-space */
|
|
#undef in_range
|
|
#define in_range(X) ((X) >= lower_limit && (X) <= upper_limit)
|
|
|
|
#undef copy
|
|
#define copy MR_agc_deep_copy
|
|
|
|
#undef copy_arg
|
|
#define copy_arg MR_agc_deep_copy_arg
|
|
|
|
#undef copy_type_info
|
|
#define copy_type_info MR_agc_deep_copy_type_info
|
|
|
|
#undef copy_pseudo_type_info
|
|
#define copy_pseudo_type_info MR_agc_deep_copy_pseudo_type_info
|
|
|
|
#undef copy_typeclass_info
|
|
#define copy_typeclass_info MR_agc_deep_copy_typeclass_info
|
|
|
|
#ifdef MR_DEBUG_AGC_FORWARDING
|
|
#define FORWARD_DEBUG_MSG(Msg, Data) \
|
|
fprintf(stderr, Msg, Data)
|
|
#else
|
|
#define FORWARD_DEBUG_MSG(Msg, Data) ((void)0)
|
|
#endif
|
|
|
|
/*
|
|
** This points to a bitmap, which is used to record which objects
|
|
** have already been copied and now hold forwarding pointers.
|
|
*/
|
|
MR_Word *MR_has_forwarding_pointer;
|
|
|
|
#define mark_as_forwarding_pointer(Data) \
|
|
do { \
|
|
size_t fwdptr_offset = \
|
|
(MR_Word *)(Data) - (MR_Word *)lower_limit; \
|
|
size_t fwdptr_word = fwdptr_offset / MR_WORDBITS; \
|
|
size_t fwdptr_bit = fwdptr_offset % MR_WORDBITS; \
|
|
MR_has_forwarding_pointer[fwdptr_word] |= (1 << fwdptr_bit); \
|
|
} while (0)
|
|
|
|
#undef if_forwarding_pointer
|
|
#define if_forwarding_pointer(Data, ACTION) \
|
|
do { \
|
|
size_t fwdptr_offset = \
|
|
(MR_Word *)(Data) - (MR_Word *)lower_limit; \
|
|
size_t fwdptr_word = fwdptr_offset / MR_WORDBITS; \
|
|
size_t fwdptr_bit = fwdptr_offset % MR_WORDBITS; \
|
|
if (MR_has_forwarding_pointer[fwdptr_word] & \
|
|
(1 << fwdptr_bit)) \
|
|
{ \
|
|
ACTION; \
|
|
} \
|
|
} while (0)
|
|
|
|
#undef leave_forwarding_pointer
|
|
#define leave_forwarding_pointer(Data, Offset, NewData) \
|
|
do { \
|
|
FORWARD_DEBUG_MSG("forwarding to %lx\n", \
|
|
(long) NewData); \
|
|
*(((MR_Word *)Data) + Offset) = NewData; \
|
|
mark_as_forwarding_pointer(Data); \
|
|
} while (0)
|
|
|
|
#undef found_out_of_range_pointer
|
|
#define found_out_of_range_pointer(Data) \
|
|
FORWARD_DEBUG_MSG("not on this heap: %lx\n", (long) Data)
|
|
|
|
#include "mercury_deep_copy_body.h"
|
|
|
|
#endif
|
|
|
|
/*---------------------------------------------------------------------------*/
|
|
|
|
#define SWAP(val1, val2, type) \
|
|
do { \
|
|
type swap_tmp; \
|
|
swap_tmp = (val1); \
|
|
(val1) = (val2); \
|
|
(val2) = swap_tmp; \
|
|
} while (0)
|
|
|
|
/*
|
|
** The above macro won't suffice when we want to swap the pointers to the
|
|
** heap and the global heap since it will cause gcc to emit warnings about
|
|
** lvalue casts being deprecated. In that case we use the following macro.
|
|
*/
|
|
#define SWAP_HEAP_AND_GLOBAL_HEAP \
|
|
do { \
|
|
MR_Word *swap_tmp; \
|
|
swap_tmp = MR_hp; \
|
|
MR_hp_word = (MR_Word) MR_global_hp; \
|
|
MR_global_hp = swap_tmp; \
|
|
} while (0)
|
|
|
|
#ifdef MR_MIGHT_RECLAIM_HP_ON_FAILURE
|
|
|
|
/*
|
|
** MR_make_long_lived(): see mercury_deep_copy.h for documentation.
|
|
*/
|
|
|
|
MR_Word
|
|
MR_make_long_lived(MR_Word term, MR_TypeInfo type_info, MR_Word *lower_limit)
|
|
{
|
|
MR_Word result;
|
|
|
|
MR_restore_transient_hp(); /* Because we play with MR_hp */
|
|
|
|
if (lower_limit < MR_ENGINE(MR_eng_heap_zone)->MR_zone_bottom ||
|
|
lower_limit > MR_ENGINE(MR_eng_heap_zone)->MR_zone_top)
|
|
{
|
|
lower_limit = MR_ENGINE(MR_eng_heap_zone)->MR_zone_bottom;
|
|
}
|
|
|
|
/* temporarily swap the heap with the global heap */
|
|
SWAP(MR_ENGINE(MR_eng_heap_zone), MR_ENGINE(MR_eng_global_heap_zone),
|
|
MR_MemoryZone *);
|
|
SWAP_HEAP_AND_GLOBAL_HEAP;
|
|
|
|
/* copy values from the heap to the global heap */
|
|
MR_save_transient_hp();
|
|
result = MR_deep_copy(term, type_info, lower_limit,
|
|
MR_ENGINE(MR_eng_global_heap_zone)->MR_zone_top);
|
|
MR_restore_transient_hp();
|
|
|
|
/* swap the heap and global heap back again */
|
|
SWAP(MR_ENGINE(MR_eng_heap_zone), MR_ENGINE(MR_eng_global_heap_zone),
|
|
MR_MemoryZone *);
|
|
SWAP_HEAP_AND_GLOBAL_HEAP;
|
|
|
|
MR_save_transient_hp(); /* Because we played with MR_hp */
|
|
|
|
return result;
|
|
}
|
|
|
|
#endif /* MIGHT_RECLAIM_HP_ON_FAILURE */
|