Technically this can also be done via static code trampolines that are mmap'd as well [1]. That approach has been used on iOS in the past to turn blocks into raw function pointers.
If you have a platform that allows W+X on code (yikes!), you can do [2] as well.
Right, this is how Objective-C's implementation works, except it keeps around one page of trampolines and remaps that around when necessary to be able to "create" more trampolines on the fly, I believe.