this repo has no description
at trunk 110 lines 4.2 kB view raw
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