Currently objects are associated with a package_id. In OpenACS 5.2 acs_objects has a package_id column. From this it is probably possible to call a package specific procedure and pass in the package_id and object_id to get the url for any object. The PostgreSQL compatible "search" package uses a service contract for this.
To determine where in the site-map an object is located, usually the site_node where a package is mounted is used to calculate most of the URL. This information is cached in an NSV array.
This makes it reasobly inexpensive to calculate the URLs for a list of search results. We only need to calculate the URLs for results that are actually displayed. Most users only look at the first page or two of results.