139 lines
5.1 KiB
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);
|
||
|
}
|
||
|
}
|
||
|
}
|