|
55 | 55 | import com.oracle.graal.python.builtins.objects.dict.DictNodes;
|
56 | 56 | import com.oracle.graal.python.builtins.objects.dict.PDict;
|
57 | 57 | import com.oracle.graal.python.builtins.objects.dict.PDictView;
|
| 58 | +import com.oracle.graal.python.builtins.objects.set.PBaseSet; |
58 | 59 | import com.oracle.graal.python.lib.IteratorExhausted;
|
59 | 60 | import com.oracle.graal.python.lib.PyIterNextNode;
|
60 | 61 | import com.oracle.graal.python.lib.PyObjectGetIter;
|
@@ -150,42 +151,62 @@ protected static boolean isEconomicMapStorage(Object o) {
|
150 | 151 | }
|
151 | 152 |
|
152 | 153 | /**
|
153 |
| - * Gets clone of the keys of the storage with all values either set to given value or with no |
154 |
| - * guarantees about the values if {@link PNone#NO_VALUE} is passed as {@code value}. |
| 154 | + * Gets clone of the keys of the storage with all values set to given value or (when used to |
| 155 | + * create a set or frozenset) to NO_VALUE. |
155 | 156 | */
|
156 | 157 | @GenerateInline(inlineByDefault = true)
|
157 | 158 | public abstract static class GetClonedHashingStorageNode extends PNodeWithContext {
|
158 |
| - public abstract HashingStorage execute(VirtualFrame frame, Node inliningTarget, Object iterator, Object value); |
| 159 | + protected abstract HashingStorage execute(VirtualFrame frame, Node inliningTarget, Object iterator, Object value); |
159 | 160 |
|
160 |
| - public final HashingStorage doNoValue(VirtualFrame frame, Node inliningTarget, Object iterator) { |
| 161 | + /** |
| 162 | + * Gets clone of the keys of the storage with all values either set to given value or, if |
| 163 | + * that is PNone.NO_VALUE, all values set to PNone.NONE. Use this method to clone into a |
| 164 | + * dict or other object where the values may be accessible from Python to avoid a) |
| 165 | + * PNone.NO_VALUE leaking to Python. |
| 166 | + */ |
| 167 | + public final HashingStorage getForDictionaries(VirtualFrame frame, Node inliningTarget, Object iterator, Object value) { |
| 168 | + return execute(frame, inliningTarget, iterator, value == PNone.NO_VALUE ? PNone.NONE : value); |
| 169 | + } |
| 170 | + |
| 171 | + /** |
| 172 | + * Gets a clone of the keys of the storage with all values set to NO_VALUE. This must be |
| 173 | + * used *only* to create new storages for use in sets and frozensets where the values cannot |
| 174 | + * be accessed from user code. |
| 175 | + */ |
| 176 | + public final HashingStorage getForSets(VirtualFrame frame, Node inliningTarget, Object iterator) { |
161 | 177 | return execute(frame, inliningTarget, iterator, PNone.NO_VALUE);
|
162 | 178 | }
|
163 | 179 |
|
164 |
| - public final HashingStorage doNoValueCached(VirtualFrame frame, Object iterator) { |
| 180 | + /** |
| 181 | + * IMPORTANT: Only for sets and frozensets. |
| 182 | + * |
| 183 | + * @see #getForSets(VirtualFrame, Node, Object) |
| 184 | + */ |
| 185 | + public final HashingStorage getForSetsCached(VirtualFrame frame, Object iterator) { |
165 | 186 | return execute(frame, null, iterator, PNone.NO_VALUE);
|
166 | 187 | }
|
167 | 188 |
|
168 |
| - @Specialization(guards = "isNoValue(value)") |
169 |
| - static HashingStorage doHashingCollectionNoValue(Node inliningTarget, PHashingCollection other, @SuppressWarnings("unused") Object value, |
170 |
| - @Shared("copyNode") @Cached HashingStorageCopy copyNode) { |
| 189 | + // This for cloning sets (we come here from doNoValue or doNoValueCached). If we clone from |
| 190 | + // some other PHashingCollection, we would hold on to keys in the sets, and if we were to |
| 191 | + // clone for some other PHashingCollection (not PBaseSet), we might leak NO_VALUE into user |
| 192 | + // code. |
| 193 | + @Specialization(guards = "isNoValue(givenValue)") |
| 194 | + static HashingStorage doSet(Node inliningTarget, PBaseSet other, @SuppressWarnings("unused") Object givenValue, |
| 195 | + @Cached HashingStorageCopy copyNode) { |
171 | 196 | return copyNode.execute(inliningTarget, other.getDictStorage());
|
172 | 197 | }
|
173 | 198 |
|
174 |
| - @Specialization(guards = "isNoValue(value)") |
175 |
| - static HashingStorage doPDictKeyViewNoValue(Node inliningTarget, PDictView.PDictKeysView other, Object value, |
176 |
| - @Shared("copyNode") @Cached HashingStorageCopy copyNode) { |
177 |
| - return copyNode.execute(inliningTarget, other.getWrappedStorage()); |
178 |
| - } |
179 |
| - |
180 |
| - @Specialization(guards = "!isNoValue(value)") |
181 |
| - static HashingStorage doHashingCollection(VirtualFrame frame, PHashingCollection other, Object value, |
| 199 | + @Specialization(replaces = "doSet") |
| 200 | + static HashingStorage doHashingCollection(VirtualFrame frame, PHashingCollection other, Object givenValue, |
182 | 201 | @Shared @Cached(inline = false) GetClonedHashingCollectionNode hashingCollectionNode) {
|
| 202 | + Object value = givenValue == PNone.NO_VALUE ? PNone.NONE : givenValue; |
183 | 203 | return hashingCollectionNode.execute(frame, other.getDictStorage(), value);
|
184 | 204 | }
|
185 | 205 |
|
186 |
| - @Specialization(guards = "!isNoValue(value)") |
187 |
| - static HashingStorage doPDictView(VirtualFrame frame, PDictView.PDictKeysView other, Object value, |
| 206 | + @Specialization |
| 207 | + static HashingStorage doPDictView(VirtualFrame frame, PDictView.PDictKeysView other, Object givenValue, |
188 | 208 | @Shared @Cached(inline = false) GetClonedHashingCollectionNode hashingCollectionNode) {
|
| 209 | + Object value = givenValue == PNone.NO_VALUE ? PNone.NONE : givenValue; |
189 | 210 | return hashingCollectionNode.execute(frame, other.getWrappedStorage(), value);
|
190 | 211 | }
|
191 | 212 |
|
@@ -282,7 +303,7 @@ static HashingStorage doPDictView(PDictView.PDictKeysView other) {
|
282 | 303 | @InliningCutoff
|
283 | 304 | static HashingStorage doGeneric(VirtualFrame frame, Node inliningTarget, Object other,
|
284 | 305 | @Cached GetClonedHashingStorageNode getHashingStorageNode) {
|
285 |
| - return getHashingStorageNode.doNoValue(frame, inliningTarget, other); |
| 306 | + return getHashingStorageNode.getForSets(frame, inliningTarget, other); |
286 | 307 | }
|
287 | 308 | }
|
288 | 309 | }
|
0 commit comments