sourcepawn/jit/x86/jit_x86.cpp
changeset 1908 318e0a01aef9
parent 1898 53dab8b45136
child 1913 a7416c7d48ea
     1.1 --- a/sourcepawn/jit/x86/jit_x86.cpp	Sat Mar 01 07:59:53 2008 +0000
     1.2 +++ b/sourcepawn/jit/x86/jit_x86.cpp	Sun Mar 02 06:40:59 2008 +0000
     1.3 @@ -1278,12 +1278,95 @@
     1.4  	IA32_Return(jit);
     1.5  }
     1.6  
     1.7 +void ProfCallGate_Begin(sp_context_t *ctx, const char *name)
     1.8 +{
     1.9 +	ctx->profiler->OnFunctionBegin(ctx->context, name);
    1.10 +}
    1.11 +
    1.12 +void ProfCallGate_End(sp_context_t *ctx)
    1.13 +{
    1.14 +	ctx->profiler->OnFunctionEnd();
    1.15 +}
    1.16 +
    1.17 +const char *find_func_name(sp_plugin_t *plugin, uint32_t offs)
    1.18 +{
    1.19 +	uint32_t max, iter;
    1.20 +	sp_fdbg_symbol_t *sym;
    1.21 +	sp_fdbg_arraydim_t *arr;
    1.22 +	uint8_t *cursor = (uint8_t *)(plugin->debug.symbols);
    1.23 +
    1.24 +	max = plugin->debug.syms_num;
    1.25 +	for (iter = 0; iter < max; iter++)
    1.26 +	{
    1.27 +		sym = (sp_fdbg_symbol_t *)cursor;
    1.28 +
    1.29 +		if (sym->ident == SP_SYM_FUNCTION
    1.30 +			&& sym->codestart <= offs 
    1.31 +			&& sym->codeend > offs)
    1.32 +		{
    1.33 +			return plugin->debug.stringbase + sym->name;
    1.34 +		}
    1.35 +
    1.36 +		if (sym->dimcount > 0)
    1.37 +		{
    1.38 +			cursor += sizeof(sp_fdbg_symbol_t);
    1.39 +			arr = (sp_fdbg_arraydim_t *)cursor;
    1.40 +			cursor += sizeof(sp_fdbg_arraydim_t) * sym->dimcount;
    1.41 +			continue;
    1.42 +		}
    1.43 +
    1.44 +		cursor += sizeof(sp_fdbg_symbol_t);
    1.45 +	}
    1.46 +
    1.47 +	return NULL;
    1.48 +}
    1.49 +
    1.50  inline void WriteOp_Call(JitWriter *jit)
    1.51  {
    1.52 -	cell_t offs = jit->read_cell();
    1.53 -
    1.54 -	jitoffs_t jmp = IA32_Call_Imm32(jit, 0);
    1.55 -	IA32_Write_Jump32(jit, jmp, RelocLookup(jit, offs, false));
    1.56 +	cell_t offs;
    1.57 +	jitoffs_t jmp;
    1.58 +	CompData *data;
    1.59 +		
    1.60 +	data = (CompData *)jit->data; 
    1.61 +	offs = jit->read_cell();
    1.62 +
    1.63 +	if ((data->profile & SP_PROF_FUNCTIONS) == SP_PROF_FUNCTIONS)
    1.64 +	{
    1.65 +		const char *name;
    1.66 +
    1.67 +		/* Find the function name */
    1.68 +		if ((name = find_func_name(data->plugin, offs)) == NULL)
    1.69 +		{
    1.70 +			name = "unknown";
    1.71 +		}
    1.72 +
    1.73 +		//push name
    1.74 +		//push [esi+context] 
    1.75 +		//call ProfCallGate_Begin
    1.76 +		//add esp, 8
    1.77 +		IA32_Push_Imm32(jit, (jit_int32_t)(intptr_t)name);
    1.78 +		IA32_Push_Rm_Disp8(jit, AMX_REG_INFO, AMX_INFO_CONTEXT);
    1.79 +		jmp = IA32_Call_Imm32(jit, 0);
    1.80 +		IA32_Write_Jump32_Abs(jit, jmp, (void *)ProfCallGate_Begin);
    1.81 +		IA32_Add_Rm_Imm8(jit, REG_ESP, 8, MOD_REG);
    1.82 +
    1.83 +		//call <addr>
    1.84 +		jmp = IA32_Call_Imm32(jit, 0);
    1.85 +		IA32_Write_Jump32(jit, jmp, RelocLookup(jit, offs, false));
    1.86 +
    1.87 +		//push [esi+context]
    1.88 +		//call ProfCallGate_End
    1.89 +		//add esp, 4
    1.90 +		IA32_Push_Rm_Disp8(jit, AMX_REG_INFO, AMX_INFO_CONTEXT);
    1.91 +		jmp = IA32_Call_Imm32(jit, 0);
    1.92 +		IA32_Write_Jump32_Abs(jit, jmp, (void *)ProfCallGate_End);
    1.93 +		IA32_Add_Rm_Imm8(jit, REG_ESP, 4, MOD_REG);
    1.94 +	}
    1.95 +	else
    1.96 +	{
    1.97 +		jmp = IA32_Call_Imm32(jit, 0);
    1.98 +		IA32_Write_Jump32(jit, jmp, RelocLookup(jit, offs, false));
    1.99 +	}
   1.100  }
   1.101  
   1.102  inline void WriteOp_Bounds(JitWriter *jit)
   1.103 @@ -1653,9 +1736,25 @@
   1.104  	jitoffs_t call = IA32_Call_Imm32(jit, 0);
   1.105  	if (!data->debug)
   1.106  	{
   1.107 -		IA32_Write_Jump32_Abs(jit, call, (void *)NativeCallback);
   1.108 -	} else {
   1.109 -		IA32_Write_Jump32_Abs(jit, call, (void *)NativeCallback_Debug);
   1.110 +		if ((data->profile & SP_PROF_NATIVES) == SP_PROF_NATIVES)
   1.111 +		{
   1.112 +			IA32_Write_Jump32_Abs(jit, call, (void *)NativeCallback_Profile);
   1.113 +		}
   1.114 +		else
   1.115 +		{
   1.116 +			IA32_Write_Jump32_Abs(jit, call, (void *)NativeCallback);
   1.117 +		}
   1.118 +	}
   1.119 +	else
   1.120 +	{
   1.121 +		if ((data->profile & SP_PROF_NATIVES) == SP_PROF_NATIVES)
   1.122 +		{
   1.123 +			IA32_Write_Jump32_Abs(jit, call, (void *)NativeCallback_Debug_Profile);
   1.124 +		}
   1.125 +		else
   1.126 +		{
   1.127 +			IA32_Write_Jump32_Abs(jit, call, (void *)NativeCallback_Debug);
   1.128 +		}
   1.129  	}
   1.130  	
   1.131  	/* check for errors */
   1.132 @@ -2122,7 +2221,9 @@
   1.133  
   1.134  cell_t NativeCallback(sp_context_t *ctx, ucell_t native_idx, cell_t *params)
   1.135  {
   1.136 -	sp_native_t *native = &ctx->natives[native_idx];
   1.137 +	sp_native_t *native;
   1.138 +	
   1.139 +	native = &ctx->natives[native_idx];
   1.140  
   1.141  	ctx->n_idx = native_idx;
   1.142  	
   1.143 @@ -2136,12 +2237,27 @@
   1.144  	return native->pfn(ctx->context, params);
   1.145  }
   1.146  
   1.147 -static cell_t InvalidNative(IPluginContext *pCtx, const cell_t *params)
   1.148 +cell_t NativeCallback_Profile(sp_context_t *ctx, ucell_t native_idx, cell_t *params)
   1.149  {
   1.150 -	sp_context_t *ctx = pCtx->GetContext();
   1.151 -	ctx->n_err = SP_ERROR_INVALID_NATIVE;
   1.152 -
   1.153 -	return 0;
   1.154 +	cell_t val;
   1.155 +	sp_native_t *native;
   1.156 +
   1.157 +	native = &ctx->natives[native_idx];
   1.158 +
   1.159 +	ctx->n_idx = native_idx;
   1.160 +
   1.161 +	/* Technically both aren't needed, I guess */
   1.162 +	if (native->status == SP_NATIVE_UNBOUND)
   1.163 +	{
   1.164 +		ctx->n_err = SP_ERROR_INVALID_NATIVE;
   1.165 +		return 0;
   1.166 +	}
   1.167 +
   1.168 +	ctx->profiler->OnNativeBegin(ctx->context, native);
   1.169 +	val = native->pfn(ctx->context, params);
   1.170 +	ctx->profiler->OnNativeEnd();
   1.171 +
   1.172 +	return val;
   1.173  }
   1.174  
   1.175  cell_t NativeCallback_Debug(sp_context_t *ctx, ucell_t native_idx, cell_t *params)
   1.176 @@ -2170,7 +2286,7 @@
   1.177  	}
   1.178  
   1.179  	cell_t result = NativeCallback(ctx, native_idx, params);
   1.180 -	
   1.181 +
   1.182  	if (ctx->n_err != SP_ERROR_NONE)
   1.183  	{
   1.184  		return result;
   1.185 @@ -2180,7 +2296,9 @@
   1.186  	{
   1.187  		ctx->n_err = SP_ERROR_STACKLEAK;
   1.188  		return result;
   1.189 -	} else if (save_hp != ctx->hp) {
   1.190 +	}
   1.191 +	else if (save_hp != ctx->hp)
   1.192 +	{
   1.193  		ctx->n_err = SP_ERROR_HEAPLEAK;
   1.194  		return result;
   1.195  	}
   1.196 @@ -2188,6 +2306,60 @@
   1.197  	return result;
   1.198  }
   1.199  
   1.200 +cell_t NativeCallback_Debug_Profile(sp_context_t *ctx, ucell_t native_idx, cell_t *params)
   1.201 +{
   1.202 +	cell_t save_sp = ctx->sp;
   1.203 +	cell_t save_hp = ctx->hp;
   1.204 +
   1.205 +	ctx->n_idx = native_idx;
   1.206 +
   1.207 +	if (ctx->hp < ctx->heap_base)
   1.208 +	{
   1.209 +		ctx->n_err = SP_ERROR_HEAPMIN;
   1.210 +		return 0;
   1.211 +	}
   1.212 +
   1.213 +	if (ctx->hp + STACK_MARGIN > ctx->sp)
   1.214 +	{
   1.215 +		ctx->n_err = SP_ERROR_STACKLOW;
   1.216 +		return 0;
   1.217 +	}
   1.218 +
   1.219 +	if ((uint32_t)ctx->sp >= ctx->mem_size)
   1.220 +	{
   1.221 +		ctx->n_err = SP_ERROR_STACKMIN;
   1.222 +		return 0;
   1.223 +	}
   1.224 +
   1.225 +	cell_t result = NativeCallback_Profile(ctx, native_idx, params);
   1.226 +
   1.227 +	if (ctx->n_err != SP_ERROR_NONE)
   1.228 +	{
   1.229 +		return result;
   1.230 +	}
   1.231 +
   1.232 +	if (save_sp != ctx->sp)
   1.233 +	{
   1.234 +		ctx->n_err = SP_ERROR_STACKLEAK;
   1.235 +		return result;
   1.236 +	}
   1.237 +	else if (save_hp != ctx->hp)
   1.238 +	{
   1.239 +		ctx->n_err = SP_ERROR_HEAPLEAK;
   1.240 +		return result;
   1.241 +	}
   1.242 +
   1.243 +	return result;
   1.244 +}
   1.245 +
   1.246 +static cell_t InvalidNative(IPluginContext *pCtx, const cell_t *params)
   1.247 +{
   1.248 +	sp_context_t *ctx = pCtx->GetContext();
   1.249 +	ctx->n_err = SP_ERROR_INVALID_NATIVE;
   1.250 +
   1.251 +	return 0;
   1.252 +}
   1.253 +
   1.254  jitoffs_t RelocLookup(JitWriter *jit, cell_t pcode_offs, bool relative)
   1.255  {
   1.256  	if (jit->outptr)
   1.257 @@ -2204,7 +2376,9 @@
   1.258  		assert(pcode_offs >= 0 && (uint32_t)pcode_offs <= data->codesize);
   1.259  		/* Do the lookup in the native dictionary. */
   1.260  		return *(jitoffs_t *)(data->rebase + pcode_offs);
   1.261 -	} else {
   1.262 +	}
   1.263 +	else
   1.264 +	{
   1.265  		return 0;
   1.266  	}
   1.267  }
   1.268 @@ -2423,6 +2597,7 @@
   1.269  	ctx->heap_base = plugin->data_size;
   1.270  	ctx->hp = ctx->heap_base;
   1.271  	ctx->sp = ctx->mem_size - sizeof(cell_t);
   1.272 +	ctx->prof_flags = data->profile;
   1.273  
   1.274  	const char *strbase = plugin->info.stringbase;
   1.275  	uint32_t max, iter;
   1.276 @@ -2726,7 +2901,7 @@
   1.277  {
   1.278  	CompData *data = (CompData *)co;
   1.279  
   1.280 -	if (strcmp(key, "debug") == 0)
   1.281 +	if (strcmp(key, SP_JITCONF_DEBUG) == 0)
   1.282  	{
   1.283  		if ((atoi(val) == 1) || !strcmp(val, "yes"))
   1.284  		{
   1.285 @@ -2741,6 +2916,18 @@
   1.286  		}
   1.287  		return true;
   1.288  	}
   1.289 +	else if (strcmp(key, SP_JITCONF_PROFILE) == 0)
   1.290 +	{
   1.291 +		data->profile = atoi(val);
   1.292 +
   1.293 +		/** Callbacks must be profiled to profile functions! */
   1.294 +		if ((data->profile & SP_PROF_FUNCTIONS) == SP_PROF_FUNCTIONS)
   1.295 +		{
   1.296 +			data->profile |= SP_PROF_CALLBACKS;
   1.297 +		}
   1.298 +
   1.299 +		return true;
   1.300 +	}
   1.301  
   1.302  	return false;
   1.303  }