diff options
-rw-r--r-- | src/common/db.c | 1 | ||||
-rw-r--r-- | src/common/ers.c | 21 | ||||
-rw-r--r-- | src/common/ers.h | 6 | ||||
-rw-r--r-- | src/map/script.c | 342 |
4 files changed, 191 insertions, 179 deletions
diff --git a/src/common/db.c b/src/common/db.c index 561371787..99c758a8d 100644 --- a/src/common/db.c +++ b/src/common/db.c @@ -2611,6 +2611,7 @@ void* db_data2ptr(DBData *data) void db_init(void) { db_iterator_ers = ers_new(sizeof(struct DBIterator_impl),"db.c::db_iterator_ers",ERS_OPT_NONE); db_alloc_ers = ers_new(sizeof(struct DBMap_impl),"db.c::db_alloc_ers",ERS_OPT_NONE); + ers_chunk_size(db_alloc_ers, 50); DB_COUNTSTAT(db_init); } diff --git a/src/common/ers.c b/src/common/ers.c index 69b7609d6..27d9222ff 100644 --- a/src/common/ers.c +++ b/src/common/ers.c @@ -84,6 +84,9 @@ typedef struct ers_cache // Objects in-use count unsigned int UsedObjs; + // Default = ERS_BLOCK_ENTRIES, can be adjusted for performance for individual cache sizes. + unsigned int ChunkSize; + // Linked list struct ers_cache *Next, *Prev; } ers_cache_t; @@ -136,6 +139,7 @@ static ers_cache_t *ers_find_cache(unsigned int size) cache->Used = 0; cache->UsedObjs = 0; cache->Max = 0; + cache->ChunkSize = ERS_BLOCK_ENTRIES; if (CacheList == NULL) { @@ -200,10 +204,10 @@ static void *ers_obj_alloc_entry(ERS self) RECREATE(instance->Cache->Blocks, unsigned char *, instance->Cache->Max); } - CREATE(instance->Cache->Blocks[instance->Cache->Used], unsigned char, instance->Cache->ObjectSize * ERS_BLOCK_ENTRIES); + CREATE(instance->Cache->Blocks[instance->Cache->Used], unsigned char, instance->Cache->ObjectSize * instance->Cache->ChunkSize); instance->Cache->Used++; - instance->Cache->Free = ERS_BLOCK_ENTRIES -1; + instance->Cache->Free = instance->Cache->ChunkSize -1; ret = &instance->Cache->Blocks[instance->Cache->Used - 1][instance->Cache->Free * instance->Cache->ObjectSize + sizeof(struct ers_list)]; } @@ -286,6 +290,18 @@ static void ers_obj_destroy(ERS self) aFree(instance); } +void ers_cache_size(ERS self, unsigned int new_size) { + struct ers_instance_t *instance = (struct ers_instance_t *)self; + + if (instance == NULL) { + ShowError("ers_cache_size: NULL object, skipping...\n"); + return; + } + + instance->Cache->ChunkSize = new_size; +} + + ERS ers_new(uint32 size, char *name, enum ERSOptions options) { struct ers_instance_t *instance; @@ -299,6 +315,7 @@ ERS ers_new(uint32 size, char *name, enum ERSOptions options) instance->VTable.free = ers_obj_free_entry; instance->VTable.entry_size = ers_obj_entry_size; instance->VTable.destroy = ers_obj_destroy; + instance->VTable.chunk_size = ers_cache_size; instance->Name = ( options & ERS_OPT_FREE_NAME ) ? aStrdup(name) : name; instance->Options = options; diff --git a/src/common/ers.h b/src/common/ers.h index 4871d8d50..51701d778 100644 --- a/src/common/ers.h +++ b/src/common/ers.h @@ -119,6 +119,8 @@ typedef struct eri { */ void (*destroy)(struct eri *self); + /* */ + void (*chunk_size) (struct eri *self, unsigned int new_size); } *ERS; #ifdef DISABLE_ERS @@ -127,6 +129,7 @@ typedef struct eri { # define ers_free(obj,entry) aFree(entry) # define ers_entry_size(obj) (size_t)0 # define ers_destroy(obj) +# define ers_chunk_size(obj,size) // Disable the public functions # define ers_new(size,name,options) NULL # define ers_report() @@ -138,6 +141,7 @@ typedef struct eri { # define ers_free(obj,entry) (obj)->free((obj),(entry)) # define ers_entry_size(obj) (obj)->entry_size(obj) # define ers_destroy(obj) (obj)->destroy(obj) +# define ers_chunk_size(obj,size) (obj)->chunk_size(obj,size) /** * Get a new instance of the manager that handles the specified entry size. @@ -154,7 +158,7 @@ ERS ers_new(uint32 size, char *name, enum ERSOptions options); /** * Print a report about the current state of the Entry Reusage System. * Shows information about the global system and each entry manager. - * The number of entries are checked and a warning is shown if extra reusable + * The number of entries are checked and a warning is shown if extra reusable * entries are found. * The extra entries are included in the count of reusable entries. */ diff --git a/src/map/script.c b/src/map/script.c index 7ce4a165f..b414247da 100644 --- a/src/map/script.c +++ b/src/map/script.c @@ -2241,7 +2241,7 @@ struct script_code* parse_script(const char *src,const char *file,int line,int o CREATE(code,struct script_code,1); code->script_buf = script_buf; code->script_size = script_size; - code->script_vars = idb_alloc(DB_OPT_RELEASE_DATA); + code->script_vars = NULL; return code; } @@ -2277,19 +2277,14 @@ void get_val(struct script_state* st, struct script_data* data) postfix = name[strlen(name) - 1]; //##TODO use reference_tovariable(data) when it's confirmed that it works [FlavioJS] - if( !reference_toconstant(data) && not_server_variable(prefix) ) - { + if( !reference_toconstant(data) && not_server_variable(prefix) ) { sd = script_rid2sd(st); - if( sd == NULL ) - {// needs player attached - if( postfix == '$' ) - {// string variable + if( sd == NULL ) {// needs player attached + if( postfix == '$' ) {// string variable ShowWarning("script:script->get_val: cannot access player variable '%s', defaulting to \"\"\n", name); data->type = C_CONSTSTR; data->u.str = ""; - } - else - {// integer variable + } else {// integer variable ShowWarning("script:script->get_val: cannot access player variable '%s', defaulting to 0\n", name); data->type = C_INT; data->u.num = 0; @@ -2298,112 +2293,100 @@ void get_val(struct script_state* st, struct script_data* data) } } - if( postfix == '$' ) - {// string variable + if( postfix == '$' ) {// string variable - switch( prefix ) - { - case '@': - data->u.str = pc->readregstr(sd, data->u.num); - break; - case '$': - data->u.str = mapreg_readregstr(data->u.num); - break; - case '#': - if( name[1] == '#' ) - data->u.str = pc_readaccountreg2str(sd, name);// global - else - data->u.str = pc_readaccountregstr(sd, name);// local - break; - case '.': - { - struct DBMap* n = - data->ref ? *data->ref: - name[1] == '@' ? st->stack->var_function:// instance/scope variable - st->script->script_vars;// npc variable - if( n ) - data->u.str = (char*)idb_get(n,reference_getuid(data)); + switch( prefix ) { + case '@': + data->u.str = pc->readregstr(sd, data->u.num); + break; + case '$': + data->u.str = mapreg_readregstr(data->u.num); + break; + case '#': + if( name[1] == '#' ) + data->u.str = pc_readaccountreg2str(sd, name);// global else - data->u.str = NULL; - } - break; - case '\'': - if ( st->instance_id >= 0 ) { - data->u.str = (char*)idb_get(instances[st->instance_id].vars,reference_getuid(data)); - } else { - ShowWarning("script:script->get_val: cannot access instance variable '%s', defaulting to \"\"\n", name); - data->u.str = NULL; + data->u.str = pc_readaccountregstr(sd, name);// local + break; + case '.': + { + struct DBMap* n = + data->ref ? *data->ref: + name[1] == '@' ? st->stack->var_function:// instance/scope variable + st->script->script_vars;// npc variable + if( n ) + data->u.str = (char*)idb_get(n,reference_getuid(data)); + else + data->u.str = NULL; } - break; - default: - data->u.str = pc_readglobalreg_str(sd, name); - break; + break; + case '\'': + if ( st->instance_id >= 0 ) { + data->u.str = (char*)idb_get(instances[st->instance_id].vars,reference_getuid(data)); + } else { + ShowWarning("script:script->get_val: cannot access instance variable '%s', defaulting to \"\"\n", name); + data->u.str = NULL; + } + break; + default: + data->u.str = pc_readglobalreg_str(sd, name); + break; } - if( data->u.str == NULL || data->u.str[0] == '\0' ) - {// empty string + if( data->u.str == NULL || data->u.str[0] == '\0' ) {// empty string data->type = C_CONSTSTR; data->u.str = ""; - } - else - {// duplicate string + } else {// duplicate string data->type = C_STR; data->u.str = aStrdup(data->u.str); } - } - else - {// integer variable + } else {// integer variable data->type = C_INT; - if( reference_toconstant(data) ) - { + if( reference_toconstant(data) ) { data->u.num = reference_getconstant(data); - } - else if( reference_toparam(data) ) - { + } else if( reference_toparam(data) ) { data->u.num = pc->readparam(sd, reference_getparamtype(data)); - } - else - switch( prefix ) - { - case '@': - data->u.num = pc->readreg(sd, data->u.num); - break; - case '$': - data->u.num = mapreg_readreg(data->u.num); - break; - case '#': - if( name[1] == '#' ) - data->u.num = pc_readaccountreg2(sd, name);// global - else - data->u.num = pc_readaccountreg(sd, name);// local - break; - case '.': - { - struct DBMap* n = - data->ref ? *data->ref: - name[1] == '@' ? st->stack->var_function:// instance/scope variable - st->script->script_vars;// npc variable - if( n ) - data->u.num = (int)idb_iget(n,reference_getuid(data)); - else - data->u.num = 0; + } else + switch( prefix ) { + case '@': + data->u.num = pc->readreg(sd, data->u.num); + break; + case '$': + data->u.num = mapreg_readreg(data->u.num); + break; + case '#': + if( name[1] == '#' ) + data->u.num = pc_readaccountreg2(sd, name);// global + else + data->u.num = pc_readaccountreg(sd, name);// local + break; + case '.': + { + struct DBMap* n = + data->ref ? *data->ref: + name[1] == '@' ? st->stack->var_function:// instance/scope variable + st->script->script_vars;// npc variable + if( n ) + data->u.num = (int)idb_iget(n,reference_getuid(data)); + else + data->u.num = 0; + } + break; + case '\'': + if( st->instance_id >= 0 ) + data->u.num = (int)idb_iget(instances[st->instance_id].vars,reference_getuid(data)); + else { + ShowWarning("script:script->get_val: cannot access instance variable '%s', defaulting to 0\n", name); + data->u.num = 0; + } + break; + default: + data->u.num = pc_readglobalreg(sd, name); + break; } - break; - case '\'': - if( st->instance_id >= 0 ) - data->u.num = (int)idb_iget(instances[st->instance_id].vars,reference_getuid(data)); - else { - ShowWarning("script:script->get_val: cannot access instance variable '%s', defaulting to 0\n", name); - data->u.num = 0; - } - break; - default: - data->u.num = pc_readglobalreg(sd, name); - break; - } } @@ -2777,6 +2760,10 @@ struct script_state* script_alloc_state(struct script_code* script, int pos, int st->oid = oid; st->sleep.timer = INVALID_TIMER; st->npc_item_flag = battle_config.item_enabled_npc; + + if( !st->script->script_vars ) + st->script->script_vars = idb_alloc(DB_OPT_RELEASE_DATA); + return st; } @@ -2785,16 +2772,20 @@ struct script_state* script_alloc_state(struct script_code* script, int pos, int /// @param st Script state void script_free_state(struct script_state* st) { - if(st->bk_st) - {// backup was not restored + if(st->bk_st) {// backup was not restored ShowDebug("script_free_state: Previous script state lost (rid=%d, oid=%d, state=%d, bk_npcid=%d).\n", st->bk_st->rid, st->bk_st->oid, st->bk_st->state, st->bk_npcid); } + if( st->sleep.timer != INVALID_TIMER ) iTimer->delete_timer(st->sleep.timer, run_script_timer); script_free_vars(st->stack->var_function); script->pop_stack(st, 0, st->stack->sp); aFree(st->stack->stack_data); aFree(st->stack); + if( st->script->script_vars && !db_size(st->script->script_vars) ) { + script_free_vars(st->script->script_vars); + st->script->script_vars = NULL; + } st->stack = NULL; st->pos = -1; aFree(st); @@ -3261,17 +3252,17 @@ int run_func(struct script_state *st) /*========================================== * script execution *------------------------------------------*/ -void run_script(struct script_code *rootscript,int pos,int rid,int oid) -{ +void run_script(struct script_code *rootscript,int pos,int rid,int oid) { struct script_state *st; if( rootscript == NULL || pos < 0 ) return; - + // TODO In jAthena, this function can take over the pending script in the player. [FlavioJS] // It is unclear how that can be triggered, so it needs the be traced/checked in more detail. // NOTE At the time of this change, this function wasn't capable of taking over the script state because st->scriptroot was never set. st = script_alloc_state(rootscript, pos, rid, oid); + run_script_main(st); } @@ -3415,7 +3406,7 @@ void run_script_main(struct script_state *st) int cmdcount = script_config.check_cmdcount; int gotocount = script_config.check_gotocount; TBL_PC *sd; - struct script_stack *stack=st->stack; + struct script_stack *stack = st->stack; struct npc_data *nd; script_attach_state(st); @@ -3433,86 +3424,85 @@ void run_script_main(struct script_state *st) } else if(st->state != END) st->state = RUN; - while(st->state == RUN) - { + while( st->state == RUN ){ enum c_op c = get_com(st->script->script_buf,&st->pos); switch(c){ - case C_EOL: - if( stack->defsp > stack->sp ) - ShowError("script:run_script_main: unexpected stack position (defsp=%d sp=%d). please report this!!!\n", stack->defsp, stack->sp); - else - script->pop_stack(st, stack->defsp, stack->sp);// pop unused stack data. (unused return value) - break; - case C_INT: - script->push_val(stack,C_INT,get_num(st->script->script_buf,&st->pos),NULL); - break; - case C_POS: - case C_NAME: - script->push_val(stack,c,GETVALUE(st->script->script_buf,st->pos),NULL); - st->pos+=3; - break; - case C_ARG: - script->push_val(stack,c,0,NULL); - break; - case C_STR: - script->push_str(stack,C_CONSTSTR,(char*)(st->script->script_buf+st->pos)); - while(st->script->script_buf[st->pos++]); - break; - case C_FUNC: - run_func(st); - if(st->state==GOTO){ - st->state = RUN; - if( !st->freeloop && gotocount>0 && (--gotocount)<=0 ){ - ShowError("run_script: infinity loop !\n"); - script_reportsrc(st); - st->state=END; + case C_EOL: + if( stack->defsp > stack->sp ) + ShowError("script:run_script_main: unexpected stack position (defsp=%d sp=%d). please report this!!!\n", stack->defsp, stack->sp); + else + script->pop_stack(st, stack->defsp, stack->sp);// pop unused stack data. (unused return value) + break; + case C_INT: + script->push_val(stack,C_INT,get_num(st->script->script_buf,&st->pos),NULL); + break; + case C_POS: + case C_NAME: + script->push_val(stack,c,GETVALUE(st->script->script_buf,st->pos),NULL); + st->pos+=3; + break; + case C_ARG: + script->push_val(stack,c,0,NULL); + break; + case C_STR: + script->push_str(stack,C_CONSTSTR,(char*)(st->script->script_buf+st->pos)); + while(st->script->script_buf[st->pos++]); + break; + case C_FUNC: + run_func(st); + if(st->state==GOTO){ + st->state = RUN; + if( !st->freeloop && gotocount>0 && (--gotocount)<=0 ){ + ShowError("run_script: infinity loop !\n"); + script_reportsrc(st); + st->state=END; + } } - } - break; + break; - case C_REF: - st->op2ref = 1; - break; + case C_REF: + st->op2ref = 1; + break; - case C_NEG: - case C_NOT: - case C_LNOT: - op_1(st ,c); - break; + case C_NEG: + case C_NOT: + case C_LNOT: + op_1(st ,c); + break; - case C_ADD: - case C_SUB: - case C_MUL: - case C_DIV: - case C_MOD: - case C_EQ: - case C_NE: - case C_GT: - case C_GE: - case C_LT: - case C_LE: - case C_AND: - case C_OR: - case C_XOR: - case C_LAND: - case C_LOR: - case C_R_SHIFT: - case C_L_SHIFT: - op_2(st, c); - break; + case C_ADD: + case C_SUB: + case C_MUL: + case C_DIV: + case C_MOD: + case C_EQ: + case C_NE: + case C_GT: + case C_GE: + case C_LT: + case C_LE: + case C_AND: + case C_OR: + case C_XOR: + case C_LAND: + case C_LOR: + case C_R_SHIFT: + case C_L_SHIFT: + op_2(st, c); + break; - case C_OP3: - op_3(st, c); - break; + case C_OP3: + op_3(st, c); + break; - case C_NOP: - st->state=END; - break; + case C_NOP: + st->state=END; + break; - default: - ShowError("unknown command : %d @ %d\n",c,st->pos); - st->state=END; - break; + default: + ShowError("unknown command : %d @ %d\n",c,st->pos); + st->state=END; + break; } if( !st->freeloop && cmdcount>0 && (--cmdcount)<=0 ){ ShowError("run_script: infinity loop !\n"); |