Skip to content

Commit d929828

Browse files
qunaibitsteve-s
authored andcommitted
Refactor and clean up
1 parent a3258d1 commit d929828

File tree

2 files changed

+130
-160
lines changed

2 files changed

+130
-160
lines changed

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/common/HashingStorage.java

Lines changed: 119 additions & 109 deletions
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,6 @@
6868
import com.oracle.graal.python.nodes.attributes.LookupCallableSlotInMRONode;
6969
import com.oracle.graal.python.nodes.builtins.ListNodes.FastConstructListNode;
7070
import com.oracle.graal.python.nodes.call.special.CallVarargsMethodNode;
71-
import com.oracle.graal.python.nodes.call.special.LookupAndCallUnaryNode;
7271
import com.oracle.graal.python.nodes.object.BuiltinClassProfiles.IsBuiltinObjectProfile;
7372
import com.oracle.graal.python.nodes.object.GetClassNode;
7473
import com.oracle.graal.python.runtime.ExecutionContext.IndirectCallContext;
@@ -81,6 +80,9 @@
8180
import com.oracle.truffle.api.dsl.Bind;
8281
import com.oracle.truffle.api.dsl.Cached;
8382
import com.oracle.truffle.api.dsl.Cached.Exclusive;
83+
import com.oracle.truffle.api.dsl.Cached.Shared;
84+
import com.oracle.truffle.api.dsl.GenerateCached;
85+
import com.oracle.truffle.api.dsl.GenerateInline;
8486
import com.oracle.truffle.api.dsl.NeverDefault;
8587
import com.oracle.truffle.api.dsl.Specialization;
8688
import com.oracle.truffle.api.frame.VirtualFrame;
@@ -157,16 +159,12 @@ static HashingStorage doNoBuiltinKeysAttr(VirtualFrame frame, PHashingCollection
157159
@Bind("this") Node inliningTarget,
158160
@SuppressWarnings("unused") @Exclusive @Cached GetClassNode getClassNode,
159161
@SuppressWarnings("unused") @Exclusive @Cached(parameters = "Iter") LookupCallableSlotInMRONode lookupIter,
160-
@Exclusive @Cached PyObjectGetIter getIter,
161-
@Exclusive @Cached HashingStorageSetItem setHashingStorageItem,
162-
@Exclusive @Cached HashingStorageAddAllToOther addAllToOther,
163-
@Exclusive @Cached("create(T_KEYS)") LookupAndCallUnaryNode callKeysNode,
164-
@Exclusive @Cached PyObjectGetItem getItemNode,
165-
@Exclusive @Cached GetNextNode nextNode,
166-
@Exclusive @Cached IsBuiltinObjectProfile errorProfile) {
167-
HashingStorage curStorage = PDict.createNewStorage(0);
168-
Object keysIterable = callKeysNode.executeObject(frame, col);
169-
return copyToStorage(frame, col, kwargs, curStorage, inliningTarget, keysIterable, getItemNode, getIter, nextNode, errorProfile, setHashingStorageItem, addAllToOther);
162+
@Exclusive @Cached PyObjectLookupAttr lookupKeysAttributeNode,
163+
@Exclusive @Cached ObjectToArrayPairNode toArrayPair,
164+
@Exclusive @Cached HashingStorageSetItem setHasihngStorageItem,
165+
@Exclusive @Cached HashingStorageAddAllToOther addAllToOther) {
166+
return updateArg(frame, col, kwargs, inliningTarget, lookupKeysAttributeNode,
167+
toArrayPair, setHasihngStorageItem, addAllToOther);
170168
}
171169

172170
protected static boolean hasIterAttrButNotBuiltin(Node inliningTarget, PHashingCollection col, GetClassNode getClassNode, LookupCallableSlotInMRONode lookupIter) {
@@ -177,34 +175,16 @@ protected static boolean hasIterAttrButNotBuiltin(Node inliningTarget, PHashingC
177175
@Specialization(guards = {"!isNoValue(arg)", "!isPDict(arg)"})
178176
static HashingStorage updateArg(VirtualFrame frame, Object arg, PKeyword[] kwargs,
179177
@Bind("this") Node inliningTarget,
180-
@Cached PyObjectLookupAttr lookupKeysAttributeNode,
181-
@Cached CallVarargsMethodNode callKeysMethod,
178+
@Exclusive @Cached PyObjectLookupAttr lookupKeysAttributeNode,
179+
@Exclusive @Cached ObjectToArrayPairNode toArrayPair,
182180
@Exclusive @Cached HashingStorageSetItem setHasihngStorageItem,
183-
@Exclusive @Cached HashingStorageAddAllToOther addAllToOther,
184-
@Exclusive @Cached PyObjectGetIter getIter,
185-
@Cached PRaiseNode.Lazy raise,
186-
@Exclusive @Cached GetNextNode nextNode,
187-
@Cached FastConstructListNode createListNode,
188-
@Exclusive @Cached PyObjectGetItem getItemNode,
189-
@Cached SequenceNodes.LenNode seqLenNode,
190-
@Cached InlinedConditionProfile lengthTwoProfile,
191-
@Cached InlinedConditionProfile hasKeyProfile,
192-
@Exclusive @Cached IsBuiltinObjectProfile errorProfile,
193-
@Exclusive @Cached IsBuiltinObjectProfile isTypeErrorProfile) {
181+
@Exclusive @Cached HashingStorageAddAllToOther addAllToOther) {
194182
Object keyAttr = lookupKeysAttributeNode.execute(frame, inliningTarget, arg, T_KEYS);
195-
if (hasKeyProfile.profile(inliningTarget, keyAttr != PNone.NO_VALUE)) {
196-
HashingStorage curStorage = PDict.createNewStorage(0);
197-
// We don't need to pass self as the attribute object has it already.
198-
Object keysIterable = callKeysMethod.execute(frame, keyAttr, EMPTY_OBJECT_ARRAY, EMPTY_KEYWORDS);
199-
return copyToStorage(frame, arg, kwargs, curStorage,
200-
inliningTarget, keysIterable, getItemNode, getIter, nextNode,
201-
errorProfile, setHasihngStorageItem, addAllToOther);
202-
} else {
203-
return addSequenceToStorage(frame, arg, kwargs,
204-
inliningTarget, PDict::createNewStorage, getIter, nextNode, createListNode,
205-
seqLenNode, lengthTwoProfile, raise, getItemNode, isTypeErrorProfile,
206-
errorProfile, setHasihngStorageItem, addAllToOther);
207-
}
183+
ArrayBuilder<KeyValue> elements = toArrayPair.execute(frame, arg, keyAttr);
184+
HashingStorage storage = PDict.createNewStorage(elements.size() + kwargs.length);
185+
storage = addKeyValuesToStorage(frame, elements, storage, inliningTarget, setHasihngStorageItem);
186+
storage = addKeywordsToStorage(frame, kwargs, storage, inliningTarget, addAllToOther);
187+
return storage;
208188
}
209189

210190
@NeverDefault
@@ -227,90 +207,120 @@ public final HashingStorage unionCached(HashingStorage other, HashingStorageCopy
227207
return addAllToOther.executeCached(null, other, newStore);
228208
}
229209

230-
/**
231-
* Adds all items from the given mapping object to storage. It is the caller responsibility to
232-
* ensure, that mapping has the 'keys' attribute.
233-
*/
234-
public static HashingStorage copyToStorage(VirtualFrame frame, Object mapping, PKeyword[] kwargs, HashingStorage storage,
210+
public static HashingStorage addKeywordsToStorage(VirtualFrame frame, PKeyword[] kwargs, HashingStorage storage,
235211
Node inliningTarget,
236-
Object keysIterable,
237-
PyObjectGetItem callGetItemNode,
238-
PyObjectGetIter getIter,
239-
GetNextNode nextNode,
240-
IsBuiltinObjectProfile errorProfile,
241-
HashingStorageSetItem setHashingStorageItem,
242-
HashingStorageAddAllToOther addAllToOtherNode) {
243-
Object keysIt = getIter.execute(frame, inliningTarget, keysIterable);
244-
HashingStorage curStorage = storage;
245-
while (true) {
246-
try {
247-
Object keyObj = nextNode.execute(frame, keysIt);
248-
Object valueObj = callGetItemNode.execute(frame, inliningTarget, mapping, keyObj);
212+
HashingStorageAddAllToOther addAllToOther) {
213+
if (kwargs.length > 0) {
214+
return addAllToOther.execute(frame, inliningTarget, new KeywordsStorage(kwargs), storage);
215+
}
216+
return storage;
217+
}
249218

250-
curStorage = setHashingStorageItem.execute(frame, inliningTarget, curStorage, keyObj, valueObj);
251-
} catch (PException e) {
252-
e.expectStopIteration(inliningTarget, errorProfile);
253-
break;
254-
}
219+
protected static final class KeyValue {
220+
final Object key;
221+
final Object value;
222+
223+
private KeyValue(Object key, Object value) {
224+
this.key = key;
225+
this.value = value;
255226
}
256-
if (kwargs.length > 0) {
257-
curStorage = addAllToOtherNode.execute(frame, inliningTarget, new KeywordsStorage(kwargs), curStorage);
227+
}
228+
229+
public static HashingStorage addKeyValuesToStorage(VirtualFrame frame, ArrayBuilder<KeyValue> elements, HashingStorage storage,
230+
Node inliningTarget,
231+
HashingStorageSetItem setHashingStorageItem) {
232+
for (int i = 0; i < elements.size(); i++) {
233+
Object key = elements.get(i).key;
234+
Object value = elements.get(i).value;
235+
storage = setHashingStorageItem.execute(frame, inliningTarget, storage, key, value);
258236
}
259-
return curStorage;
237+
return storage;
260238
}
261239

262-
@FunctionalInterface
263-
public interface StorageSupplier {
264-
HashingStorage get(int length);
240+
public static HashingStorage addKeyValuesToStorage(VirtualFrame frame, PDict self, Object other, Object keyAttr,
241+
Node inliningTarget,
242+
ObjectToArrayPairNode toArrayPair,
243+
HashingStorageSetItem setHashingStorageItem) {
244+
ArrayBuilder<KeyValue> elements = toArrayPair.execute(frame, other, keyAttr);
245+
HashingStorage storage = self.getDictStorage();
246+
return addKeyValuesToStorage(frame, elements, storage, inliningTarget, setHashingStorageItem);
265247
}
266248

267-
public static HashingStorage addSequenceToStorage(VirtualFrame frame, Object iterable, PKeyword[] kwargs, Node inliningTarget,
268-
StorageSupplier storageSupplier,
269-
PyObjectGetIter getIter,
270-
GetNextNode nextNode,
271-
FastConstructListNode createListNode,
272-
LenNode seqLenNode,
273-
InlinedConditionProfile lengthTwoProfile,
274-
PRaiseNode.Lazy raise,
275-
PyObjectGetItem getItemNode,
276-
IsBuiltinObjectProfile isTypeErrorProfile,
277-
IsBuiltinObjectProfile errorProfile,
278-
HashingStorageSetItem setHashingStorageItem,
279-
HashingStorageAddAllToOther addAllToOther) throws PException {
280-
Object it = getIter.execute(frame, inliningTarget, iterable);
281-
ArrayBuilder<PSequence> elements = new ArrayBuilder<>();
282-
try {
283-
while (true) {
284-
Object next = nextNode.execute(frame, it);
285-
PSequence element = createListNode.execute(frame, inliningTarget, next);
286-
assert element != null;
287-
// This constructs a new list using the builtin type. So, the object cannot
288-
// be subclassed and we can directly call 'len()'.
289-
int len = seqLenNode.execute(inliningTarget, element);
249+
// partial impl dict_update_arg
250+
@GenerateCached
251+
@GenerateInline(false)
252+
public abstract static class ObjectToArrayPairNode extends PNodeWithContext {
253+
public abstract ArrayBuilder<KeyValue> execute(VirtualFrame frame, Object mapping, Object keyAttr);
290254

291-
if (lengthTwoProfile.profile(inliningTarget, len != 2)) {
292-
throw raise.get(inliningTarget).raise(ValueError, ErrorMessages.DICT_UPDATE_SEQ_ELEM_HAS_LENGTH_2_REQUIRED, elements.size(), len);
255+
/**
256+
* Adds all items from the given mapping object to storage. It is the caller responsibility
257+
* to ensure, that mapping has the 'keys' attribute.
258+
*/
259+
// partial impl PyDict_Merge
260+
@Specialization(guards = "!isNoValue(keyAttr)")
261+
static ArrayBuilder<KeyValue> partialMerge(VirtualFrame frame, Object mapping, Object keyAttr,
262+
@Bind("this") Node inliningTarget,
263+
@Shared @Cached PyObjectGetIter getIter,
264+
@Shared @Cached GetNextNode nextNode,
265+
@Shared @Cached PyObjectGetItem getItemNode,
266+
@Shared @Cached IsBuiltinObjectProfile errorProfile,
267+
@Cached CallVarargsMethodNode callKeysMethod) {
268+
// We don't need to pass self as the attribute object has it already.
269+
Object keysIterable = callKeysMethod.execute(frame, keyAttr, EMPTY_OBJECT_ARRAY, EMPTY_KEYWORDS);
270+
Object keysIt = getIter.execute(frame, inliningTarget, keysIterable);
271+
ArrayBuilder<KeyValue> elements = new ArrayBuilder<>();
272+
while (true) {
273+
try {
274+
Object keyObj = nextNode.execute(frame, keysIt);
275+
Object valueObj = getItemNode.execute(frame, inliningTarget, mapping, keyObj);
276+
elements.add(new KeyValue(keyObj, valueObj));
277+
} catch (PException e) {
278+
e.expectStopIteration(inliningTarget, errorProfile);
279+
break;
293280
}
294-
295-
elements.add(element);
296281
}
297-
} catch (PException e) {
298-
if (isTypeErrorProfile.profileException(inliningTarget, e, TypeError)) {
299-
throw raise.get(inliningTarget).raise(TypeError, ErrorMessages.CANNOT_CONVERT_DICT_UPDATE_SEQ, elements.size());
300-
} else {
301-
e.expectStopIteration(inliningTarget, errorProfile);
302-
}
303-
}
304-
HashingStorage storage = storageSupplier.get(elements.size() + kwargs.length);
305-
for (int j = 0; j < elements.size(); j++) {
306-
PSequence element = elements.get(j);
307-
Object key = getItemNode.execute(frame, inliningTarget, element, 0);
308-
Object value = getItemNode.execute(frame, inliningTarget, element, 1);
309-
storage = setHashingStorageItem.execute(frame, inliningTarget, storage, key, value);
282+
return elements;
310283
}
311-
if (kwargs.length > 0) {
312-
storage = addAllToOther.execute(frame, inliningTarget, new KeywordsStorage(kwargs), storage);
284+
285+
// partial impl PyDict_MergeFromSeq2
286+
@Specialization
287+
static ArrayBuilder<KeyValue> partialMergeFromSeq2(VirtualFrame frame, Object iterable, @SuppressWarnings("unused") PNone keyAttr,
288+
@Bind("this") Node inliningTarget,
289+
@Shared @Cached PyObjectGetIter getIter,
290+
@Shared @Cached GetNextNode nextNode,
291+
@Shared @Cached PyObjectGetItem getItemNode,
292+
@Shared @Cached IsBuiltinObjectProfile errorProfile,
293+
@Cached FastConstructListNode createListNode,
294+
@Cached LenNode seqLenNode,
295+
@Cached PRaiseNode.Lazy raise,
296+
@Cached InlinedConditionProfile lengthTwoProfile,
297+
@Exclusive @Cached IsBuiltinObjectProfile isTypeErrorProfile) throws PException {
298+
Object it = getIter.execute(frame, inliningTarget, iterable);
299+
ArrayBuilder<KeyValue> elements = new ArrayBuilder<>();
300+
try {
301+
while (true) {
302+
Object next = nextNode.execute(frame, it);
303+
PSequence element = createListNode.execute(frame, inliningTarget, next);
304+
assert element != null;
305+
// This constructs a new list using the builtin type. So, the object cannot
306+
// be subclassed and we can directly call 'len()'.
307+
int len = seqLenNode.execute(inliningTarget, element);
308+
309+
if (lengthTwoProfile.profile(inliningTarget, len != 2)) {
310+
throw raise.get(inliningTarget).raise(ValueError, ErrorMessages.DICT_UPDATE_SEQ_ELEM_HAS_LENGTH_2_REQUIRED, elements.size(), len);
311+
}
312+
Object key = getItemNode.execute(frame, inliningTarget, element, 0);
313+
Object value = getItemNode.execute(frame, inliningTarget, element, 1);
314+
elements.add(new KeyValue(key, value));
315+
}
316+
} catch (PException e) {
317+
if (isTypeErrorProfile.profileException(inliningTarget, e, TypeError)) {
318+
throw raise.get(inliningTarget).raise(TypeError, ErrorMessages.CANNOT_CONVERT_DICT_UPDATE_SEQ, elements.size());
319+
} else {
320+
e.expectStopIteration(inliningTarget, errorProfile);
321+
}
322+
}
323+
return elements;
313324
}
314-
return storage;
315325
}
316326
}

0 commit comments

Comments
 (0)