static void reg_free_block(sl_compile_state_t* cs, size_t reg, int count) { for(int i = 0; i < count; i++) { reg_free(cs, reg + i); } }
static void emit_assignment(sl_compile_state_t* cs, sl_node_base_t* lval, size_t reg) { sl_node_assign_var_t a_var; sl_node_send_t send; size_t dest_reg = reg_alloc(cs); sl_node__register_t node; node.base.type = SL_NODE__REGISTER; node.base.line = 0; node.reg = reg; switch(lval->type) { case SL_NODE_VAR: a_var.base.type = SL_NODE_ASSIGN_VAR; break; case SL_NODE_IVAR: a_var.base.type = SL_NODE_ASSIGN_IVAR; break; case SL_NODE_CVAR: a_var.base.type = SL_NODE_ASSIGN_CVAR; break; case SL_NODE_CONST: a_var.base.type = SL_NODE_ASSIGN_CONST; break; case SL_NODE_ARRAY: a_var.base.type = SL_NODE_ASSIGN_ARRAY; break; case SL_NODE_SEND: /* special case that turns a.b = 1 into a.send("b=", 1) */ /* this is separate to the other method of handling send assignments which also handles compound assignments. */ memcpy(&send, lval, sizeof(sl_node_send_t)); send.id = sl_id_make_setter(cs->vm, send.id); sl_node_base_t** args = sl_alloc(cs->vm->arena, sizeof(sl_node_base_t*) * (send.arg_count + 1)); memcpy(args, send.args, sizeof(sl_node_base_t*) * send.arg_count); args[send.arg_count++] = (sl_node_base_t*)&node; send.args = args; compile_node(cs, (sl_node_base_t*)&send, dest_reg); reg_free(cs, dest_reg); return; default: { SLVAL err = sl_make_cstring(cs->vm, "Invalid lval in assignment"); err = sl_make_error2(cs->vm, cs->vm->lib.SyntaxError, err); sl_error_add_frame(cs->vm, err, sl_make_cstring(cs->vm, "<compiler>"), sl_make_cstring(cs->vm, (char*)cs->section->filename), sl_make_int(cs->vm, lval->line)); sl_throw(cs->vm, err); } } a_var.base.line = 0; a_var.lval = (void*)lval; a_var.rval = (sl_node_base_t*)&node; compile_node(cs, (sl_node_base_t*)&a_var, dest_reg); reg_free(cs, dest_reg); }
void registers_free(REGISTERS *regs) { for(--regs->qtdRegs; regs->qtdRegs > 0; regs->qtdRegs--) { reg_free(regs->regs[regs->qtdRegs]); } free(regs); }
static void tnp_free_ep(registry_t *reg, void *en) { (void) reg; tn_endpoint_t *tnpep = (tn_endpoint_t*)en; reg_free(&(tnpep->base.files), tnp_free_file); if (tnpep->hostname) { mem_free(tnpep->hostname); } mem_free(en); }
NODE(sl_node_def_t, def) { sl_vm_insn_t insn; sl_compile_state_t sub_cs; size_t i, on_reg; init_compile_state(&sub_cs, cs->vm, cs, node->req_arg_count + node->opt_arg_count + 1); for(i = 0; i < node->req_arg_count; i++) { st_insert(sub_cs.vars, (st_data_t)node->req_args[i], (st_data_t)(i + 1)); } for(i = 0; i < node->opt_arg_count; i++) { st_insert(sub_cs.vars, (st_data_t)node->opt_args[i].name, (st_data_t)(node->req_arg_count + i + 1)); } sub_cs.section->name = node->name; sub_cs.section->req_registers = node->req_arg_count; sub_cs.section->arg_registers = node->req_arg_count + node->opt_arg_count; sub_cs.section->opt_skip = sl_alloc(cs->vm->arena, sizeof(size_t) * (node->opt_arg_count + 1)); for(i = 0; i < node->opt_arg_count; i++) { sub_cs.section->opt_skip[i] = sub_cs.section->insns_count; compile_node(&sub_cs, node->opt_args[i].default_value, node->req_arg_count + i + 1); } sub_cs.section->opt_skip[node->opt_arg_count] = sub_cs.section->insns_count; compile_node(&sub_cs, node->body, 0); insn.opcode = SL_OP_RETURN; emit(&sub_cs, insn); insn.uint = 0; emit(&sub_cs, insn); if(node->on) { on_reg = reg_alloc(cs); compile_node(cs, node->on, on_reg); insn.opcode = SL_OP_DEFINE_ON; emit(cs, insn); insn.uint = on_reg; emit(cs, insn); reg_free(cs, on_reg); } else { insn.opcode = SL_OP_DEFINE; emit(cs, insn); } insn.imm = node->name; emit(cs, insn); insn.section = sub_cs.section; emit(cs, insn); insn.uint = dest; emit(cs, insn); }
NODE(sl_node_def_t, def) { sl_compile_state_t sub_cs; size_t i, on_reg; size_t init_regs = 1 + node->req_arg_count + node->opt_arg_count; if(node->rest_arg) { init_regs++; } init_compile_state(&sub_cs, cs->vm, cs, init_regs); for(i = 0; i < node->req_arg_count; i++) { sl_st_insert(sub_cs.vars, (sl_st_data_t)node->req_args[i], (sl_st_data_t)(i + 1)); } for(i = 0; i < node->opt_arg_count; i++) { sl_st_insert(sub_cs.vars, (sl_st_data_t)node->opt_args[i].name, (sl_st_data_t)(node->req_arg_count + i + 1)); } if(node->rest_arg) { sl_st_insert(sub_cs.vars, (sl_st_data_t)node->rest_arg, (sl_st_data_t)(node->req_arg_count + node->opt_arg_count + 1)); sub_cs.section->has_extra_rest_arg = 1; } sub_cs.section->name = node->name; sub_cs.section->req_registers = node->req_arg_count; sub_cs.section->arg_registers = node->req_arg_count + node->opt_arg_count; sub_cs.section->opt_skip = sl_alloc(cs->vm->arena, sizeof(size_t) * (node->opt_arg_count + 1)); for(i = 0; i < node->opt_arg_count; i++) { sub_cs.section->opt_skip[i] = sub_cs.section->insns_count; compile_node(&sub_cs, node->opt_args[i].default_value, node->req_arg_count + i + 1); } sub_cs.section->opt_skip[node->opt_arg_count] = sub_cs.section->insns_count; compile_node(&sub_cs, node->body, 0); op_return(&sub_cs, 0); if(node->on) { on_reg = reg_alloc(cs); compile_node(cs, node->on, on_reg); op_define_on(cs, on_reg, node->name, node->doc, sub_cs.section, dest); reg_free(cs, on_reg); } else { op_define(cs, node->name, node->doc, sub_cs.section, dest); } }
static void tnp_end(void) { reg_free(&endpoints, tnp_free_ep); }
int main(int argn, char *argv[]) { unsigned int i, ret, readers, writers, tot_count_read = 0; timer exec_time; if(argn < 7) { fprintf(stderr, "Usage: %s: n_writer n_reader end_write end_read busy_write busy_read size\n", argv[0]); exit(EXIT_FAILURE); } writers = atoi(argv[1]); readers = atoi(argv[2]); size = atoi(argv[3]); if(argn == 7){ busy_write = atoi(argv[4]); busy_read = atoi(argv[5]); duration = atoi(argv[6]); } else if (argn == 8){ busy_write = atoi(argv[4]); busy_read = atoi(argv[5]); end_write = atoi(argv[6]); end_read = atoi(argv[7]); } pthread_t p_tid[writers + readers]; reg = reg_init(writers, readers, size); //reg = reg_init(writers, readers, DIM*sizeof(unsigned long long)); if((count_read = calloc(readers, sizeof(unsigned int))) == NULL){ printf("malloc failed\n"); abort(); } for(i = 0; i < writers; i++) { if( (ret = pthread_create(&p_tid[i], NULL, run_write, NULL)) != 0) { fprintf(stderr, "%s\n", strerror(errno)); abort(); } } for(i = 0; i < readers; i++) { if( (ret = pthread_create(&p_tid[writers+i], NULL, run_read, NULL)) != 0) { fprintf(stderr, "%s\n", strerror(errno)); abort(); } } sleep(1); printf("\n\n+-----------------------------------------------------------------------------------+\n"); printf("START TEST on REGISTER(%u,%u) of size %u: +\n", writers, readers, size); printf("\t write operation: %u, %u: +\n", end_write, busy_write); printf("\t read operation: %u, %u: +\n", end_read, busy_read); printf("+-----------------------------------------------------------------------------------+\n\n\n"); timer_start(exec_time); start = true; if(duration > 0){ sleep(duration); end = true; } for(i = 0; i < writers + readers; i++){ pthread_join(p_tid[i], NULL); } printf("\n\n+-----------------------------------------------------------------------------------+\n"); printf("TEST ENDED: %.5f seconds\n", (double)timer_value_seconds(exec_time)); printf("TOTAL WRTE: %u\n", count_write); for(i = 0; i < readers; i++) tot_count_read +=count_read[i]; printf("TOTAL READ: %u\n", tot_count_read); printf("TOTAL OPER: %u\n", tot_count_read+count_write); printf("+-----------------------------------------------------------------------------------+\n\n\n"); reg_free(reg); }
/* ------------------------------------------------------------------------------------------ */ void checkInstruction(ins *p){ reg *rz=NULL; reg *rx=NULL; reg *ry=NULL; reg *rt=NULL; // temporary register (may or not be used) ins *ip=NULL; // auxiliary instruction pointer (for other registers) ins *ti=NULL; // temporary instruction pointer (to be used with the temporary register) ins *mi=NULL; // main instruction pointer (used with the final instruction) /* * >> input: rz = rx <op> ry * * * rx = ARP + lookup(rx->value) * rx = * rx * ry = ARP + lookup(ry->value) * ry = * ry * rt = rx <op> ry * rz = ARP + lookup(rz->value) * *rz = rt */ if(p == NULL) return; #ifdef VERBOSE printf("\n"); table_print(registers); printf("[checkInstruction] "); printInstruction(p); #endif // :: -------------------------------- :: THE ALGORITHM :: // 1st step: ensure that 'rx' and 'ry' have register // -- // checking 'rx' if((p->src1[0] != '\0') && !isNumeric(p->src1)){ rx=reg_search(p->src1); if(rx==NULL){ // allocates register rx=reg_ensure(p->src1); if(isVar(p->src1)){ // loading the local variable from memory load(p->src1); ip = createInstruction(idx++); copy(ip->dst, rx->name); ip->arp=true; ip->offset=lookup(p->src1); append(ip); ip = createInstruction(idx++); copy(ip->dst, rx->name); ip->ops1='*'; copy(ip->src1, rx->name); append(ip); } if(rx!=NULL){ // set properties for register rx->dist=distance(p, rx->value); rx->dirty=false; } } } else rx=NULL; // checking 'ry' if((p->src2[0] != '\0') && !isNumeric(p->src2)){ ry=reg_search(p->src2); if(ry==NULL){ // allocates register ry=reg_ensure(p->src2); if(isVar(p->src2)){ // loading the local variable 'ry' from memory load(p->src2); // loading the local variable 'ry' from memory ip = createInstruction(idx++); copy(ip->dst, ry->name); ip->arp=true; ip->offset=lookup(p->src2); append(ip); ip = createInstruction(idx++); copy(ip->dst, ry->name); ip->ops1='*'; copy(ip->src1, ry->name); append(ip); } if(ry!=NULL){ // set properties for register ry->dist=distance(p, ry->value); ry->dirty=true; } } } else ry=NULL; // 2nd step: allocate the 'rt' temporary register; creates the 'ti' temporary instruction // -- ti = createInstruction(idx++); // get 'rx' if(isNumeric(p->src1)) copy(ti->src1, p->src1); // found a constant else if(rx!=NULL) copy(ti->src1, rx->name); // got the 'rx' // get the operator ti->ops2=p->ops2; // get 'ry' if(isNumeric(p->src2)) copy(ti->src2, p->src2); // found a constant else if(ry!=NULL) copy(ti->src2, ry->name); // got the 'ry' if((p->dst[0] != '\0') && !isNumeric(p->dst)){ // allocate the 'rt' register ("r0" by default) rt=reg_search("store"); // rt=reg_get(); if(rt!=NULL) rt->dirty=false; } else rt=NULL; // this could lead to an error if(rt!=NULL) copy(ti->dst, rt->name); append(ti); // 3rd step: frees if possible frees 'rx' and 'ry' // -- // free 'rx' if((rx!=NULL) && (rx->dist==MAXDIST || rx->dist==-2)) reg_free(rx); // free 'ry' if((ry!=NULL) && (ry->dist==MAXDIST || ry->dist==-2)) reg_free(ry); // 4th step: allocate the 'rz' register and create the main instruction 'mi' // -- mi = createInstruction(idx++); // allocate the 'rz' register if((p->dst[0] != '\0') && !isNumeric(p->dst)){ // store store(p->dst); rz=reg_search(p->dst); if(rz==NULL){ // allocates register rz=reg_ensure(p->dst); if(isVar(p->dst)){ // loads the local variable for store operation ip = createInstruction(idx++); copy(ip->dst, rz->name); ip->arp=true; ip->offset=lookup(p->dst); append(ip); } if(rz!=NULL){ // set properties for register rz->dist=distance(p, rz->value); rz->dirty=false; } } } else rz=NULL; // this would be an error if(rz!=NULL) copy(mi->dst, rz->name); if(rt!=NULL) copy(mi->src1, rt->name); if(isVar(p->dst)) mi->opd='*'; append(mi); // 5th step: frees 'rt'; if possible frees 'rz' // -- #ifdef VERBOSE if(rt!=NULL) printf(" [rt] store: %s :: (%s)\n", rt->name, rt->value); else printf(" [rt] is null\n"); if(rz!=NULL) printf(" [rz] store: %s :: (%s)\n", rz->name, rz->value); else printf(" [rz] is null\n"); #endif // free 'rt' if(rt!=NULL) reg_free(rt); // free 'rz' if((rz!=NULL) && (rz->dist==MAXDIST || rz->dist<0)) reg_free(rz); // 6th step: set the dirty property for the registers // -- // check 'rx' if(rx!=NULL) rx->dirty=true; // check 'ry' if(ry!=NULL) ry->dirty=true; // check 'rt' if(rt!=NULL) rt->dirty=true; // check 'rz' if(rz!=NULL) rz->dirty=false; // nota: um registo e' dirty apenas quando o seu conteudo e' manipulado na memoria !!!! // (confirmar e corrigir se necessario o 6o passo) // mudar os valores de dirty para oposto: 'false' <-> 'true' // :: -------------------------------- :: THE END :: #ifdef VERBOSE table_print(registers); printf("\n"); #endif return; }