@@ -237,22 +237,17 @@ for the component caller or callee, resp.
237
237
The meaning of the ` opts ` and ` inst ` fields are described with their associated
238
238
types below.
239
239
240
- The ` lenders ` and ` borrow_count ` fields are used by the following 4 methods of
241
- ` CallContext ` . These methods are called at the appropriate points in the
242
- lifecycle of a call (below) and maintain the bookkeeping to dynamically ensure
243
- that ` own ` handles are not dropped while they have been ` borrow ` ed and that all
244
- ` borrow ` handles created for a call are dropped before the end of the call.
240
+ The ` lenders ` and ` borrow_count ` fields are used by the following helper
241
+ methods of ` CallContext ` plus the ` {lift,lower}_{own,borrow} ` operations. These
242
+ fields are updated at the appropriate points in the lifecycle of a call (below)
243
+ and maintain the bookkeeping to dynamically ensure that ` own ` handles are not
244
+ dropped while they have been ` borrow ` ed and that all ` borrow ` handles created
245
+ for a call are dropped before the end of the call.
245
246
``` python
246
- def lift_borrow_from (self , lending_handle ):
247
- if lending_handle.own:
248
- lending_handle.lend_count += 1
249
- self .lenders.append(lending_handle)
250
-
251
- def add_borrow_to_table (self ):
252
- self .borrow_count += 1
253
-
254
- def remove_borrow_from_table (self ):
255
- self .borrow_count -= 1
247
+ def track_owning_lend (self , lending_handle ):
248
+ assert (lending_handle.own)
249
+ lending_handle.lend_count += 1
250
+ self .lenders.append(lending_handle)
256
251
257
252
def exit_call (self ):
258
253
trap_if(self .borrow_count != 0 )
@@ -380,23 +375,14 @@ free list in the free elements of `array`.
380
375
else :
381
376
i = len (self .array)
382
377
self .array.append(h)
383
- if h.scope is not None :
384
- h.scope.add_borrow_to_table()
385
378
return i
386
379
387
380
def remove (self , rt , i ):
388
381
h = self .get(i)
389
- trap_if(h.lend_count != 0 )
390
382
self .array[i] = None
391
383
self .free.append(i)
392
- if h.scope is not None :
393
- h.scope.remove_borrow_from_table()
394
384
return h
395
385
```
396
- In addition to handling allocation of the handle elements, the ` add ` and
397
- ` remove ` methods make balanced calls to the ` add_borrow_to_table ` and
398
- ` remove_borrow_from_table ` methods of ` CallContext ` which participate in the
399
- enforcement of the dynamic borrow rules.
400
386
401
387
Finally, we can define ` HandleTables ` (plural) as simply a wrapper around
402
388
a mutable mapping from ` ResourceType ` to ` HandleTable ` :
@@ -637,10 +623,13 @@ def unpack_flags_from_int(i, labels):
637
623
638
624
` own ` handles are lifted by removing the handle from the current component
639
625
instance's handle table, so that ownership is * transferred* to the lowering
640
- component.
626
+ component. The lifting operation fails if unique ownership of the handle isn't
627
+ possible, for example if the index was actually a ` borrow ` or if the ` own `
628
+ handle is currently being lent out as borrows.
641
629
``` python
642
630
def lift_own (cx , i , t ):
643
631
h = cx.inst.handles.remove(t.rt, i)
632
+ trap_if(h.lend_count != 0 )
644
633
trap_if(not h.own)
645
634
return h.rep
646
635
```
@@ -657,10 +646,11 @@ component instance's handle table:
657
646
``` python
658
647
def lift_borrow (cx , i , t ):
659
648
h = cx.inst.handles.get(t.rt, i)
660
- cx.lift_borrow_from(h)
649
+ if h.own:
650
+ cx.track_owning_lend(h)
661
651
return h.rep
662
652
```
663
- The ` lift_borrow_from ` call to ` CallContext ` participates in the enforcement of
653
+ The ` track_owning_lend ` call to ` CallContext ` participates in the enforcement of
664
654
the dynamic borrow rules.
665
655
666
656
@@ -1013,6 +1003,7 @@ def lower_borrow(cx, rep, t):
1013
1003
if cx.inst is t.rt.impl:
1014
1004
return rep
1015
1005
h = HandleElem(rep, own = False , scope = cx)
1006
+ cx.borrow_count += 1
1016
1007
return cx.inst.handles.add(t.rt, h)
1017
1008
```
1018
1009
The special case in ` lower_borrow ` is an optimization, recognizing that, when
@@ -1610,9 +1601,15 @@ the resource's destructor.
1610
1601
def canon_resource_drop (inst , rt , i ):
1611
1602
h = inst.handles.remove(rt, i)
1612
1603
if h.own:
1604
+ assert (h.scope is None )
1605
+ trap_if(h.lend_count != 0 )
1613
1606
trap_if(inst is not rt.impl and not rt.impl.may_enter)
1614
1607
if rt.dtor:
1615
1608
rt.dtor(h.rep)
1609
+ else :
1610
+ assert (h.scope is not None )
1611
+ assert (h.scope.borrow_count > 0 )
1612
+ h.scope.borrow_count -= 1
1616
1613
```
1617
1614
The ` may_enter ` guard ensures the non-reentrance [ component invariant] , since
1618
1615
a destructor call is analogous to a call to an export.
0 commit comments