Link's members are laid out like so:
nsLinkState mLinkState;
mutable nsCOMPtr<nsIURI> mCachedURI;
bool mRegistered;
Element * const mElement;
// Strong reference to History. The link has to unregister before History
// can disappear.
nsCOMPtr<IHistory> mHistory;
Besides this introducing 11 (!) bytes of padding on a 64-bit system, there's no need for mLinkState to be a full integer. nsLinkState only has a handful of values. mLinkState should be a PRUInt16 or similar; mRegistered could then be packed with it, which would save a word on 32-bit and 64-bit systems.

(In reply to Boris Zbarsky (:bz) from comment #2)
> r=me. I wish compilers would get with the program and just let us declare
> the sizes of enums!
If you're holding your breath to inject some sanity into any C++ compiler soon, be warned that you might need to hold it for way longer than recommended by the medical community. :-)

Nice patch! I had to use PRInt16 instead of a sized enum in bug 712865 as well.
What were the before and after sizes (on both 32-bit and 64-bit)? And roughly how many Link objects do we have live at a time?

(In reply to Nicholas Nethercote [:njn] from comment #6)
> Nice patch! I had to use PRInt16 instead of a sized enum in bug 712865 as
> well.
>
> What were the before and after sizes (on both 32-bit and 64-bit)? And
> roughly how many Link objects do we have live at a time?
This should save 4 bytes on 32-bit and 8 bytes on 64-bit per Link object.