Drop the adj_free field from vm_map_entry_t. Refine the max_free field so that p->max_free is the size of the largest gap with one endpoint in the subtree rooted at p. Change vm_map_findspace so that tree searches do not terminate at an interior node, first, the address-based splay is restricted to tree nodes with large-enough max_free value, to avoid searching for the right starting point in a subtree where all the gaps are too small. Second, when the address search leads to a tree search for the first large-enough gap, but only at a null pointerthat gap is the subject of a splay-search that brings the gap to the top of the tree, and then the address is set to the end value of the vm_map_entry on the left side of the gap that the null pointer representsso that an immediate insertion will take constant time.
This changes findspace so that left and right pointers are followed to the bottom of the treeBreak up the splay code into separate components, rather than to a first-fitting interior nodeone for searching and breaking up the tree and another for reassembling it. However, all the additional vm_map_entries examined on the way to the bottom of tree are ones that will be examined, and modified, when a new map entry is ultimately inserted in the gapUse these components, so there should be no negative impact from extra data accesses.
Break up theand not splay code into separate componentsitself, one for searching and brealinking up the tree and another for reassembling itunlinking. Use these components, and not splay itselfDrop the after-where parameter to link, for linking and unlinkingas it is computed as a side-effect of the splay search.