Beispiel #1
0
void cache_put(icode_str *src, mstr *object)
{
	cache_entry	*csp;
	int		i, fixup_cnt;
	mval		*fix_base, *fix;
	var_tabent	*var_base, *varent;
	ht_ent_objcode	*tabent;
	boolean_t	added;

	indir_cache_mem_size += (ICACHE_SIZE + object->len);
	if (indir_cache_mem_size > max_cache_memsize || cache_table.size > max_cache_entries)
		cache_table_rebuild();
	csp = (cache_entry *)GTM_TEXT_ALLOC(ICACHE_SIZE + object->len);
	csp->obj.addr = (char *)csp + ICACHE_SIZE;
	csp->refcnt = csp->zb_refcnt = 0;
	csp->src = *src;
	csp->obj.len = object->len;
	memcpy(csp->obj.addr, object->addr, object->len);
	((ihdtyp *)(csp->obj.addr))->indce = csp;	/* Set backward link to this cache entry */
	added = add_hashtab_objcode(&cache_table, &csp->src, csp, &tabent);
	assert(added);

	/* Do address fixup on the literals that preceed the code */
	fixup_cnt = ((ihdtyp *)(csp->obj.addr))->fixup_vals_num;
	if (fixup_cnt)
	{
		/* Do address fixups for literals in indirect code. This is done by making them point
		   to the literals that are still resident in the stringpool. The rest of the old object
		   code will be garbage collected but these literals will be salvaged. The reason to point
		   to the stringpool version instead of in the copy we just created is that if an assignment
		   to a local variable from an indirect string literal were to occur, only the mval is copied.
		   So then there would be a local variable mval pointing into our malloc'd storage instead of
		   the stringpool. If the cache entry were recycled to hold a different object, the local
		   mval would then be pointing at garbage. By pointing these literals to their stringpool
		   counterparts, we save having to (re)copy them to the stringpool where they will be handled
		   safely and correctly.
		*/
		fix_base = (mval *)((unsigned char *)csp->obj.addr + ((ihdtyp *)(csp->obj.addr))->fixup_vals_off);

		for (fix = fix_base, i = 0 ;  i < fixup_cnt ;  i++, fix++)
		{
			if (MV_IS_STRING(fix))		/* if string, place in string pool */
				fix->str.addr = (INTPTR_T)fix->str.addr + object->addr;
		}
	}
	fixup_cnt = ((ihdtyp *)(csp->obj.addr))->vartab_len;
	if (fixup_cnt)
	{
		/* Do address fix up of local variable name which is in stringpool */
		var_base = (var_tabent *)((unsigned char *)csp->obj.addr + ((ihdtyp *)(csp->obj.addr))->vartab_off);
		for (varent = var_base, i = 0; i < fixup_cnt; i++, varent++)
			varent->var_name.addr = (INTPTR_T) varent->var_name.addr + object->addr;
	}
	*object = csp->obj;				/* Update location of object code for comp_indr */
	cacheflush(csp->obj.addr, csp->obj.len, BCACHE);
}
/* The code created and returned by make_cimode() is executed in the frame GTM$CI at level 1 of
 * every nested call-in environment. For every M routine being called-in from C, GTM$CI code
 * will setup argument registers/stack and executes the M routine. When the M routine returns
 * from its final QUIT, GTM$CI returns to gtm_ci(). make_cimode generates machine equivalents
 * for the following operations in that order:
 *
 * 	CALL ci_restart	 :setup register/stack arguments from 'param_list' and transfer control
 * 		to op_extcall/op_extexfun which return only after the M routine finishes and QUITs.
 * 	CALL ci_ret_code :transfer control from the M routine back to C (gtm_ci). Never returns.
 * 	CALL opp_ret	 :an implicit QUIT although it is never executed.
 *
 * Before GTM$CI executes, it is assumed that the global 'param_list' has been populated with
 * argument/return mval*.
 */
rhdtyp *make_cimode(void)
{
	static rhdtyp	*base_address = NULL;
	lab_tabent	*lbl;
	int		*lnr;
	unsigned char	*code;

	if (NULL != base_address)
		return base_address;
	base_address = (rhdtyp *)GTM_TEXT_ALLOC(SIZEOF(rhdtyp) + CODE_SIZE + SIZEOF(lab_tabent) + CODE_LINES * SIZEOF(int4));
	memset(base_address,0,SIZEOF(rhdtyp) + CODE_SIZE + SIZEOF(lab_tabent) + CODE_LINES * SIZEOF(int4));
	base_address->routine_name.len = STR_LIT_LEN(GTM_CIMOD);
	base_address->routine_name.addr = GTM_CIMOD;
	base_address->ptext_ptr = SIZEOF(rhdtyp);
	base_address->vartab_ptr =
		base_address->labtab_ptr = SIZEOF(rhdtyp) + CODE_SIZE;	/* hdr + code */
	base_address->lnrtab_ptr = SIZEOF(rhdtyp) + CODE_SIZE + SIZEOF(lab_tabent);
	base_address->labtab_len = 1;
	base_address->lnrtab_len = CODE_LINES;
	code = (unsigned char *) base_address + base_address->ptext_ptr;
	*code++ = I386_INS_CALL_Jv;
	*((int4 *)code) = (int4)((unsigned char *)ci_restart - (code + SIZEOF(int4)));
	code += SIZEOF(int4);
	*code++ = I386_INS_CALL_Jv; /* a CALL to return control from M to ci_ret_code() which in turn returns to gtm_ci() */
	*((int4 *)code) = (int4)((unsigned char *)ci_ret_code - (code + SIZEOF(int4)));
	code += SIZEOF(int4);
	*code++ = I386_INS_JMP_Jv;
	*((int4 *)code) = (int4)((unsigned char *)opp_ret - (code + SIZEOF(int4)));
	code += SIZEOF(int4);
	lbl = (lab_tabent *)((int) base_address + base_address->labtab_ptr);
	lbl->lab_ln_ptr = base_address->lnrtab_ptr;
	lnr = (int *)((int)base_address + base_address->lnrtab_ptr);
	*lnr++ = base_address->ptext_ptr;
	*lnr++ = base_address->ptext_ptr;
	*lnr++ = base_address->ptext_ptr + 2 * CALL_SIZE;
	assert(code - ((unsigned char *)base_address + base_address->ptext_ptr) == CODE_SIZE);
	zlput_rname(base_address);
	inst_flush(base_address, SIZEOF(rhdtyp) + CODE_SIZE + SIZEOF(lab_tabent) + CODE_LINES * SIZEOF(int4));
	return base_address;
}
Beispiel #3
0
rhdtyp *make_dmode(void)
{
	rhdtyp		*base_address;
	lab_tabent	*lbl;
	int		*lnr;
	unsigned char	*code;
						/* dummy code + label entry + line entries */
	base_address = (rhdtyp *)GTM_TEXT_ALLOC(SIZEOF(rhdtyp) + CODE_SIZE + SIZEOF(lab_tabent) + CODE_LINES * SIZEOF(int4));
	memset(base_address,0,SIZEOF(rhdtyp) + CODE_SIZE + SIZEOF(lab_tabent) + CODE_LINES*SIZEOF(int4));
	base_address->routine_name.len = STR_LIT_LEN(GTM_DMOD);
	base_address->routine_name.addr = GTM_DMOD;
	base_address->ptext_ptr = SIZEOF(rhdtyp);
	base_address->vartab_ptr =
		base_address->labtab_ptr = SIZEOF(rhdtyp) + CODE_SIZE;	/* hdr + code */
	base_address->lnrtab_ptr = SIZEOF(rhdtyp) + CODE_SIZE + SIZEOF(lab_tabent);
	base_address->labtab_len = 1;
	base_address->lnrtab_len = CODE_LINES;
	code = (unsigned char *) base_address + base_address->ptext_ptr;
	*code++ = I386_INS_CALL_Jv;
	*((int4 *)code) = (int4)((unsigned char *)dm_setup - (code + SIZEOF(int4)));
	code += SIZEOF(int4);
	*code++ = I386_INS_CALL_Jv; /* this should be a CALL to maintain uniformity between transfer to mum_tstart from baseframe
				       and transfers to mum_tstart from error processing (MUM_TSTART marco in
				       mdb_condition_handler) */
	*((int4 *)code) = (int4)((unsigned char *)mum_tstart - (code + SIZEOF(int4)));
	code += SIZEOF(int4);
	*code++ = I386_INS_JMP_Jv;
	*((int4 *)code) = (int4)((unsigned char *)opp_ret - (code + SIZEOF(int4)));
	code += SIZEOF(int4);
	lbl = (lab_tabent *)((int) base_address + base_address->labtab_ptr);
	lbl->lab_ln_ptr = base_address->lnrtab_ptr;
	lnr = (int *)((int)base_address + base_address->lnrtab_ptr);
	*lnr++ = base_address->ptext_ptr;
	*lnr++ = base_address->ptext_ptr;
	*lnr++ = base_address->ptext_ptr + 2 * CALL_SIZE;
	assert(code - ((unsigned char *)base_address + base_address->ptext_ptr) == CODE_SIZE);
	zlput_rname(base_address);
	inst_flush(base_address, SIZEOF(rhdtyp) + CODE_SIZE + SIZEOF(lab_tabent) + CODE_LINES * SIZEOF(int4));
	return base_address;
}
Beispiel #4
0
rhdtyp *make_mode (int mode_index)
{
	rhdtyp		*base_address;
	lab_tabent	*lbl;
	lnr_tabent	*lnr;
	CODEBUF_TYPE	*code;
	dyn_modes	*dmode;
	int algnd_rtnhdr_size = (int)ROUND_UP2(SIZEOF(rhdtyp), SECTION_ALIGN_BOUNDARY);
	int algnd_code_size   = (int)ROUND_UP2(CODE_SIZE, NATIVE_WSIZE);
	int algnd_lbltab_size = (int)ROUND_UP2(SIZEOF(lab_tabent), NATIVE_WSIZE);
	int algnd_lnrtab_size = (int)ROUND_UP2(CODE_LINES * SIZEOF(lnr_tabent), NATIVE_WSIZE);

	assert((DM_MODE == mode_index) || (CI_MODE == mode_index));
        base_address = (rhdtyp *)GTM_TEXT_ALLOC(algnd_rtnhdr_size + algnd_code_size + algnd_lbltab_size + algnd_lnrtab_size);
	memset(base_address, 0, algnd_rtnhdr_size + algnd_code_size + algnd_lbltab_size + algnd_lnrtab_size);
	dmode = &our_modes[mode_index];
	base_address->routine_name.len = dmode->rtn_name_len;
	base_address->routine_name.addr = dmode->rtn_name;
	base_address->ptext_adr = (unsigned char *)base_address + algnd_rtnhdr_size;
	base_address->ptext_end_adr = (unsigned char *)base_address->ptext_adr + algnd_code_size;
	base_address->lnrtab_adr = (lnr_tabent *)base_address->ptext_end_adr;
	base_address->labtab_adr = (lab_tabent *)((unsigned char *)base_address + algnd_rtnhdr_size +
						  algnd_code_size + algnd_lnrtab_size);
	base_address->lnrtab_len = CODE_LINES;
	base_address->labtab_len = 1;
	code = (CODEBUF_TYPE *)base_address->ptext_adr;	/* start of executable code */
#ifdef __ia64
	if (dyn_modes_type[mode_index][0] == 'C')
	{
		GEN_CALL_C(CODE_ADDRESS(dmode->func_ptr1))		/* line 0,1 */
	} else
	{
		GEN_CALL_ASM(CODE_ADDRESS(dmode->func_ptr1))		/* line 0,1 */
	}
#else
	GEN_CALL(dmode->func_ptr1);			/* line 0,1 */
#endif /* __ia64 */

#ifdef _AIX
	if (CI_MODE == mode_index)
	{
		/* Following 2 instructions are generated to call the routine stored in GTM_REG_ACCUM.
		 * ci_restart would have loaded this register with the address of op_extcall/op_extexfun.
		 * On other platforms, ci_start usually invokes op_ext* which will return directly
		 * to the generated code. Since RS6000 doesn't support call instruction without altering
		 * return address register (LR), the workaround is to call op_ext* not from ci_restart
		 * but from this dummy code
		 */
		*code++ = RS6000_INS_MTLR | GTM_REG_ACCUM << RS6000_SHIFT_RS;
		*code++ = RS6000_INS_BRL;
	}
#endif

#ifdef __ia64
        if (dyn_modes_type[mode_index][1] == 'C')
	{
                GEN_CALL_C(CODE_ADDRESS(dmode->func_ptr2))
	} else
	{
                GEN_CALL_ASM(CODE_ADDRESS(dmode->func_ptr2))
	}
#else
        GEN_CALL(dmode->func_ptr2);
#endif /* __ia64 */

#if defined (__ia64)
	if (DM_MODE == mode_index)
	{
		GEN_UNCOD_JUMP(-(2 * 5)); /* branch to dm_setup which is at the top of the direct mode frame. */
	}
#elif defined(__hpux)
	if (DM_MODE == mode_index)
	{
		*code++ = HPPA_INS_BEQ | (MAKE_COND_BRANCH_TARGET(-8) << HPPA_SHIFT_OFFSET); /* BEQ r0,r0, -8 */
		*code++ = HPPA_INS_NOP;
	}
#endif /* __ia64 */

#ifdef __ia64
        if (dyn_modes_type[mode_index][2] == 'C')
	{
                GEN_CALL_C(CODE_ADDRESS(dmode->func_ptr3));  	/* line 2 */
	} else
	{
                GEN_CALL_ASM(CODE_ADDRESS(dmode->func_ptr3));  /* line 2 */
	}
#else
        GEN_CALL(dmode->func_ptr3); 			/* line 2 */
#endif /* __ia64 */
	lnr = LNRTAB_ADR(base_address);
	*lnr++ = 0;								/* line 0 */
	*lnr++ = 0;								/* line 1 */
	IA64_ONLY(*lnr++ = 2 * CALL_SIZE + EXTRA_INST_SIZE;)			/* line 2 */