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 }