The much-maligned 286 MMU was object based: segments were referred to by handle and had a byte-granular length, so out-of-bounds accesses were impossible.
I once saw a Smalltalk which used the 286 MMU like this. Each Smalltalk object had its own segment descriptor, effectively exploiting the MMU as a fast and cheap way to implement the object pointer table. The Smalltalk garbage collector could move things around behind the scenes and everything still worked, there being no pointers to update.
Of course, with segment sizes limited to 64kB and a limit of (I think?) 2^13 different segments it wouldn't scale to modern machines, but it was still pretty nifty for a 16-bit system. It's a shame it never got used to its full potential.
I once saw a Smalltalk which used the 286 MMU like this. Each Smalltalk object had its own segment descriptor, effectively exploiting the MMU as a fast and cheap way to implement the object pointer table. The Smalltalk garbage collector could move things around behind the scenes and everything still worked, there being no pointers to update.
Of course, with segment sizes limited to 64kB and a limit of (I think?) 2^13 different segments it wouldn't scale to modern machines, but it was still pretty nifty for a 16-bit system. It's a shame it never got used to its full potential.