Procesory take obsahují instrukce k výprázdnění techto cache. Často jsou povinné, například, když se x86 mění režim činnosti procesoru (třeba při vstupu do protect mode). Takže automodifikující se program ano, ale po každé modifikaci je nutné vyprázdnit cache.
Čímž ovšem ztratíme veškeré výhody, které automodifikace přinesla. Vyprázdnění cache ve výsledku stojí více, než ušetřených pár desítek nanosekund.
Takže na moderních procesorech již automodifikaci nelze použít jako prostředek pro urychlení běhu programu. Nanejvýš nako systémový nástroj (např. pro relokaci).
Takové geniální věci jako proměnná, která je zároveň argumentem instrukce, operátor, který je instrukčním kódem, nebo vyskočení ze smyčky přepsáním instrukce jump na konci, jsou dnes již minulostí.
Lispové kompilátory s citlivou automodifikací (tedy nikoli pár instrukcí kolem aktuální hodnoty PC :-)) nemají problémy na žádné platformě (jinak by vůbec nefungovaly :-)), stejně jako nemají problém s ad-hoc generováním kódu (některé implementace CLOSu). Jak přesně by to mohlo dnes sloužit jako prostředek k urychlení běhu programu? Myslím, že by s tím v dnešní době interferovalo víc věcí, nejen cache, ale třeba i branch prediction.
Tento problém se objevil už s příchodem fronty instrukcí (vlastně taková malá neinteligentní a jednosměrná cache :-). Nevím, jak přesně to bylo u platformy 68k, ale na x86 se tak dalo testovat, jestli je program krokovaný (v debuggeru) či ne - snad to dokonce používal nějaký vir pro detekci toho, jestli je na něj puštěnej heuristický detektor.
Opravdu to par viru na konci jejich zlate DOSovske ery pouzivalo. Dokonce jsem pri krokovani takoveho kodu kdysi ztratil relativne spoustu casu nez jsem si ten trik uvedomil. Jako myslenka to v dane dobe a v dane "aplikaci" bylo genialni :-). Rad bych poznal cloveka, ktereho to napadlo jako prvni. Snad to byl nejaky Bulhar - ti byvali v tomto smeru velice plodni.
Existuji dokonce andi-debuggovaci opatreni v programech, ktera toho dokonce vyuzivaji - kod se modifikuje v okamziku, kdy uz je nacteny v instrukcni pipeline. Pokud se zmena projevi, program usoudi, ze bezi v debuggeru.
Na x86 (a asi i x86-64) jsou sebemodifikující-se programy dovolené. 8086 až 80486 mělo několikabytovou frontu instrukcí a synchronizaci s tou frontou neřešilo --- programátor musel udělat JMP, poté, co si modifikoval kód. Pentium a vyšší do své pipeliny umí nacpat i instrukce za tím JMP, takže bylo potřeba vyvinout mechanismus, jak umožnit starým sebemodifikujícím-se programům, které vyprazdňují frontu pomocí JMP, fungovat. Takže všechny procesory od Pentia výš mají složitý mechanismus, který kontroluje, zda se nemodifikují nějaké rozpracované instrukce, a pokud ano, tak se celá pipelina vyprázdní (na Pentium 4 se vyprazdňuje i celá trace cache).
Sebemodifikující kód používá např. Quake, pokud se to modifikuje málo často (např. se modifikují konstanty v kódu po změně aspect ratio, po nahrátí mapy, při novém snímku), tak to vyprazdňování pipeliny ani nezpomaluje.