Split Capabilities: Making Capabilities Scale

Mark S. Miller markm@caplet.com
Sun, 23 Jul 2000 17:22:01 -0700

At 05:22 PM 7/20/00 , Karp, Alan wrote:
> > In E I'm not sure what "objects are cheaper than 
> > capabilities" would mean.  
> > Objects and capabilities are 1-for-1.
> > 
>I thought that capabilities are handles for objects and each represents a
>facet of an object.  An interposer is a running piece of code; a capability
>is the handle used to access the interposer and the access rights of the

I think we have the same picture in mind, but are using slightly different 
labels.  I believe your usage may also correspond to Jonathan's in 
describing EROS.  ("... capabilities conveying distinct access rights to the 
same object."  --p64 of 14Feb99 Draft of EROS Thesis)  I used to use the 
same labels I think you and Jonathan are using, but I found there were some 
fine points I couldn't make.  

We agree on "facet", and that the same object-state can be seen through 
multiple facets.  However, what's an "object"?  If we take seriously the 
conventional slogan that "An object is a combination of state and behavior", 
then the object-state shared by a set of facets is not an object, it is only 
state.  (It may in fact be an object at a lower implementational level of 
abstraction, but that would be another matter.

By this definition, only the facets are objects, since the facet represents 
the pairing of state (heap-allocated object state) and behavior (vtable-like 
method dispatch).  Only in what Jonathan calls a "thinning" pattern, can the 
behavior be seen in terms of "access rights", because only in this pattern 
is one vtable exactly a subset of another more powerful vtable.  This is a 
common faceting pattern, but not the only one.  For example:

     define incDecPair new(x) :any {
         [define incr do { x += 1 },
          define decr do { x -= 1 },
          define getX() :any { x }]

returns three facets on shared state.  The first two both respond to the 
"do/0" message ("do" with 0 arguments).  But they each respond to it with 
different behaviors.  The first represents only the authority to increment 
x, and the second only the authority to decrement x.  To someone who holds 
one of these facets, they can exercise the authority they've got, but they 
can't tell which flavor of authority that is.

Jonathan, besides our terminological differences, I think there may also be 
a semantic difference between our descriptions.  You speak of a capability 
as combining state/object (what I call state & you call object) with a *set* 
of access-rights rather than a *mapping* from order codes to access-rights.  
(An EROS order-code corresponds to an E message name.)  I believe your 
"access right" corresponds to my "method" -- code defined by the 
state/object definer that is given access to this state when it executes.  
The "right", of course, would be the right to invoke this code on this state.

Depending on what layer of abstraction you're at, you can either speak in 
terms of overall behaviors, where the behavior includes any dispatching on 
the order-code, or you can fold this dispatching into your semantics and 
speak of access-rights or methods. In the former, a capability combines 
state with behavior.  In the latter, a capability combines state with a 
mapping from order-codes to access-rights/methods.  However, you can only 
describe a capability as combining state and a *set* of access rights at the 
price of not being able to describe the opaque polymorphism displayed by the 
incDecPair above -- an example as valid for EROS as it is for E.

>My statement refers to the fact that the interposer need be nothing but two
>lines of code to be a message forwarder, while a capability, if remote,
>requires some cryptography.

Gotcha.  Indeed, a remote capability is more expensive than a typical E 
object.  (But not by a lot, and most capabilities are local anyway.)