fis-gtm/sr_port/op_clralsvars.c

139 lines
5.1 KiB
C

/****************************************************************
* *
* Copyright 2009, 2011 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. *
* *
****************************************************************/
#include "mdef.h"
#include "gtm_string.h"
#include "gtm_stdio.h"
#include "rtnhdr.h"
#include "stack_frame.h"
#include "op.h"
#include "hashtab_mname.h"
#include "lv_val.h"
#include "gdsroot.h"
#include "gtm_facility.h"
#include "fileinfo.h"
#include "gdsbt.h"
#include "gdsfhead.h"
#include "alias.h"
GBLREF symval *curr_symval;
GBLREF stack_frame *frame_pointer;
GBLREF unsigned char *stackbase, *stacktop, *msp, *stackwarn;
/* Run the local var hash table looking for variables with the name "$ZWRTAC*" and performing
"KILL *" processing on any that are found and remove them from the hash table.
*/
void op_clralsvars(lv_val *rslt)
{
int htcnt, delcnt, table_size_orig;
boolean_t done;
hash_table_mname *table;
ht_ent_mname *table_base, *table_top, **last_lsym_hte, **htep, *table_base_orig;
ht_ent_mname *tabent, *tabent_top;
stack_frame *fp, *fpprev;
lv_val *lvp;
DEBUG_ONLY(boolean_t first_sym;)
delcnt = 0;
/* Remove $ZWRTAC* vars from hash table. Hash table shrink may be triggered in the next hashtab call */
for (tabent = curr_symval->h_symtab.base, tabent_top = curr_symval->h_symtab.top; tabent < tabent_top; tabent++)
{
if (HTENT_VALID_MNAME(tabent, lv_val, lvp))
{ /* Check if this var is $ZWRTAC* */
if ((STR_LIT_LEN(DOLLAR_ZWRTAC) <= tabent->key.var_name.len)
&& (0 == MEMCMP_LIT(tabent->key.var_name.addr, DOLLAR_ZWRTAC)))
{ /* Note use here of delete_hashtab_ent_mname() instead of delete_hashtab_mname() not
* only saves looking up the entry in the hashtab but avoids the chance of hashtable
* compaction which would be *really* bad since this call is not protected with the
* wrapper that add_hashtab_mname_symval() has to fix the l_symtab entries.
*/
DECR_BASE_REF_RQ(tabent, lvp, FALSE); /* Our ref disappears like the symbol */
delete_hashtab_ent_mname(&curr_symval->h_symtab, tabent); /* Remove from symbol table */
++delcnt;
}
}
}
if (delcnt)
{ /* Vars have been removed from hash table. Now find/clear any l_symtab entries that pointed
* to these vars (basically looking for pointers to deleted entries). Note this loop is similar
* to stack frame loops in als_lsymtab_repair().
*/
last_lsym_hte = NULL;
done = FALSE;
fp = frame_pointer;
table_base = curr_symval->h_symtab.base;
table_top = table_base + curr_symval->h_symtab.size;
assert(frame_pointer);
do
{
if (fp->l_symtab != last_lsym_hte)
{ /* Different l_symtab than last time (don't want to update twice) */
last_lsym_hte = fp->l_symtab;
if (fp->vartab_len)
{ /* Only process non-zero length l_symtabs */
DEBUG_ONLY(first_sym = TRUE);
for (htep = fp->l_symtab, htcnt = fp->vartab_len; htcnt; --htcnt, ++htep)
{
tabent = *htep;
if (NULL == tabent)
continue;
if (tabent < table_base || tabent >= table_top)
{ /* Entry doesn't point to the current symbol table */
assert(first_sym);
done = TRUE;
break;
}
if (HTENT_MARK_DELETED(tabent))
*htep = NULL; /* Clear l_symtab value for deleted hash entry */
DEBUG_ONLY(first_sym = FALSE);
}
}
}
if (done)
break;
fpprev = fp;
fp = fp->old_frame_pointer;
if (SFF_CI & fpprev->flags)
{ /* Callins needs to be able to crawl past apparent end of stack to earlier stack segments */
/* We should be in the base frame now. See if an earlier frame exists */
fp = *(stack_frame **)(fp + 1); /* Backups up to "prev pointer" created by base_frame() */
if (NULL == fp || fp >= (stack_frame *)stackbase || fp < (stack_frame *)stacktop)
break; /* Pointer not within the stack -- must be earliest occurence */
}
} while(fp);
/* Now that $ZWRTAC* vars have been deleted, we should check if compaction is a suggested thing
* to get rid of the deleted vars which will improve the free slot search and reduce the slot scan
* on a gargabe collection (both types). If it is, compact in a safe way and do the necessary l_symtab
* fixup.
*/
if (COMPACT_NEEDED(&curr_symval->h_symtab))
{ /* Step 1: Remember the current table */
table = &curr_symval->h_symtab;
table_base_orig = table->base;
table_size_orig = table->size;
/* Step 2: compact the table */
/* We'll do the base release once we do the reparations */
DEFER_BASE_REL_HASHTAB(table, TRUE);
compact_hashtab_mname(&curr_symval->h_symtab);
/* Step 3: fix l_symtab and related entries */
if (table_base_orig != curr_symval->h_symtab.base)
{
/* Only needed if expansion was successful */
als_lsymtab_repair(table, table_base_orig, table_size_orig);
FREE_BASE_HASHTAB(table, table_base_orig);
}
DEFER_BASE_REL_HASHTAB(table, FALSE);
}
}
}