diff --git a/C/c_interface.c b/C/c_interface.c index 0aeda15ba..70dca595e 100755 --- a/C/c_interface.c +++ b/C/c_interface.c @@ -494,16 +494,81 @@ X_API void YAP_SetOutputMessage(void); X_API int YAP_StreamToFileNo(Term); X_API void YAP_CloseAllOpenStreams(void); X_API void YAP_FlushAllStreams(void); + +/** +@group slotInterface Term Handles or Slots +@{ + +Term handles correspond to SWI-Prolog's term_t datatype: they are a safe representation +of terms. Slots are safe houses in the stack, the garbage collector and the stack +shifter know about them and make sure they have correct values. In this +case, we use a slot to preserve _t_ during the execution of +YAP_RunGoal). When the execution of _t_ is over we read the +(possibly changed) value of _t_ back from the slot _sl_ and tell +YAP that the slot _sl_ is not needed and can be given back to the +system. + + YAP supports storing and manipulating term_t like slots or handles, but in the C +the programmer needs to take care as most operations still require unwrapping the term +inside. + +For implementation details and more information, please check term_t_slots in the implementation section. + +*/ +/// @brief report the current position of the slots, assuming that they occupy the top of the stack. +/// +/// X_API Int YAP_CurrentSlot(void); -X_API Int YAP_NewSlots(int); -X_API Int YAP_InitSlot(Term); -X_API Term YAP_GetFromSlot(Int); -X_API Term *YAP_AddressFromSlot(Int); -X_API Term *YAP_AddressOfTermInSlot(Int); -X_API void YAP_PutInSlot(Int, Term); -X_API int YAP_RecoverSlots(int); -X_API Int YAP_ArgsToSlots(int); -X_API void YAP_SlotsToArgs(int, Int); + +/// @brief allocate n empty new slots +/// +/// Return a handle to the system's default slot. +X_API Int YAP_NewSlots(int NumberOfSlots); + +/// @brief allocate n empty new slots +/// +/// Allocate _NumberOfSlots_ from the stack and return an handle to the +/// last one. The other handle can be obtained by decrementing the handle. +X_API Int YAP_InitSlot(YAP_Term t); + +/// @brief read from a slot. +/// +/// +X_API YAP_Term YAP_GetFromSlot(YAP_Int slot); + +/// @brief get the memory address of a slot +/// +/// Return the address of slot _slot_: please use with care. +X_API YAP_Term *YAP_AddressFromSlot(YAP_Int); + +/// @brief get the memory address of the term actually stored in a slot +/// +/// +X_API YAP_Term *YAP_AddressOfTermInSlot(YAP_Int); + +/// @brief store term in a slot +/// +/// +X_API void YAP_PutInSlot(YAP_Int slot, YAP_Term t); + +/// @brief Succeeds if it recovers the space allocated for $n$ contiguous slots starting at topSlot. +/// +/// Set the contents of slot _slot_ to _t_. +X_API int YAP_RecoverSlots(int, YAP_Int topSlot); + +/// @brief copies the first new n YAAM registers to slots +/// +/// Store the current first _HowMany_ arguments in new slots. +X_API YAP_Int YAP_ArgsToSlots(int HowMany); + +/// @brief copies n slots such that sl is copied to the last abstract ,achine register. +/// +/// Set the first _HowMany_ arguments to the _HowMany_ slots +// starting at _slot_. +X_API void YAP_SlotsToArgs(int HowMany, YAP_Int slot); + +/// @} + X_API void YAP_Throw(Term); X_API void YAP_AsyncThrow(Term); X_API void YAP_Halt(int); @@ -995,7 +1060,7 @@ YAP_MkPairTerm(Term t1, Term t2) BACKUP_H(); t1 = Yap_GetFromSlot(sl1 PASS_REGS); t2 = Yap_GetFromSlot(sl2 PASS_REGS); - Yap_RecoverSlots(2 PASS_REGS); + Yap_RecoverSlots(2, sl2 PASS_REGS); } t = MkPairTerm(t1, t2); RECOVER_H(); @@ -1019,7 +1084,7 @@ YAP_MkListFromTerms(Term *ta, Int sz) } BACKUP_H(); ta = (CELL *)Yap_GetFromSlot(sl1 PASS_REGS); - Yap_RecoverSlots(1 PASS_REGS); + Yap_RecoverSlots(1, sl1 PASS_REGS); } h = HR; t = AbsPair(h); @@ -1330,10 +1395,10 @@ YAP_InitSlot(Term t) } X_API int -YAP_RecoverSlots(int n) +YAP_RecoverSlots(int n, Int sl) { CACHE_REGS - return Yap_RecoverSlots(n PASS_REGS); + return Yap_RecoverSlots(n, sl PASS_REGS); } X_API Term diff --git a/H/Regs.h b/H/Regs.h index f33da00d2..6bc5ba96e 100755 --- a/H/Regs.h +++ b/H/Regs.h @@ -13,6 +13,8 @@ * version: $Id: Regs.h,v 1.42 2008-08-12 01:27:22 vsc Exp $ * *************************************************************************/ +#ifndef REGS_H +#define REGS_H 1 /********* abstract machine registers **********************************/ #ifdef YAP_H @@ -731,3 +733,4 @@ void SET_ASP__(CELL *yreg, Int sz USES_REGS) { ASP = (CELL *)PROTECT_FROZEN_B(B); } +#endif diff --git a/H/YapHandles.h b/H/YapHandles.h index 66c7a9fe6..3a53e5b5e 100755 --- a/H/YapHandles.h +++ b/H/YapHandles.h @@ -15,36 +15,40 @@ #ifndef YAP_HANDLES_H #define YAP_HANDLES_H 1 +#include "Regs.h" -/************************************************************************************************* - slots +/** + @group term_t_slots -Also known as term handles, they provide a way to access terms without being exposed to stack shifts in gc. +Also known as term handles, slots are offsets to entries in the local stack. YAP never compresses the local stack, so slots are respected by the garbage collector, +hence providing a way to access terms without being exposed to stack shifts or garbage-collection. -They should always be used as local variables. + Space is released when the function terminataes. Thus, slots will be automatically released at the end +of a function. Hence, slots should always be used as local variables. -They are organized as follows: ----- Tagged Offset of next pointer in chain ----- Tagged Number of entries +Slots are organized as follows: +---- Offset of next pointer in chain (tagged as an Int) +---- Number of entries (tagged as Int), in the example TAG(INT,4) Entry Entry Entry Entry ----- Tagged Number of entries +---- Number of entries (tagged as Int), in the example TAG(INT,4) -They are not known to the yaam. Instead, -they are created when entering user code (see YAP_Execute* functions). They are also created: +Slots are not known to the yaam. Instead, A new set of slots is created when the emulator calls user C-code. +(see YAP_Execute* functions). They are also created: -- by SWI PL_foreign_frame function, -- by YAP_*Goal routines, when they exit successfully. Notice that all handles created by c-goals within -a *Goal execution should not be used afterwards. + - by SWI's PL_foreign_frame() function, + - by the YAP_RunGoal() routines and friends, when they exit successfully. Notice that all handles created by c-goals within + a `Goal` execution should not be used afterwards. +This section lists the main internal functions for slot management. These functions are then exported through corresponding FLI C-functions *************************************************************************************************/ - +/// @brief start a new set of slots, linking them to the last active slots (who may, or not, be active). static inline Int Yap_StartSlots( USES_REGS1 ) { Int CurSlot = LOCAL_CurSlot; @@ -58,46 +62,55 @@ Yap_StartSlots( USES_REGS1 ) { return CurSlot; } + +/// @brief reset slots to a well-known position in the stack static inline void Yap_CloseSlots( Int slot USES_REGS ) { LOCAL_CurSlot = slot; } +/// @brief report the current position of the slots, assuming that they occupy the top of the stack. static inline Int Yap_CurrentSlot( USES_REGS1 ) { return IntOfTerm(ASP[0]); } +/// @brief read from a slot. static inline Term Yap_GetFromSlot(Int slot USES_REGS) { return(Deref(LCL0[slot])); } +/// @brief read from a slot. but does not try to dereference the slot. static inline Term Yap_GetDerefedFromSlot(Int slot USES_REGS) { return LCL0[slot]; } +/// @brief read the object in a slot. but do not try to dereference the slot. static inline Term Yap_GetPtrFromSlot(Int slot USES_REGS) { return(LCL0[slot]); } +/// @brief get the memory address of a slot static inline Term * Yap_AddressFromSlot(Int slot USES_REGS) { return(LCL0+slot); } +/// @brief store term in a slot static inline void Yap_PutInSlot(Int slot, Term t USES_REGS) { LCL0[slot] = t; } +/// @brief allocate n empty new slots static inline Int Yap_NewSlots(int n USES_REGS) { @@ -111,6 +124,7 @@ Yap_NewSlots(int n USES_REGS) return((ASP+1)-LCL0); } +/// @brief create a new slot with term t static inline Int Yap_InitSlot(Term t USES_REGS) { @@ -121,13 +135,16 @@ Yap_InitSlot(Term t USES_REGS) return((ASP+1)-LCL0); } +/// @brief Succeeds if it is to recover the space allocated for $n$ contiguos slots starting at topSlot. static inline int -Yap_RecoverSlots(int n USES_REGS) +Yap_RecoverSlots(int n, Int topSlot USES_REGS) { Int old_slots = IntOfTerm(ASP[0]); - if (old_slots - n < 0) { + if (old_slots < n) { return FALSE; } + if (ASP+1 != LCL0+topSlot) + return FALSE; ASP += n; ASP[old_slots+(n-old_slots+1)] = ASP[0] = MkIntTerm(old_slots-n); return TRUE; diff --git a/library/dialect/swi/fli/swi.c b/library/dialect/swi/fli/swi.c index 492436427..3444f7c46 100755 --- a/library/dialect/swi/fli/swi.c +++ b/library/dialect/swi/fli/swi.c @@ -234,7 +234,7 @@ X_API void PL_reset_term_refs(term_t after) { CACHE_REGS term_t new = Yap_NewSlots(1 PASS_REGS); - Yap_RecoverSlots(after-new PASS_REGS); + Yap_RecoverSlots(after-new, new PASS_REGS); } /** @}