An interesting alternative to the explicit dirty=true
approach, although it is probably overkill for most situations and often not applicable, would be to use guard pages. Set the memory page as read-only (e.g. with VirtualProtect() on Windows) and catch the signal/exception when the program tries to write to the page. Make a record that the page has been modified, then change the protection flags of the page to writable and resume execution.
This is the technique usually employed by operating systems to determine whether a page needs to be written to the swap file before it is evicted from RAM.