In meinem On-Again-Off-Again-Compiler-Projekt habe ich Closures als reservierten Speicher mit einem ausführbaren Präfix implementiert. Also ist eine Schließung wie folgt zugeteilt:
%Vor% c
ist ein Zeiger auf einen Block des zugewiesenen Speichers, der wie folgt aussieht:
closure_call ist eine Hilfsfunktion, die auf die zuletzt im Stapel platzierte Adresse schaut und diese verwendet, um die Schließungsdaten und den Codezeiger zu finden. Boehm GC wird für die allgemeine Speicherverwaltung verwendet, und wenn die Schließung nicht mehr referenziert wird, kann sie vom GC deallokiert werden.
Jedenfalls muss dieser zugewiesene Speicher als ausführbar markiert werden; Tatsächlich werden die gesamten Seiten, die es umfasst, markiert. Wenn Closures erstellt und freigegeben werden, wird mehr und mehr Heapspeicher im Prozess ausführbar sein.
Aus Gründen der defensiven Programmierung würde ich es vorziehen, die Menge des ausführbaren Heaps zu minimieren. Mein Plan ist, zu versuchen, alle Schließungen auf derselben Seite (n) zusammen zu halten und ausführbare Seiten nach Bedarf zuzuordnen und freizugeben; d.h. um einen benutzerdefinierten Zuordner für Schließungen zu implementieren. (Dies ist einfacher, wenn alle Closures dieselbe Größe haben. Der erste Schritt besteht also darin, die Umgebungsdaten in eine separate nicht ausführbare Zuweisung zu verschieben, die normal verwaltet werden kann. Dies macht auch defensive Programmierung sinnvoll.)
Aber das verbleibende Problem ist GC. Böhm macht das schon! Ich möchte Boehm irgendwie über meine Sonderzuteilungen berichten und Boehm bitten, mir zu sagen, wann es möglich ist, sie zu bestätigen, aber es mir zu überlassen, sie auszuteilen.
Also meine Frage ist, gibt es Haken in Böhm, die für benutzerdefinierte Zuordnungen wie diese bieten?
Vielleicht können Sie mit einem Finalizer tun, was Sie wollen - Boehm GC würde die Zuordnung immer noch aufheben, aber Sie hätten vorher die Möglichkeit, die Schließung mit Breakpoint-Ops (0xCC auf x86) zu memsen und die Seite nach Möglichkeit als nicht ausführbar zu markieren.
Allerdings haben Finalizer einen hohen Preis, sollten also nicht leicht verwendet werden. Boehm GC basiert auf einem Mark-Sweep-Algorithmus, der zuerst alle Chunks identifiziert, die nicht freigegeben werden sollen (mark.c), und dann alles andere auf einmal freigibt (reclaim.c). In Ihrem Fall ist es sinnvoll, den Wiederherstellungsprozess so zu modifizieren, dass auch der gesamte freie Speicherplatz in der ausführbaren Region mit Breakpoint-Ops gefüllt wird, und Seiten, die nicht ausführbar sind, als vollständig leer markiert werden. Dies vermeidet Finalisten, auf Kosten der Verzweigung der Bibliothek (Ich konnte keinen Erweiterungsmechanismus dafür finden).
Beachten Sie schließlich, dass die Ausführungsprävention eine Tiefenverteidigungsmaßnahme ist und nicht Ihr einziger Sicherheitsschutz sein sollte. Die renditeorientierte Programmierung kann verwendet werden, um beliebigen Code auszuführen, der nicht modifizierbare ausführbare Regionen verwendet.
Tags und Links garbage-collection compiler-construction closures boehm-gc