this repo has no description
1/* Copyright (c) Facebook, Inc. and its affiliates. (http://www.facebook.com) */
2#pragma once
3
4#include "handles.h"
5#include "objects.h"
6
7namespace py {
8
9class Thread;
10
11const int kAttributeBucketNumWords = 2;
12const int kAttributeBucketKeyOffset = 0;
13const int kAttributeBucketValueOffset = 1;
14const RawObject kAttributeDictEmptyKey = SmallInt::fromWord(0);
15const RawObject kAttributeDictTombstoneKey = NoneType::object();
16
17bool attributeAt(RawAttributeDict attrs, RawObject name, RawObject* result_out);
18
19bool attributeAtWithHash(RawAttributeDict attrs, RawObject name, word hash,
20 RawObject* result_out);
21
22RawObject attributeAtPut(Thread* thread, const AttributeDict& attrs,
23 const Object& name, const Object& value);
24
25void attributeDictInit(Thread* thread, const AttributeDict& attrs);
26
27RawObject attributeKeys(Thread* thread, const AttributeDict& attrs);
28
29word attributeLen(Thread* thread, const AttributeDict& attrs);
30
31// Prepare `name` to be used as an attribute name: Raise a TypeError if it
32// is not a string; reject some string subclasses. Otherwise return an
33// interned string that can be used with attribute accessors.
34RawObject attributeName(Thread* thread, const Object& name);
35
36RawObject attributeNameNoException(Thread* thread, const Object& name);
37
38bool attributeFindForRemoval(const AttributeDict& attrs, const Object& name,
39 Object* value_cell_out, word* index_out);
40
41void attributeRemove(const AttributeDict& attrs, word index);
42
43// Look-up underlying value-cell to a name.
44bool attributeValueCellAt(RawAttributeDict attrs, RawObject name,
45 RawObject* result_out);
46
47// Look-up underlying value-cell to a name.
48bool attributeValueCellAtWithHash(RawAttributeDict attrs, RawObject name,
49 word hash, RawObject* result_out);
50
51// Look-up or insert a value-cell for a given name.
52RawObject attributeValueCellAtPut(Thread* thread, const AttributeDict& attrs,
53 const Object& name);
54
55RawObject attributeValues(Thread* thread, const AttributeDict& attrs);
56
57word internedStrHash(RawObject name);
58
59inline bool attributeValueCellAtWithHash(RawAttributeDict attrs, RawObject name,
60 word hash, RawObject* result_out) {
61 RawMutableTuple data = MutableTuple::cast(attrs.attributes());
62 word mask = (data.length() - 1) >> 1;
63 for (word bucket = hash & mask, num_probes = 0;;
64 bucket = (bucket + ++num_probes) & mask) {
65 word idx = bucket * kAttributeBucketNumWords;
66 RawObject key = data.at(idx + kAttributeBucketKeyOffset);
67 if (key == name) {
68 *result_out = data.at(idx + kAttributeBucketValueOffset);
69 return true;
70 }
71 if (key == kAttributeDictEmptyKey) {
72 return false;
73 }
74 // Remaining cases are either a key that does not match or tombstone.
75 }
76}
77
78inline RawObject attributeAtPut(Thread* thread, const AttributeDict& attrs,
79 const Object& name, const Object& value) {
80 RawValueCell value_cell =
81 ValueCell::cast(attributeValueCellAtPut(thread, attrs, name));
82 value_cell.setValue(*value);
83 return value_cell;
84}
85
86inline bool attributeAtWithHash(RawAttributeDict attrs, RawObject name,
87 word hash, RawObject* result_out) {
88 RawObject result = NoneType::object();
89 if (!attributeValueCellAtWithHash(attrs, name, hash, &result) ||
90 ValueCell::cast(result).isPlaceholder()) {
91 return false;
92 }
93 *result_out = ValueCell::cast(result).value();
94 return true;
95}
96
97inline bool attributeAt(RawAttributeDict attrs, RawObject name,
98 RawObject* result_out) {
99 word hash = internedStrHash(name);
100 return attributeAtWithHash(attrs, name, hash, result_out);
101}
102
103inline word internedStrHash(RawObject name) {
104 if (name.isImmediateObjectNotSmallInt()) {
105 return SmallStr::cast(name).hash();
106 }
107 word hash = LargeStr::cast(name).header().hashCode();
108 DCHECK(hash != Header::kUninitializedHash,
109 "hash has not been computed (string not interned?)");
110 return hash;
111}
112
113} // namespace py