fis-gtm/sr_port/glvn_pool.h

140 lines
6.8 KiB
C
Raw Permalink Normal View History

2024-07-19 11:44:10 -04:00
/****************************************************************
* *
* Copyright 2012 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
* under a license. If you do not know the terms of *
* the license, please stop and do not read further. *
* *
****************************************************************/
#ifndef GLVN_POOL_H_INCLUDED
#define GLVN_POOL_H_INCLUDED
#include "callg.h"
#include "compiler.h"
#include "lv_val.h"
/* Here we provide tools for saving identifying information of local or global variables. For local variables this includes
* the variable name itself, as well as copies of each subscript. For global variables we save each argument that needs to
* be later passed into op_gvname/op_gvnaked/op_gvextnam. Note that deferring the op_gvnaked call allows us to achieve
* correct naked indicator flow. For example, in the command SET @"^(subs)"=rhs, the ^() needs to be evaluated relative to
* the expression on the right hand side, and the right hand side needs to happen AFTER the subscripts have been evaluated.
* The structure involved - the "glvn pool" - consists of a stack of entries, each corresponding to a single glvn, and
* a parallel stack of mvals, each corresponding to some parent entry. Both stacks are expandable, doubling in size whenever
* they run out of space. The glvn pool entries can be popped in three different ways. For SET, it's convenient to save the
* glvn pool state, i.e. the top of the array of still-relevant entries. After completion of the set, the pool is restored to
* this state and younger entries popped. With FOR, it's more convenient defer popping until another FOR loop at the same
* nesting level starts. At that time the previously used FOR slot is recycled and everything younger than it is popped.
* Finally, when a non-indirect frame is unwound, all younger pool entries are popped.
*/
#define ANY_SLOT 0
#define FIRST_SAVED_ARG(SLOT) ((OC_SAVLVN == (SLOT)->sav_opcode) ? 1 : 0)
/* To avoid breaking gtmpcat, we retain the 'for_ctrl_stack' field of the frame_pointer struct instead of replacing it
* with a uint4 'glvn_indx' field. The macros manipulate this field. Also for the convenience of gtmpcat: we declare the
* glvn_pool and glvn_pool_entry structs in compiler.h instead of here. This is because gtmpcat does not know to include
* glvn_pool.h when going through gtm_threadgbl_defs.h.
* When gtmpcat is changed to accommodate a new name, these macros and the stack frame struct need to be changed,
* and the glvn_pool structs in compiler.h should probably be moved into this file.
*/
#define GLVN_INDX(FP) ((uint4)(UINTPTR_T)((FP)->for_ctrl_stack))
#define GLVN_POOL_EMPTY ((uint4)-1) /* this must be an "impossible" value for a real pool */
#define GLVN_POOL_SLOTS_AVAILABLE ((TREF(glvn_pool_ptr))->capacity - (TREF(glvn_pool_ptr))->top)
#define GLVN_POOL_MVALS_AVAILABLE ((TREF(glvn_pool_ptr))->mval_capacity - (TREF(glvn_pool_ptr))->mval_top)
#define INIT_GLVN_POOL_CAPACITY 8
#define INIT_GLVN_POOL_MVAL_CAPACITY 64
#define GLVN_POOL_UNTOUCHED 0
#define MAX_EXPECTED_CAPACITY 2048
#define MAX_EXPECTED_MVAL_CAPACITY 2048
#define SLOT_NEEDS_REWIND(INDX) (((TREF(glvn_pool_ptr))->top <= (INDX)) && (GLVN_POOL_EMPTY != (INDX)))
#define SLOT_OPCODE(INDX) ((TREF(glvn_pool_ptr))->slot[INDX].sav_opcode)
#define SET_GLVN_INDX(FP, VALUE) \
{ \
(FP)->for_ctrl_stack = (unsigned char *)(UINTPTR_T)(VALUE); \
}
#define GLVN_POOL_EXPAND_IF_NEEDED \
{ \
if (!TREF(glvn_pool_ptr)) \
glvn_pool_init(); \
else if (!GLVN_POOL_SLOTS_AVAILABLE) \
glvn_pool_expand_slots(); \
}
#define ENSURE_GLVN_POOL_SPACE(SPC) \
{ \
if (GLVN_POOL_MVALS_AVAILABLE < (uint4)(SPC)) \
{ \
glvn_pool_expand_mvals(); \
assert(GLVN_POOL_MVALS_AVAILABLE >= (uint4)(SPC)); \
} \
}
#define GET_GLVN_POOL_STATE(SLOT, M) \
{ /* Find current available SLOT and mval. */ \
uint4 INDX, MVAL_INDX; \
\
INDX = (TREF(glvn_pool_ptr))->share_slot; \
SLOT = &(TREF(glvn_pool_ptr))->slot[INDX]; \
MVAL_INDX = SLOT->mval_top; \
M = &(TREF(glvn_pool_ptr))->mval_stack[MVAL_INDX]; \
}
#define DRAIN_GLVN_POOL_IF_NEEDED \
{ \
int I; \
uint4 INDX, FINDX; \
glvn_pool_entry *SLOT; \
\
if ((GLVN_POOL_UNTOUCHED != GLVN_INDX(frame_pointer)) && !(frame_pointer->flags & SFF_INDCE)) \
{ /* Someone used an ugly FOR control variable or did an indirect set. */ \
INDX = (GLVN_POOL_EMPTY != GLVN_INDX(frame_pointer)) ? GLVN_INDX(frame_pointer) : 0; \
op_glvnpop(INDX); \
for (I = 1; I <= MAX_FOR_STACK; I++) \
{ /* rewind the for_slot array */ \
FINDX = (TREF(glvn_pool_ptr))->for_slot[I]; \
if (SLOT_NEEDS_REWIND(FINDX)) \
{ /* reset to precursor */ \
SLOT = &(TREF(glvn_pool_ptr))->slot[FINDX]; \
assert(!SLOT_NEEDS_REWIND(SLOT->precursor)); \
(TREF(glvn_pool_ptr))->for_slot[I] = SLOT->precursor; \
} else /* no higher FOR levels were used by current frame */ \
break; \
} \
} \
}
#define INSERT_INDSAVGLVN(CTRL, V, RECYCLE, DO_REF) \
{ \
triple *PUSH, *SAV, *PAR; \
\
PUSH = newtriple(OC_GLVNSLOT); \
PUSH->operand[0] = put_ilit((mint)(RECYCLE)); \
CTRL = put_tref(PUSH); \
SAV = newtriple(OC_INDSAVGLVN); \
SAV->operand[0] = V; \
PAR = newtriple(OC_PARAMETER); \
SAV->operand[1] = put_tref(PAR); \
PAR->operand[0] = CTRL; \
PAR->operand[1] = put_ilit((mint)(DO_REF)); /* flag to suppress global reference here */ \
}
void glvn_pool_init(void); /* invoked via GLVN_POOL_EXPAND_IF_NEEDED macro */
void glvn_pool_expand_slots(void); /* invoked via GLVN_POOL_EXPAND_IF_NEEDED macro */
void glvn_pool_expand_mvals(void); /* invoked via ENSURE_GLVN_POOL_SPACE macro */
void op_glvnpop(uint4 indx); /* Used by [SET and $ORDER()] */
uint4 op_glvnslot(uint4 recycle); /* Used by [FOR, SET and $ORDER()] */
void op_indsavglvn(mval *target, uint4 slot, uint4 do_ref); /* Used by [SET and $ORDER()] */
void op_indsavlvn(mval *target, uint4 slot); /* Used by [FOR] */
void op_rfrshgvn(uint4 indx, opctype oc); /* Used by [SET and $ORDER()] */
lv_val *op_rfrshlvn(uint4 indx, opctype oc); /* Used by [FOR, SET and $ORDER()] */
void op_savgvn(UNIX_ONLY_COMMA(int argcnt) mval *val_arg, ...); /* Used by [SET and $ORDER()] */
void op_savlvn(UNIX_ONLY_COMMA(int argcnt) lv_val *start, ...); /* Used by [FOR, SET and $ORDER()] */
void op_shareslot(uint4 indx, opctype opcode); /* Used by [FOR, SET and $ORDER()] */
void op_stoglvn(uint4 indx, mval *value); /* Used by [SET] */
#endif /* GLVN_POOL_H_INCLUDED */