//! Lecture (à travers le cache). Cache_Error Cache_Read(struct Cache *pcache, int irfile, void *precord) { if(CheckSync(pcache)) Cache_Sync(pcache); int ibfile = (int)(irfile/pcache->nrecords); struct Cache_Block_Header *cbh = NULL; for(struct Cache_Block_Header *h = pcache->headers; h < (pcache->headers + pcache->nblocks); h++) { if(h->ibfile == ibfile && (h->flags & VALID)) { cbh = h; pcache->instrument.n_hits++; break; } } if(!cbh) { cbh = Strategy_Replace_Block(pcache); if(!cbh) cbh = pcache->headers; if(cbh->flags&MODIF) { fseek(pcache->fp, DADDR(pcache, cbh->ibfile), SEEK_SET); fwrite(cbh->data, pcache->blocksz, 1, pcache->fp); } cbh->ibfile = ibfile; cbh->flags = VALID; fseek(pcache->fp, DADDR(pcache, ibfile), SEEK_SET); fread(cbh->data, pcache->blocksz, 1, pcache->fp); } memcpy(precord, ADDR(pcache, irfile, cbh), pcache->recordsz); pcache->instrument.n_reads++; Strategy_Read(pcache, cbh); return CACHE_OK; }
/*! \brief Écriture physique d'un bloc dans le fichier. * * \ingroup cache_internal * * On écrit le bloc puis on efface le flag de modification. * * \param pcache un pointeur sur le cache * \param un pointeur sur le bloc du cache à écrire * \return un code d'erreur */ static Cache_Error Write_Block(struct Cache *pcache, struct Cache_Block_Header *pbh) { /* On positionne le pointeur d'E/S à l'adresse du bloc dans le fichier */ fseek(pcache->fp, DADDR(pcache, pbh->ibfile), SEEK_SET); /* On écrit les données du bloc */ if (fwrite(pbh->data, 1, pcache->blocksz, pcache->fp) != pcache->blocksz) return CACHE_KO; /* On efface la marque de modification */ pbh->flags &= ~MODIF; return CACHE_OK; }
//! Synchronisation du cache. Cache_Error Cache_Sync(struct Cache *pcache) { for(struct Cache_Block_Header *h = pcache->headers; h < (pcache->headers + pcache->nblocks); h++) { if(h->flags & MODIF) { h->flags &= ~MODIF; fseek(pcache->fp, DADDR(pcache, h->ibfile), SEEK_SET); fwrite(h->data, pcache->blocksz, 1, pcache->fp); } } pcache->instrument.n_syncs++; return CACHE_OK; }
/*! \brief Lecture physique d'un bloc depuis le fichier. * * \ingroup cache_internal * * Si le bloc correspond à des enregistrements existants actuellement sur le * fichier, on écrase juste les données du fichier par celles du bloc. S'il * est dela de la fin de fichier, on cree un bloc de zéros. Dans tous les cas * on valide le bloc. * * \param pcache un pointeur sur le cache * \param un pointeur sur le bloc du cache à écrire * \return un code d'erreur */ static Cache_Error Read_Block(struct Cache *pcache, struct Cache_Block_Header *pbh) { long loff, leof; /* On cherche la longueur courante du fichier */ if (fseek(pcache->fp, 0, SEEK_END) < 0) return CACHE_KO; leof = ftell(pcache->fp); /* Si l'on est au dela de la fin de fichier, on cree un bloc de zeros. Sinon, on lit le bloc depuis le fichier */ loff = DADDR(pcache, pbh->ibfile); /* Adresse en octets du bloc dans le fichier */ if (loff >= leof) { /* Le bloc cherché est au dela de la fin de fichier. */ /* On n'effectue aucune entrée-sortie, se contentant de mettre le bloc à 0. */ memset(pbh->data, '\0', pcache->blocksz); } else { /* Le bloc existe dans le fichier */ /* On y va ! */ if (fseek(pcache->fp, loff, SEEK_SET) != 0) return CACHE_KO; /* Et on le lit */ if (fread(pbh->data, 1, pcache->blocksz, pcache->fp) != pcache->blocksz) return CACHE_KO; } /* Le bloc est maintenant valide */ pbh->flags |= VALID; return CACHE_OK; }
static void _disassemble_class(const Ref<GDScript> &p_class, const Vector<String> &p_code) { const Map<StringName, GDScriptFunction *> &mf = p_class->debug_get_member_functions(); for (const Map<StringName, GDScriptFunction *>::Element *E = mf.front(); E; E = E->next()) { const GDScriptFunction &func = *E->get(); const int *code = func.get_code(); int codelen = func.get_code_size(); String defargs; if (func.get_default_argument_count()) { defargs = "defarg at: "; for (int i = 0; i < func.get_default_argument_count(); i++) { if (i > 0) defargs += ","; defargs += itos(func.get_default_argument_addr(i)); } defargs += " "; } print_line("== function " + String(func.get_name()) + "() :: stack size: " + itos(func.get_max_stack_size()) + " " + defargs + "=="); #define DADDR(m_ip) (_disassemble_addr(p_class, func, code[ip + m_ip])) for (int ip = 0; ip < codelen;) { int incr = 0; String txt = itos(ip) + " "; switch (code[ip]) { case GDScriptFunction::OPCODE_OPERATOR: { int op = code[ip + 1]; txt += "op "; String opname = Variant::get_operator_name(Variant::Operator(op)); txt += DADDR(4); txt += " = "; txt += DADDR(2); txt += " " + opname + " "; txt += DADDR(3); incr += 5; } break; case GDScriptFunction::OPCODE_SET: { txt += "set "; txt += DADDR(1); txt += "["; txt += DADDR(2); txt += "]="; txt += DADDR(3); incr += 4; } break; case GDScriptFunction::OPCODE_GET: { txt += " get "; txt += DADDR(3); txt += "="; txt += DADDR(1); txt += "["; txt += DADDR(2); txt += "]"; incr += 4; } break; case GDScriptFunction::OPCODE_SET_NAMED: { txt += " set_named "; txt += DADDR(1); txt += "[\""; txt += func.get_global_name(code[ip + 2]); txt += "\"]="; txt += DADDR(3); incr += 4; } break; case GDScriptFunction::OPCODE_GET_NAMED: { txt += " get_named "; txt += DADDR(3); txt += "="; txt += DADDR(1); txt += "[\""; txt += func.get_global_name(code[ip + 2]); txt += "\"]"; incr += 4; } break; case GDScriptFunction::OPCODE_SET_MEMBER: { txt += " set_member "; txt += "[\""; txt += func.get_global_name(code[ip + 1]); txt += "\"]="; txt += DADDR(2); incr += 3; } break; case GDScriptFunction::OPCODE_GET_MEMBER: { txt += " get_member "; txt += DADDR(2); txt += "="; txt += "[\""; txt += func.get_global_name(code[ip + 1]); txt += "\"]"; incr += 3; } break; case GDScriptFunction::OPCODE_ASSIGN: { txt += " assign "; txt += DADDR(1); txt += "="; txt += DADDR(2); incr += 3; } break; case GDScriptFunction::OPCODE_ASSIGN_TRUE: { txt += " assign "; txt += DADDR(1); txt += "= true"; incr += 2; } break; case GDScriptFunction::OPCODE_ASSIGN_FALSE: { txt += " assign "; txt += DADDR(1); txt += "= false"; incr += 2; } break; case GDScriptFunction::OPCODE_CONSTRUCT: { Variant::Type t = Variant::Type(code[ip + 1]); int argc = code[ip + 2]; txt += " construct "; txt += DADDR(3 + argc); txt += " = "; txt += Variant::get_type_name(t) + "("; for (int i = 0; i < argc; i++) { if (i > 0) txt += ", "; txt += DADDR(i + 3); } txt += ")"; incr = 4 + argc; } break; case GDScriptFunction::OPCODE_CONSTRUCT_ARRAY: { int argc = code[ip + 1]; txt += " make_array "; txt += DADDR(2 + argc); txt += " = [ "; for (int i = 0; i < argc; i++) { if (i > 0) txt += ", "; txt += DADDR(2 + i); } txt += "]"; incr += 3 + argc; } break; case GDScriptFunction::OPCODE_CONSTRUCT_DICTIONARY: { int argc = code[ip + 1]; txt += " make_dict "; txt += DADDR(2 + argc * 2); txt += " = { "; for (int i = 0; i < argc; i++) { if (i > 0) txt += ", "; txt += DADDR(2 + i * 2 + 0); txt += ":"; txt += DADDR(2 + i * 2 + 1); } txt += "}"; incr += 3 + argc * 2; } break; case GDScriptFunction::OPCODE_CALL: case GDScriptFunction::OPCODE_CALL_RETURN: { bool ret = code[ip] == GDScriptFunction::OPCODE_CALL_RETURN; if (ret) txt += " call-ret "; else txt += " call "; int argc = code[ip + 1]; if (ret) { txt += DADDR(4 + argc) + "="; } txt += DADDR(2) + "."; txt += String(func.get_global_name(code[ip + 3])); txt += "("; for (int i = 0; i < argc; i++) { if (i > 0) txt += ", "; txt += DADDR(4 + i); } txt += ")"; incr = 5 + argc; } break; case GDScriptFunction::OPCODE_CALL_BUILT_IN: { txt += " call-built-in "; int argc = code[ip + 2]; txt += DADDR(3 + argc) + "="; txt += GDScriptFunctions::get_func_name(GDScriptFunctions::Function(code[ip + 1])); txt += "("; for (int i = 0; i < argc; i++) { if (i > 0) txt += ", "; txt += DADDR(3 + i); } txt += ")"; incr = 4 + argc; } break; case GDScriptFunction::OPCODE_CALL_SELF_BASE: { txt += " call-self-base "; int argc = code[ip + 2]; txt += DADDR(3 + argc) + "="; txt += func.get_global_name(code[ip + 1]); txt += "("; for (int i = 0; i < argc; i++) { if (i > 0) txt += ", "; txt += DADDR(3 + i); } txt += ")"; incr = 4 + argc; } break; case GDScriptFunction::OPCODE_YIELD: { txt += " yield "; incr = 1; } break; case GDScriptFunction::OPCODE_YIELD_SIGNAL: { txt += " yield_signal "; txt += DADDR(1); txt += ","; txt += DADDR(2); incr = 3; } break; case GDScriptFunction::OPCODE_YIELD_RESUME: { txt += " yield resume: "; txt += DADDR(1); incr = 2; } break; case GDScriptFunction::OPCODE_JUMP: { txt += " jump "; txt += itos(code[ip + 1]); incr = 2; } break; case GDScriptFunction::OPCODE_JUMP_IF: { txt += " jump-if "; txt += DADDR(1); txt += " to "; txt += itos(code[ip + 2]); incr = 3; } break; case GDScriptFunction::OPCODE_JUMP_IF_NOT: { txt += " jump-if-not "; txt += DADDR(1); txt += " to "; txt += itos(code[ip + 2]); incr = 3; } break; case GDScriptFunction::OPCODE_JUMP_TO_DEF_ARGUMENT: { txt += " jump-to-default-argument "; incr = 1; } break; case GDScriptFunction::OPCODE_RETURN: { txt += " return "; txt += DADDR(1); incr = 2; } break; case GDScriptFunction::OPCODE_ITERATE_BEGIN: { txt += " for-init " + DADDR(4) + " in " + DADDR(2) + " counter " + DADDR(1) + " end " + itos(code[ip + 3]); incr += 5; } break; case GDScriptFunction::OPCODE_ITERATE: { txt += " for-loop " + DADDR(4) + " in " + DADDR(2) + " counter " + DADDR(1) + " end " + itos(code[ip + 3]); incr += 5; } break; case GDScriptFunction::OPCODE_LINE: { int line = code[ip + 1] - 1; if (line >= 0 && line < p_code.size()) txt = "\n" + itos(line + 1) + ": " + p_code[line] + "\n"; else txt = ""; incr += 2; } break; case GDScriptFunction::OPCODE_END: { txt += " end"; incr += 1; } break; case GDScriptFunction::OPCODE_ASSERT: { txt += " assert "; txt += DADDR(1); incr += 2; } break; } if (incr == 0) { ERR_EXPLAIN("unhandled opcode: " + itos(code[ip])); ERR_BREAK(incr == 0); } ip += incr; if (txt != "") print_line(txt); } } }