From a64894bbe43e16169a4bcd85294ff6fffd9b8c54 Mon Sep 17 00:00:00 2001 From: David Anderson Date: Thu, 13 Mar 2008 17:04:25 +0000 Subject: [PATCH] updated to trunk code --HG-- branch : sourcemod-1.1.0 extra : convert_revision : svn%3A39bc706e-5318-0410-9160-8a85361fbb7c/branches/sourcemod-1.1.0%401936 --- sourcepawn/compiler/Makefile | 4 +- sourcepawn/compiler/sc1.c | 2 + sourcepawn/compiler/sc3.c | 11 +- sourcepawn/jit/x86/Makefile | 7 +- sourcepawn/jit/x86/dll_exports.cpp | 2 +- sourcepawn/jit/x86/jit_x86.cpp | 237 ++++++++++++++++++++++++++--- sourcepawn/jit/x86/jit_x86.h | 5 +- 7 files changed, 238 insertions(+), 30 deletions(-) diff --git a/sourcepawn/compiler/Makefile b/sourcepawn/compiler/Makefile index b7007401..c7b7c1dd 100644 --- a/sourcepawn/compiler/Makefile +++ b/sourcepawn/compiler/Makefile @@ -36,7 +36,7 @@ else CPPFLAGS += $(OPT_CPP_FLAGS) endif -CFLAGS += -DLINUX -DNDEBUG -DHAVE_STDINT_H -DAMX_ANSIONLY -DENABLE_BINRELOC +CFLAGS += -DLINUX -DNDEBUG -DHAVE_STDINT_H -DAMX_ANSIONLY -DENABLE_BINRELOC -m32 CPPFLAGS += -Wno-deprecated -fno-exceptions -fno-rtti OBJ_LINUX := $(OBJECTS:%.cpp=$(BIN_DIR)/%.o) @@ -53,7 +53,7 @@ all: $(MAKE) spcomp spcomp: $(OBJ_LINUX) - $(CPP) $(INCLUDE) $(CFLAGS) $(CPPFLAGS) $(OBJ_LINUX) $(LINK) -ldl -lm -o$(BIN_DIR)/$(BINARY) + $(CPP) $(INCLUDE) $(CFLAGS) $(CPPFLAGS) $(OBJ_LINUX) $(LINK) -m32 -ldl -lm -o$(BIN_DIR)/$(BINARY) debug: $(MAKE) all DEBUG=true diff --git a/sourcepawn/compiler/sc1.c b/sourcepawn/compiler/sc1.c index fc304674..75828758 100644 --- a/sourcepawn/compiler/sc1.c +++ b/sourcepawn/compiler/sc1.c @@ -4136,6 +4136,8 @@ static int newfunc(char *firstname,int firsttag,int fpublic,int fstatic,int stoc /* "declargs()" found the ")"; if a ";" appears after this, it was a * prototype */ if (matchtoken(';')) { + if (sym->usage & uPUBLIC) + error(10); sym->usage|=uFORWARD; if (!sc_needsemicolon) error(10); /* old style prototypes used with optional semicolumns */ diff --git a/sourcepawn/compiler/sc3.c b/sourcepawn/compiler/sc3.c index 5ff02707..2ef2be5c 100644 --- a/sourcepawn/compiler/sc3.c +++ b/sourcepawn/compiler/sc3.c @@ -1207,7 +1207,7 @@ static int hier14(value *lval1) } /* if */ } /* if */ if (lval3.sym->dim.array.level!=level) - return error(48); /* array dimensions must match */ + return error(47); /* array dimensions must match */ else if (ltlengthval || val==0) return error(47); /* array sizes must match */ else if (lval3.ident!=iARRAYCELL && !matchtag(lval3.sym->x.tags.index,idxtag,TRUE)) @@ -1217,6 +1217,7 @@ static int hier14(value *lval1) symbol *sym1 = lval3.sym; symbol *sym2 = lval2.sym; int i; + error(23); assert(sym1!=NULL && sym2!=NULL); /* ^^^ sym2 must be valid, because only variables can be * multi-dimensional (there are no multi-dimensional literals), @@ -1328,7 +1329,9 @@ static int hier13(value *lval) array1= (lval->ident==iARRAY || lval->ident==iREFARRAY); array2= (lval2.ident==iARRAY || lval2.ident==iREFARRAY); if (array1 && !array2) { - char *ptr=(lval->sym->name!=NULL) ? lval->sym->name : "-unknown-"; + const char *ptr = "-unknown-"; + if (lval->sym != NULL && lval->sym->name != NULL) + ptr = lval->sym->name; error(33,ptr); /* array must be indexed */ } else if (!array1 && array2) { char *ptr=(lval2.sym->name!=NULL) ? lval2.sym->name : "-unknown-"; @@ -1569,7 +1572,7 @@ static int hier2(value *lval) if (level>sym->dim.array.level+1) { error(28,sym->name); /* invalid subscript */ } else if (level==sym->dim.array.level+1) { - lval->constval= (idxsym!=NULL && idxsym->dim.array.length>0) ? idxsym->dim.array.length : 1; + lval->constval=(idxsym!=NULL && idxsym->dim.array.length>0) ? idxsym->dim.array.length : 1; } else { lval->constval=array_levelsize(sym,level); } @@ -2365,7 +2368,7 @@ static int nesting=0; */ } else { arglist[argpos]=ARG_DONE; /* flag argument as "present" */ - if (arg[argidx].numtags==1) /* set the expected tag, if any */ + if (arg[argidx].ident!=0 && arg[argidx].numtags==1) /* set the expected tag, if any */ lval.cmptag=arg[argidx].tags[0]; lvalue=hier14(&lval); assert(sc_status==statFIRST || arg[argidx].tags!=NULL); diff --git a/sourcepawn/jit/x86/Makefile b/sourcepawn/jit/x86/Makefile index 55148aac..d6bd4873 100644 --- a/sourcepawn/jit/x86/Makefile +++ b/sourcepawn/jit/x86/Makefile @@ -32,7 +32,10 @@ endif GCC_VERSION := $(shell $(CPP) -dumpversion >&1 | cut -b1) -CFLAGS += -D_LINUX -DNDEBUG -Dstricmp=strcasecmp -D_stricmp=strcasecmp -D_strnicmp=strncasecmp -Dstrnicmp=strncasecmp -D_snprintf=snprintf -D_vsnprintf=vsnprintf -D_alloca=alloca -Dstrcmpi=strcasecmp -Wall -Wno-non-virtual-dtor -Werror -fPIC -fno-exceptions -fno-rtti -msse -DHAVE_STDINT_H +CFLAGS += -D_LINUX -DNDEBUG -Dstricmp=strcasecmp -D_stricmp=strcasecmp -D_strnicmp=strncasecmp \ + -Dstrnicmp=strncasecmp -D_snprintf=snprintf -D_vsnprintf=vsnprintf -D_alloca=alloca \ + -Dstrcmpi=strcasecmp -Wall -Wno-non-virtual-dtor -Werror -fno-exceptions -fno-rtti \ + -DHAVE_STDINT_H -m32 ifeq "$(GCC_VERSION)" "4" CFLAGS += $(GCC4_FLAGS) @@ -52,7 +55,7 @@ all: ln -sf $(BIN_DIR)/$(BINARY) $(BINARY) binary: $(OBJ_LINUX) - $(CPP) $(INCLUDE) $(CFLAGS) $(OBJ_LINUX) $(LINK) -shared -ldl -lm -o$(BIN_DIR)/$(BINARY) + $(CPP) $(INCLUDE) $(CFLAGS) $(OBJ_LINUX) $(LINK) -m32 -shared -ldl -lm -o$(BIN_DIR)/$(BINARY) debug: $(MAKE) all DEBUG=true diff --git a/sourcepawn/jit/x86/dll_exports.cpp b/sourcepawn/jit/x86/dll_exports.cpp index f5f4c552..c69666c1 100644 --- a/sourcepawn/jit/x86/dll_exports.cpp +++ b/sourcepawn/jit/x86/dll_exports.cpp @@ -25,7 +25,7 @@ EXPORTFUNC int GiveEnginePointer2(SourcePawn::ISourcePawnEngine *engine_p, unsig { engine = engine_p; - if (api_version > SOURCEPAWN_ENGINE_API_VERSION) + if (api_version > SOURCEPAWN_ENGINE_API_VERSION || api_version < 2) { return SP_ERROR_PARAM; } diff --git a/sourcepawn/jit/x86/jit_x86.cpp b/sourcepawn/jit/x86/jit_x86.cpp index ec492a5b..6103f3da 100644 --- a/sourcepawn/jit/x86/jit_x86.cpp +++ b/sourcepawn/jit/x86/jit_x86.cpp @@ -1278,12 +1278,99 @@ inline void WriteOp_Retn(JitWriter *jit) IA32_Return(jit); } +void ProfCallGate_Begin(sp_context_t *ctx, const char *name) +{ + ctx->profiler->OnFunctionBegin(ctx->context, name); +} + +void ProfCallGate_End(sp_context_t *ctx) +{ + ctx->profiler->OnFunctionEnd(); +} + +const char *find_func_name(sp_plugin_t *plugin, uint32_t offs) +{ + uint32_t max, iter; + sp_fdbg_symbol_t *sym; + sp_fdbg_arraydim_t *arr; + uint8_t *cursor = (uint8_t *)(plugin->debug.symbols); + + max = plugin->debug.syms_num; + for (iter = 0; iter < max; iter++) + { + sym = (sp_fdbg_symbol_t *)cursor; + + if (sym->ident == SP_SYM_FUNCTION + && sym->codestart <= offs + && sym->codeend > offs) + { + return plugin->debug.stringbase + sym->name; + } + + if (sym->dimcount > 0) + { + cursor += sizeof(sp_fdbg_symbol_t); + arr = (sp_fdbg_arraydim_t *)cursor; + cursor += sizeof(sp_fdbg_arraydim_t) * sym->dimcount; + continue; + } + + cursor += sizeof(sp_fdbg_symbol_t); + } + + return NULL; +} + inline void WriteOp_Call(JitWriter *jit) { - cell_t offs = jit->read_cell(); + cell_t offs; + jitoffs_t jmp; + CompData *data; + + data = (CompData *)jit->data; + offs = jit->read_cell(); - jitoffs_t jmp = IA32_Call_Imm32(jit, 0); - IA32_Write_Jump32(jit, jmp, RelocLookup(jit, offs, false)); + if ((data->profile & SP_PROF_FUNCTIONS) == SP_PROF_FUNCTIONS) + { + const char *name; + + /* Find the function name */ + if ((name = find_func_name(data->plugin, offs)) == NULL) + { + name = "unknown"; + } + + //push name + //push [esi+context] + //call ProfCallGate_Begin + //add esp, 8 + IA32_Push_Imm32(jit, (jit_int32_t)(intptr_t)name); + IA32_Push_Rm_Disp8(jit, AMX_REG_INFO, AMX_INFO_CONTEXT); + jmp = IA32_Call_Imm32(jit, 0); + IA32_Write_Jump32_Abs(jit, jmp, (void *)ProfCallGate_Begin); + IA32_Add_Rm_Imm8(jit, REG_ESP, 8, MOD_REG); + + //call + //push eax + jmp = IA32_Call_Imm32(jit, 0); + IA32_Write_Jump32(jit, jmp, RelocLookup(jit, offs, false)); + IA32_Push_Reg(jit, REG_EAX); + + //push [esi+context] + //call ProfCallGate_End + //add esp, 4 + //pop eax + IA32_Push_Rm_Disp8(jit, AMX_REG_INFO, AMX_INFO_CONTEXT); + jmp = IA32_Call_Imm32(jit, 0); + IA32_Write_Jump32_Abs(jit, jmp, (void *)ProfCallGate_End); + IA32_Add_Rm_Imm8(jit, REG_ESP, 4, MOD_REG); + IA32_Pop_Reg(jit, REG_EAX); + } + else + { + jmp = IA32_Call_Imm32(jit, 0); + IA32_Write_Jump32(jit, jmp, RelocLookup(jit, offs, false)); + } } inline void WriteOp_Bounds(JitWriter *jit) @@ -1653,9 +1740,25 @@ inline void WriteOp_Sysreq_N(JitWriter *jit) jitoffs_t call = IA32_Call_Imm32(jit, 0); if (!data->debug) { - IA32_Write_Jump32_Abs(jit, call, (void *)NativeCallback); - } else { - IA32_Write_Jump32_Abs(jit, call, (void *)NativeCallback_Debug); + if ((data->profile & SP_PROF_NATIVES) == SP_PROF_NATIVES) + { + IA32_Write_Jump32_Abs(jit, call, (void *)NativeCallback_Profile); + } + else + { + IA32_Write_Jump32_Abs(jit, call, (void *)NativeCallback); + } + } + else + { + if ((data->profile & SP_PROF_NATIVES) == SP_PROF_NATIVES) + { + IA32_Write_Jump32_Abs(jit, call, (void *)NativeCallback_Debug_Profile); + } + else + { + IA32_Write_Jump32_Abs(jit, call, (void *)NativeCallback_Debug); + } } /* check for errors */ @@ -2122,7 +2225,9 @@ inline void WriteOp_FloatCompare(JitWriter *jit) cell_t NativeCallback(sp_context_t *ctx, ucell_t native_idx, cell_t *params) { - sp_native_t *native = &ctx->natives[native_idx]; + sp_native_t *native; + + native = &ctx->natives[native_idx]; ctx->n_idx = native_idx; @@ -2136,12 +2241,27 @@ cell_t NativeCallback(sp_context_t *ctx, ucell_t native_idx, cell_t *params) return native->pfn(ctx->context, params); } -static cell_t InvalidNative(IPluginContext *pCtx, const cell_t *params) +cell_t NativeCallback_Profile(sp_context_t *ctx, ucell_t native_idx, cell_t *params) { - sp_context_t *ctx = pCtx->GetContext(); - ctx->n_err = SP_ERROR_INVALID_NATIVE; + cell_t val; + sp_native_t *native; - return 0; + native = &ctx->natives[native_idx]; + + ctx->n_idx = native_idx; + + /* Technically both aren't needed, I guess */ + if (native->status == SP_NATIVE_UNBOUND) + { + ctx->n_err = SP_ERROR_INVALID_NATIVE; + return 0; + } + + ctx->profiler->OnNativeBegin(ctx->context, native); + val = native->pfn(ctx->context, params); + ctx->profiler->OnNativeEnd(); + + return val; } cell_t NativeCallback_Debug(sp_context_t *ctx, ucell_t native_idx, cell_t *params) @@ -2170,7 +2290,7 @@ cell_t NativeCallback_Debug(sp_context_t *ctx, ucell_t native_idx, cell_t *param } cell_t result = NativeCallback(ctx, native_idx, params); - + if (ctx->n_err != SP_ERROR_NONE) { return result; @@ -2180,7 +2300,9 @@ cell_t NativeCallback_Debug(sp_context_t *ctx, ucell_t native_idx, cell_t *param { ctx->n_err = SP_ERROR_STACKLEAK; return result; - } else if (save_hp != ctx->hp) { + } + else if (save_hp != ctx->hp) + { ctx->n_err = SP_ERROR_HEAPLEAK; return result; } @@ -2188,6 +2310,60 @@ cell_t NativeCallback_Debug(sp_context_t *ctx, ucell_t native_idx, cell_t *param return result; } +cell_t NativeCallback_Debug_Profile(sp_context_t *ctx, ucell_t native_idx, cell_t *params) +{ + cell_t save_sp = ctx->sp; + cell_t save_hp = ctx->hp; + + ctx->n_idx = native_idx; + + if (ctx->hp < ctx->heap_base) + { + ctx->n_err = SP_ERROR_HEAPMIN; + return 0; + } + + if (ctx->hp + STACK_MARGIN > ctx->sp) + { + ctx->n_err = SP_ERROR_STACKLOW; + return 0; + } + + if ((uint32_t)ctx->sp >= ctx->mem_size) + { + ctx->n_err = SP_ERROR_STACKMIN; + return 0; + } + + cell_t result = NativeCallback_Profile(ctx, native_idx, params); + + if (ctx->n_err != SP_ERROR_NONE) + { + return result; + } + + if (save_sp != ctx->sp) + { + ctx->n_err = SP_ERROR_STACKLEAK; + return result; + } + else if (save_hp != ctx->hp) + { + ctx->n_err = SP_ERROR_HEAPLEAK; + return result; + } + + return result; +} + +static cell_t InvalidNative(IPluginContext *pCtx, const cell_t *params) +{ + sp_context_t *ctx = pCtx->GetContext(); + ctx->n_err = SP_ERROR_INVALID_NATIVE; + + return 0; +} + jitoffs_t RelocLookup(JitWriter *jit, cell_t pcode_offs, bool relative) { if (jit->outptr) @@ -2204,7 +2380,9 @@ jitoffs_t RelocLookup(JitWriter *jit, cell_t pcode_offs, bool relative) assert(pcode_offs >= 0 && (uint32_t)pcode_offs <= data->codesize); /* Do the lookup in the native dictionary. */ return *(jitoffs_t *)(data->rebase + pcode_offs); - } else { + } + else + { return 0; } } @@ -2380,7 +2558,8 @@ jit_rewind: /* the total codesize is now known! */ codemem = writer.get_outputpos(); - writer.outbase = (jitcode_t)engine->ExecAlloc(codemem); + writer.outbase = (jitcode_t)engine->AllocatePageMemory(codemem); + engine->SetReadWrite(writer.outbase); writer.outptr = writer.outbase; /* go back for third pass */ goto jit_rewind; @@ -2398,6 +2577,8 @@ jit_rewind: } /* Write these last because error jumps should be unpredicted, and thus forward */ WriteErrorRoutines(data, jit); + + engine->SetReadExecute(writer.outbase); } /************* @@ -2420,6 +2601,7 @@ jit_rewind: ctx->heap_base = plugin->data_size; ctx->hp = ctx->heap_base; ctx->sp = ctx->mem_size - sizeof(cell_t); + ctx->prof_flags = data->profile; const char *strbase = plugin->info.stringbase; uint32_t max, iter; @@ -2605,22 +2787,25 @@ rewind: if (jw.outbase == NULL) { /* Second pass: Actually write */ - jw.outbase = (jitcode_t)engine->ExecAlloc(jw.get_outputpos()); + jw.outbase = (jitcode_t)engine->AllocatePageMemory(jw.get_outputpos()); if (!jw.outbase) { return NULL; } + engine->SetReadWrite(jw.outbase); jw.outptr = jw.outbase; goto rewind; } - + + engine->SetReadExecute(jw.outbase); + return (SPVM_NATIVE_FUNC)jw.outbase; } void JITX86::DestroyFakeNative(SPVM_NATIVE_FUNC func) { - engine->ExecFree((void *)func); + engine->FreePageMemory((void *)func); } const char *JITX86::GetVMName() @@ -2637,7 +2822,7 @@ int JITX86::ContextExecute(sp_context_t *ctx, uint32_t code_idx, cell_t *result) void JITX86::FreeContext(sp_context_t *ctx) { - engine->ExecFree(ctx->codebase); + engine->FreePageMemory(ctx->codebase); delete [] ctx->memory; delete [] ctx->files; delete [] ctx->lines; @@ -2720,7 +2905,7 @@ bool JITX86::SetCompilationOption(ICompilation *co, const char *key, const char { CompData *data = (CompData *)co; - if (strcmp(key, "debug") == 0) + if (strcmp(key, SP_JITCONF_DEBUG) == 0) { if ((atoi(val) == 1) || !strcmp(val, "yes")) { @@ -2735,6 +2920,18 @@ bool JITX86::SetCompilationOption(ICompilation *co, const char *key, const char } return true; } + else if (strcmp(key, SP_JITCONF_PROFILE) == 0) + { + data->profile = atoi(val); + + /** Callbacks must be profiled to profile functions! */ + if ((data->profile & SP_PROF_FUNCTIONS) == SP_PROF_FUNCTIONS) + { + data->profile |= SP_PROF_CALLBACKS; + } + + return true; + } return false; } diff --git a/sourcepawn/jit/x86/jit_x86.h b/sourcepawn/jit/x86/jit_x86.h index 1bdc1311..a1d9dc0b 100644 --- a/sourcepawn/jit/x86/jit_x86.h +++ b/sourcepawn/jit/x86/jit_x86.h @@ -67,13 +67,14 @@ class CompData : public ICompilation { public: CompData() : plugin(NULL), - debug(false), inline_level(0), rebase(NULL), + debug(false), profile(0), inline_level(0), rebase(NULL), error_set(SP_ERROR_NONE), func_idx(0) { }; public: sp_plugin_t *plugin; /* plugin handle */ bool debug; /* whether to compile debug mode */ + int profile; /* profiling flags */ int inline_level; /* inline optimization level */ jitcode_t rebase; /* relocation map */ int error_set; /* error code to halt process */ @@ -121,6 +122,8 @@ public: cell_t NativeCallback(sp_context_t *ctx, ucell_t native_idx, cell_t *params); cell_t NativeCallback_Debug(sp_context_t *ctx, ucell_t native_idx, cell_t *params); +cell_t NativeCallback_Debug_Profile(sp_context_t *ctx, ucell_t native_idx, cell_t *params); +cell_t NativeCallback_Profile(sp_context_t *ctx, ucell_t native_idx, cell_t *params); jitoffs_t RelocLookup(JitWriter *jit, cell_t pcode_offs, bool relative=false); #define AMX_REG_PRI REG_EAX