Welcome to mirror list, hosted at ThFree Co, Russian Federation.

finalization-registry.tq « builtins « src « v8 « deps - github.com/nodejs/node.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
blob: 143486c73768f19f5ee1406446e33d03acfe8a20 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
// Copyright 2020 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

namespace runtime {
extern runtime
ShrinkFinalizationRegistryUnregisterTokenMap(
    Context, JSFinalizationRegistry): void;
}

namespace weakref {
extern transitioning macro
RemoveFinalizationRegistryCellFromUnregisterTokenMap(
    JSFinalizationRegistry, WeakCell): void;

macro SplitOffTail(weakCell: WeakCell): WeakCell|Undefined {
  const weakCellTail = weakCell.next;
  weakCell.next = Undefined;
  typeswitch (weakCellTail) {
    case (Undefined): {
    }
    case (tailIsNowAHead: WeakCell): {
      assert(tailIsNowAHead.prev == weakCell);
      tailIsNowAHead.prev = Undefined;
    }
  }
  return weakCellTail;
}

transitioning macro
PopClearedCell(finalizationRegistry: JSFinalizationRegistry): WeakCell|
    Undefined {
  typeswitch (finalizationRegistry.cleared_cells) {
    case (Undefined): {
      return Undefined;
    }
    case (weakCell: WeakCell): {
      assert(weakCell.prev == Undefined);
      finalizationRegistry.cleared_cells = SplitOffTail(weakCell);

      // If the WeakCell has an unregister token, remove the cell from the
      // unregister token linked lists and and the unregister token from
      // key_map. This doesn't shrink key_map, which is done manually after
      // the cleanup loop to avoid a runtime call.
      if (weakCell.unregister_token != Undefined) {
        RemoveFinalizationRegistryCellFromUnregisterTokenMap(
            finalizationRegistry, weakCell);
      }

      return weakCell;
    }
  }
}

transitioning macro
FinalizationRegistryCleanupLoop(implicit context: Context)(
    finalizationRegistry: JSFinalizationRegistry, callback: Callable) {
  while (true) {
    const weakCellHead = PopClearedCell(finalizationRegistry);
    typeswitch (weakCellHead) {
      case (Undefined): {
        break;
      }
      case (weakCell: WeakCell): {
        try {
          Call(context, callback, Undefined, weakCell.holdings);
        } catch (e) {
          runtime::ShrinkFinalizationRegistryUnregisterTokenMap(
              context, finalizationRegistry);
          ReThrow(context, e);
        }
      }
    }
  }

  runtime::ShrinkFinalizationRegistryUnregisterTokenMap(
      context, finalizationRegistry);
}

transitioning javascript builtin
FinalizationRegistryPrototypeCleanupSome(
    js-implicit context: NativeContext, receiver: JSAny)(...arguments): JSAny {
  // 1. Let finalizationRegistry be the this value.
  //
  // 2. Perform ? RequireInternalSlot(finalizationRegistry, [[Cells]]).
  const methodName: constexpr string =
      'FinalizationRegistry.prototype.cleanupSome';
  const finalizationRegistry =
      Cast<JSFinalizationRegistry>(receiver) otherwise ThrowTypeError(
          MessageTemplate::kIncompatibleMethodReceiver, methodName, receiver);

  let callback: Callable;
  if (arguments[0] != Undefined) {
    // 4. If callback is not undefined and IsCallable(callback) is
    //    false, throw a TypeError exception.
    callback = Cast<Callable>(arguments[0]) otherwise ThrowTypeError(
        MessageTemplate::kWeakRefsCleanupMustBeCallable, arguments[0]);
  } else {
    callback = finalizationRegistry.cleanup;
  }

  FinalizationRegistryCleanupLoop(finalizationRegistry, callback);
  return Undefined;
}
}