this repo has no description
1// Copyright (c) Facebook, Inc. and its affiliates. (http://www.facebook.com)
2#include "ref-builtins.h"
3
4#include "builtins.h"
5#include "frame.h"
6#include "globals.h"
7#include "objects.h"
8#include "runtime.h"
9#include "thread.h"
10#include "type-builtins.h"
11
12namespace py {
13
14static const BuiltinAttribute kRefAttributes[] = {
15 {ID(_ref__referent), RawWeakRef::kReferentOffset, AttributeFlags::kHidden},
16 {ID(_ref__callback), RawWeakRef::kCallbackOffset, AttributeFlags::kHidden},
17 {ID(_ref__link), RawWeakRef::kLinkOffset, AttributeFlags::kHidden},
18 {ID(_ref__hash), RawWeakRef::kHashOffset, AttributeFlags::kHidden},
19};
20
21static const BuiltinAttribute kWeakLinkAttributes[] = {
22 {ID(__weaklink__referent), RawWeakLink::kReferentOffset,
23 AttributeFlags::kHidden},
24 {ID(__weaklink__callback), RawWeakLink::kCallbackOffset,
25 AttributeFlags::kHidden},
26 {ID(__weaklink__link), RawWeakLink::kLinkOffset, AttributeFlags::kHidden},
27 {ID(__weaklink__hash), RawWeakLink::kHashOffset, AttributeFlags::kHidden},
28 {ID(__weaklink__next), RawWeakLink::kNextOffset, AttributeFlags::kHidden},
29 {ID(__weaklink__prev), RawWeakLink::kPrevOffset, AttributeFlags::kHidden},
30};
31
32static const BuiltinAttribute kWeakCallableProxyAttributes[] = {
33 {ID(ref_obj), RawWeakCallableProxy::kReferentOffset},
34};
35
36static const BuiltinAttribute kWeakProxyAttributes[] = {
37 {ID(ref_obj), RawWeakProxy::kReferentOffset},
38};
39
40void initializeRefTypes(Thread* thread) {
41 addBuiltinType(thread, ID(weakref), LayoutId::kWeakRef,
42 /*superclass_id=*/LayoutId::kObject, kRefAttributes,
43 WeakRef::kSize, /*basetype=*/true);
44
45 addBuiltinType(thread, ID(weakcallableproxy), LayoutId::kWeakCallableProxy,
46 /*superclass_id=*/LayoutId::kObject,
47 kWeakCallableProxyAttributes, WeakCallableProxy::kSize,
48 /*basetype=*/false);
49
50 addBuiltinType(thread, ID(weakproxy), LayoutId::kWeakProxy,
51 /*superclass_id=*/LayoutId::kObject, kWeakProxyAttributes,
52 WeakProxy::kSize, /*basetype=*/false);
53
54 addBuiltinType(thread, ID(_weaklink), LayoutId::kWeakLink,
55 /*superclass_id=*/LayoutId::kObject, kWeakLinkAttributes,
56 WeakLink::kSize, /*basetype=*/false);
57}
58
59RawObject METH(weakref, __call__)(Thread* thread, Arguments args) {
60 HandleScope scope(thread);
61 Object self(&scope, args.get(0));
62 if (!thread->runtime()->isInstanceOfWeakRef(*self)) {
63 return thread->raiseRequiresType(self, ID(weakref));
64 }
65 WeakRef ref(&scope, weakRefUnderlying(*self));
66 return ref.referent();
67}
68
69RawObject METH(weakref, __new__)(Thread* thread, Arguments args) {
70 HandleScope scope(thread);
71 Object type_obj(&scope, args.get(0));
72 Runtime* runtime = thread->runtime();
73 if (!runtime->isInstanceOfType(*type_obj)) {
74 return thread->raiseWithFmt(LayoutId::kTypeError, "not a type object");
75 }
76 Type type(&scope, *type_obj);
77 if (type.builtinBase() != LayoutId::kWeakRef) {
78 return thread->raiseWithFmt(LayoutId::kTypeError,
79 "not a subtype of weakref");
80 }
81 // Note that CPython only allows reference to types with `tp_weaklistoffset`
82 // set. Since we don't simulate `tp_weaklistoffset` yet we allow any heap
83 // object.
84 Object referent(&scope, args.get(1));
85 if (!referent.isHeapObject()) {
86 return thread->raiseWithFmt(LayoutId::kTypeError,
87 "cannot create weak reference to '%T' object",
88 &referent);
89 }
90 Object callback(&scope, args.get(2));
91 WeakRef result(&scope, runtime->newWeakRef(thread, referent));
92 if (type.isBuiltin()) {
93 if (callback.isNoneType()) {
94 result.setCallback(*callback);
95 return *result;
96 }
97 result.setCallback(runtime->newBoundMethod(callback, result));
98 return *result;
99 }
100 Layout layout(&scope, type.instanceLayout());
101 UserWeakRefBase instance(&scope, runtime->newInstance(layout));
102 instance.setValue(*result);
103 if (callback.isNoneType()) {
104 result.setCallback(*callback);
105 return *instance;
106 }
107 result.setCallback(runtime->newBoundMethod(callback, instance));
108 return *instance;
109}
110} // namespace py