Skip to content

Commit ed39066

Browse files
committed
[GR-17453] [GR-17191] Benchmark tweaks
PullRequest: graalpython/599
2 parents 5aebc2d + b48420b commit ed39066

File tree

4 files changed

+177
-162
lines changed

4 files changed

+177
-162
lines changed

ci_common/mixins.libsonnet

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -115,7 +115,7 @@ local const = import 'constants.libsonnet';
115115
BENCH_RESULTS_FILE_PATH: "bench-results.json",
116116
},
117117
logs +: [
118-
"results.json",
118+
"bench-results.json",
119119
],
120120
},
121121
bench:: bench,

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/attributes/ReadAttributeFromDynamicObjectNode.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -133,7 +133,7 @@ protected Object readDirect(DynamicObject dynamicObject, Object key,
133133
if (loc == null) {
134134
return PNone.NO_VALUE;
135135
} else {
136-
return loc.get(dynamicObject);
136+
return loc.get(dynamicObject, cachedShape);
137137
}
138138
}
139139

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/frame/DestructuringAssignmentNode.java

Lines changed: 142 additions & 137 deletions
Original file line numberDiff line numberDiff line change
@@ -25,61 +25,43 @@
2525
*/
2626
package com.oracle.graal.python.nodes.frame;
2727

28-
import static com.oracle.graal.python.builtins.objects.PNone.NO_VALUE;
29-
import static com.oracle.graal.python.nodes.SpecialMethodNames.__GETITEM__;
30-
import static com.oracle.graal.python.runtime.exception.PythonErrorType.IndexError;
3128
import static com.oracle.graal.python.runtime.exception.PythonErrorType.ValueError;
3229

33-
import java.util.Arrays;
34-
3530
import com.oracle.graal.python.PythonLanguage;
36-
import com.oracle.graal.python.builtins.modules.BuiltinFunctions;
37-
import com.oracle.graal.python.builtins.modules.BuiltinFunctionsFactory;
31+
import com.oracle.graal.python.builtins.PythonBuiltinClassType;
32+
import com.oracle.graal.python.builtins.objects.common.SequenceStorageNodes;
33+
import com.oracle.graal.python.builtins.objects.list.PList;
34+
import com.oracle.graal.python.builtins.objects.tuple.PTuple;
3835
import com.oracle.graal.python.nodes.PRaiseNode;
39-
import com.oracle.graal.python.nodes.attributes.LookupInheritedAttributeNode;
40-
import com.oracle.graal.python.nodes.builtins.ListNodes.CreateStorageFromIteratorNode;
4136
import com.oracle.graal.python.nodes.builtins.TupleNodes;
42-
import com.oracle.graal.python.nodes.control.GetIteratorExpressionNode.GetIteratorNode;
4337
import com.oracle.graal.python.nodes.expression.ExpressionNode;
4438
import com.oracle.graal.python.nodes.object.IsBuiltinClassProfile;
4539
import com.oracle.graal.python.nodes.statement.StatementNode;
46-
import com.oracle.graal.python.nodes.subscript.GetItemNode;
47-
import com.oracle.graal.python.nodes.subscript.GetItemNodeGen;
4840
import com.oracle.graal.python.runtime.PythonContext;
49-
import com.oracle.graal.python.runtime.exception.PException;
41+
import com.oracle.graal.python.runtime.PythonCore;
5042
import com.oracle.graal.python.runtime.object.PythonObjectFactory;
43+
import com.oracle.graal.python.runtime.sequence.storage.SequenceStorage;
44+
import com.oracle.truffle.api.CompilerAsserts;
5145
import com.oracle.truffle.api.CompilerDirectives;
5246
import com.oracle.truffle.api.CompilerDirectives.CompilationFinal;
5347
import com.oracle.truffle.api.TruffleLanguage.ContextReference;
48+
import com.oracle.truffle.api.dsl.Cached;
49+
import com.oracle.truffle.api.dsl.Specialization;
5450
import com.oracle.truffle.api.frame.VirtualFrame;
5551
import com.oracle.truffle.api.nodes.ExplodeLoop;
56-
import com.oracle.truffle.api.profiles.BranchProfile;
5752

58-
public final class DestructuringAssignmentNode extends StatementNode implements WriteNode {
59-
@Child private PythonObjectFactory factory = PythonObjectFactory.create();
53+
public abstract class DestructuringAssignmentNode extends StatementNode implements WriteNode {
54+
/* Lazily initialized helpers, also acting as branch profiles */
6055
@Child private PRaiseNode raiseNode;
56+
@Child private PythonObjectFactory factory;
6157
@CompilationFinal private ContextReference<PythonContext> contextRef;
6258

59+
/* Syntactic children */
6360
@Child private ExpressionNode rhs;
6461
@Children private final WriteNode[] slots;
6562
@Children private final StatementNode[] assignments;
6663

67-
@Child private GetItemNode getItem = GetItemNodeGen.create();
68-
@Child private GetItemNode getNonExistingItem = GetItemNodeGen.create();
69-
@Child private BuiltinFunctions.LenNode lenNode;
70-
@Child private LookupInheritedAttributeNode lookupGetItemNode = LookupInheritedAttributeNode.create(__GETITEM__);
71-
@Child private TupleNodes.ConstructTupleNode constructTupleNode = TupleNodes.ConstructTupleNode.create();
72-
73-
@Child private CreateStorageFromIteratorNode storageNode = CreateStorageFromIteratorNode.create();
74-
@Child private GetIteratorNode getIteratorNode = GetIteratorNode.create();
75-
76-
private final IsBuiltinClassProfile notEnoughValuesProfile = IsBuiltinClassProfile.create();
77-
private final IsBuiltinClassProfile tooManyValuesErrorProfile = IsBuiltinClassProfile.create();
78-
private final BranchProfile tooManyValuesProfile = BranchProfile.create();
79-
80-
private final IsBuiltinClassProfile errorProfile1 = IsBuiltinClassProfile.create();
81-
private final IsBuiltinClassProfile errorProfile2 = IsBuiltinClassProfile.create();
82-
private final int starredIndex;
64+
protected final int starredIndex;
8365

8466
public DestructuringAssignmentNode(ExpressionNode rhs, ReadNode[] slots, int starredIndex, StatementNode[] assignments) {
8567
this.rhs = rhs;
@@ -89,135 +71,157 @@ public DestructuringAssignmentNode(ExpressionNode rhs, ReadNode[] slots, int sta
8971
for (int i = 0; i < slots.length; i++) {
9072
this.slots[i] = (WriteNode) slots[i].makeWriteNode(null);
9173
}
92-
this.lenNode = starredIndex == -1 ? null : BuiltinFunctionsFactory.LenNodeFactory.create();
9374
}
9475

9576
public static DestructuringAssignmentNode create(ExpressionNode rhs, ReadNode[] slots, int starredIndex, StatementNode[] assignments) {
96-
return new DestructuringAssignmentNode(rhs, slots, starredIndex, assignments);
77+
return DestructuringAssignmentNodeGen.create(rhs, slots, starredIndex, assignments);
9778
}
9879

99-
@ExplodeLoop
100-
private void fillSlots(VirtualFrame frame, Object rhsValue, int stop) {
101-
for (int i = 0; i < stop; i++) {
102-
Object value = getItem.execute(frame, rhsValue, i);
103-
slots[i].doWrite(frame, value);
104-
}
80+
public abstract void executeWith(VirtualFrame frame, Object rhsValue);
81+
82+
@Override
83+
public final void executeVoid(VirtualFrame frame) {
84+
Object rhsValue = rhs.execute(frame);
85+
executeWith(frame, rhsValue);
10586
}
10687

107-
@ExplodeLoop
108-
private int fillRest(VirtualFrame frame, Object rhsValue, int pos) {
109-
int current = pos;
110-
for (int i = starredIndex + 1; i < slots.length; i++) {
111-
Object value = getItem.execute(frame, rhsValue, current++);
112-
slots[i].doWrite(frame, value);
113-
}
114-
return current;
88+
public final void doWrite(VirtualFrame frame, Object rhsValue) {
89+
executeWith(frame, rhsValue);
90+
}
91+
92+
public ExpressionNode getRhs() {
93+
return rhs;
94+
}
95+
96+
protected static boolean isBuiltinList(Object object, IsBuiltinClassProfile profile) {
97+
return object instanceof PList && profile.profileObject((PList) object, PythonBuiltinClassType.PList);
98+
}
99+
100+
protected static boolean isBuiltinTuple(Object object, IsBuiltinClassProfile profile) {
101+
return object instanceof PTuple && profile.profileObject((PTuple) object, PythonBuiltinClassType.PTuple);
102+
}
103+
104+
@Specialization(guards = {"isBuiltinList(rhsVal, isBuiltinClass)", "starredIndex < 0"})
105+
public void writeList(VirtualFrame frame, PList rhsVal,
106+
@Cached SequenceStorageNodes.LenNode lenNode,
107+
@Cached SequenceStorageNodes.GetItemNode getItemNode,
108+
@SuppressWarnings("unused") @Cached IsBuiltinClassProfile isBuiltinClass) {
109+
SequenceStorage sequenceStorage = rhsVal.getSequenceStorage();
110+
writeSequenceStorage(frame, sequenceStorage, lenNode, getItemNode);
111+
performAssignments(frame);
112+
}
113+
114+
@Specialization(guards = {"isBuiltinTuple(rhsVal, isBuiltinClass)", "starredIndex < 0"})
115+
public void writeTuple(VirtualFrame frame, PTuple rhsVal,
116+
@Cached SequenceStorageNodes.LenNode lenNode,
117+
@Cached SequenceStorageNodes.GetItemNode getItemNode,
118+
@SuppressWarnings("unused") @Cached IsBuiltinClassProfile isBuiltinClass) {
119+
SequenceStorage sequenceStorage = rhsVal.getSequenceStorage();
120+
writeSequenceStorage(frame, sequenceStorage, lenNode, getItemNode);
121+
performAssignments(frame);
115122
}
116123

117124
@ExplodeLoop
118-
private int fillFromArray(VirtualFrame frame, Object[] array, int startIndex) {
119-
int index = startIndex;
120-
for (int i = starredIndex + 1; i < slots.length; i++) {
121-
slots[i].doWrite(frame, array[index++]);
125+
private void writeSequenceStorage(VirtualFrame frame, SequenceStorage sequenceStorage, SequenceStorageNodes.LenNode lenNode, SequenceStorageNodes.GetItemNode getItemNode) {
126+
int len = lenNode.execute(sequenceStorage);
127+
if (len > slots.length) {
128+
throw getCore().raiseInvalidSyntax(getEncapsulatingSourceSection().getSource(), getEncapsulatingSourceSection(), "too many values to unpack (expected %d)", slots.length);
129+
} else if (len < slots.length) {
130+
throw ensureRaiseNode().raise(ValueError, "not enough values to unpack (expected %d, got %d)", slots.length, len);
131+
} else {
132+
for (int i = 0; i < slots.length; i++) {
133+
Object value = getItemNode.execute(sequenceStorage, i);
134+
slots[i].doWrite(frame, value);
135+
}
122136
}
123-
return index;
124137
}
125138

126-
private int fillStarred(VirtualFrame frame, Object rhsValue) {
127-
int pos = starredIndex;
128-
try {
129-
// TODO(ls): proper cast to int
130-
// TODO(ls): the result of the len call doesn't seem to be used in Python
131-
int length = (int) lenNode.executeWith(frame, rhsValue);
132-
int starredLength = length - (slots.length - 1);
139+
@Specialization(guards = {"isBuiltinList(rhsVal, isBuiltinClass)", "starredIndex >= 0"})
140+
public void writeListStarred(VirtualFrame frame, PList rhsVal,
141+
@Cached SequenceStorageNodes.LenNode lenNode,
142+
@Cached SequenceStorageNodes.GetItemNode getItemNode,
143+
@SuppressWarnings("unused") @Cached IsBuiltinClassProfile isBuiltinClass) {
144+
SequenceStorage sequenceStorage = rhsVal.getSequenceStorage();
145+
writeSequenceStorageStarred(frame, sequenceStorage, lenNode, getItemNode);
146+
performAssignments(frame);
147+
}
148+
149+
@Specialization(guards = {"isBuiltinTuple(rhsVal, isBuiltinClass)", "starredIndex >= 0"})
150+
public void writeTupleStarred(VirtualFrame frame, PTuple rhsVal,
151+
@Cached SequenceStorageNodes.LenNode lenNode,
152+
@Cached SequenceStorageNodes.GetItemNode getItemNode,
153+
@SuppressWarnings("unused") @Cached IsBuiltinClassProfile isBuiltinClass) {
154+
SequenceStorage sequenceStorage = rhsVal.getSequenceStorage();
155+
writeSequenceStorageStarred(frame, sequenceStorage, lenNode, getItemNode);
156+
performAssignments(frame);
157+
}
158+
159+
@ExplodeLoop
160+
private void writeSequenceStorageStarred(VirtualFrame frame, SequenceStorage sequenceStorage, SequenceStorageNodes.LenNode lenNode, SequenceStorageNodes.GetItemNode getItemNode) {
161+
int len = lenNode.execute(sequenceStorage);
162+
if (len < slots.length - 1) {
163+
throw ensureRaiseNode().raise(ValueError, "not enough values to unpack (expected %d, got %d)", slots.length, len);
164+
} else {
165+
for (int i = 0; i < starredIndex; i++) {
166+
Object value = getItemNode.execute(sequenceStorage, i);
167+
slots[i].doWrite(frame, value);
168+
}
169+
final int starredLength = len - (slots.length - 1);
133170
Object[] array = new Object[starredLength];
171+
CompilerAsserts.partialEvaluationConstant(starredLength);
172+
int pos = starredIndex;
134173
for (int i = 0; i < starredLength; i++) {
135-
array[i] = getItem.execute(frame, rhsValue, pos++);
174+
array[i] = getItemNode.execute(sequenceStorage, pos++);
136175
}
137-
slots[starredIndex].doWrite(frame, factory.createList(array));
138-
return fillRest(frame, rhsValue, pos);
139-
} catch (PException e) {
140-
e.expectAttributeError(errorProfile1);
141-
// __len__ is not implemented
142-
Object[] array = new Object[2];
143-
int length = 0;
144-
while (true) {
145-
try {
146-
if (length + 1 > array.length) {
147-
array = Arrays.copyOf(array, array.length << 1);
148-
}
149-
array[length] = getItem.execute(frame, rhsValue, pos);
150-
length++;
151-
pos++;
152-
} catch (PException e2) {
153-
e2.expect(IndexError, errorProfile2);
154-
// expected, fall through
155-
break;
156-
}
176+
slots[starredIndex].doWrite(frame, factory().createList(array));
177+
for (int i = starredIndex + 1; i < slots.length; i++) {
178+
Object value = getItemNode.execute(sequenceStorage, pos++);
179+
slots[i].doWrite(frame, value);
157180
}
158-
int rest = slots.length - starredIndex - 1;
159-
fillFromArray(frame, array, length - rest);
160-
slots[starredIndex].doWrite(frame, factory.createList(Arrays.copyOf(array, length - rest)));
161181
}
162-
return pos;
163182
}
164183

165-
@Override
166-
public void executeVoid(VirtualFrame frame) {
167-
Object rhsValue = rhs.execute(frame);
168-
Object getItemAttribute = lookupGetItemNode.execute(rhsValue);
169-
if (getItemAttribute == NO_VALUE) {
170-
rhsValue = constructTupleNode.execute(frame, rhsValue);
184+
@ExplodeLoop
185+
private void performAssignments(VirtualFrame frame) {
186+
for (int i = 0; i < assignments.length; i++) {
187+
assignments[i].executeVoid(frame);
171188
}
172-
doWrite(frame, rhsValue);
173189
}
174190

175-
public ExpressionNode getRhs() {
176-
return rhs;
191+
@Specialization(guards = {"!isBuiltinTuple(iterable, tupleProfile)", "!isBuiltinList(iterable, listProfile)", "starredIndex < 0"})
192+
public void writeIterable(VirtualFrame frame, Object iterable,
193+
@Cached TupleNodes.ConstructTupleNode constructTupleNode,
194+
@Cached SequenceStorageNodes.LenNode lenNode,
195+
@Cached SequenceStorageNodes.GetItemNode getItemNode,
196+
@SuppressWarnings("unused") @Cached IsBuiltinClassProfile tupleProfile,
197+
@SuppressWarnings("unused") @Cached IsBuiltinClassProfile listProfile) {
198+
PTuple rhsValue = constructTupleNode.execute(frame, iterable);
199+
SequenceStorage sequenceStorage = rhsValue.getSequenceStorage();
200+
writeSequenceStorage(frame, sequenceStorage, lenNode, getItemNode);
201+
performAssignments(frame);
177202
}
178203

179-
public void doWrite(VirtualFrame frame, Object rhsVal) {
180-
Object rhsValue = factory.createList(storageNode.execute(frame, getIteratorNode.executeWith(frame, rhsVal)));
181-
int nonExistingItem;
182-
try {
183-
if (starredIndex == -1) {
184-
fillSlots(frame, rhsValue, slots.length);
185-
nonExistingItem = slots.length;
186-
} else {
187-
fillSlots(frame, rhsValue, starredIndex);
188-
nonExistingItem = fillStarred(frame, rhsValue);
189-
}
190-
} catch (PException e) {
191-
if (notEnoughValuesProfile.profileException(e, IndexError)) {
192-
if (lenNode == null) {
193-
CompilerDirectives.transferToInterpreterAndInvalidate();
194-
lenNode = insert(BuiltinFunctionsFactory.LenNodeFactory.create());
195-
}
196-
throw ensureRaiseNode().raise(ValueError, "not enough values to unpack (expected %d, got %d)", slots.length, lenNode.executeWith(frame, rhsValue));
197-
} else {
198-
throw e;
199-
}
200-
}
201-
try {
202-
getNonExistingItem.execute(frame, rhsValue, nonExistingItem);
203-
tooManyValuesProfile.enter();
204-
if (contextRef == null) {
205-
CompilerDirectives.transferToInterpreterAndInvalidate();
206-
contextRef = PythonLanguage.getContextRef();
207-
}
208-
throw contextRef.get().getCore().raiseInvalidSyntax(getEncapsulatingSourceSection().getSource(), getEncapsulatingSourceSection(), "too many values to unpack (expected %d)",
209-
nonExistingItem);
210-
} catch (PException e) {
211-
if (tooManyValuesErrorProfile.profileException(e, IndexError)) {
212-
// expected, fall through
213-
} else {
214-
throw e;
215-
}
216-
}
217-
204+
@Specialization(guards = {"!isBuiltinTuple(iterable, tupleProfile)", "!isBuiltinList(iterable, listProfile)", "starredIndex >= 0"})
205+
public void writeIterableStarred(VirtualFrame frame, Object iterable,
206+
@Cached TupleNodes.ConstructTupleNode constructTupleNode,
207+
@Cached SequenceStorageNodes.LenNode lenNode,
208+
@Cached SequenceStorageNodes.GetItemNode getItemNode,
209+
@SuppressWarnings("unused") @Cached IsBuiltinClassProfile tupleProfile,
210+
@SuppressWarnings("unused") @Cached IsBuiltinClassProfile listProfile) {
211+
PTuple rhsValue = constructTupleNode.execute(frame, iterable);
212+
SequenceStorage sequenceStorage = rhsValue.getSequenceStorage();
213+
writeSequenceStorageStarred(frame, sequenceStorage, lenNode, getItemNode);
218214
performAssignments(frame);
219215
}
220216

217+
private PythonCore getCore() {
218+
if (contextRef == null) {
219+
CompilerDirectives.transferToInterpreterAndInvalidate();
220+
contextRef = PythonLanguage.getContextRef();
221+
}
222+
return contextRef.get().getCore();
223+
}
224+
221225
private PRaiseNode ensureRaiseNode() {
222226
if (raiseNode == null) {
223227
CompilerDirectives.transferToInterpreterAndInvalidate();
@@ -226,10 +230,11 @@ private PRaiseNode ensureRaiseNode() {
226230
return raiseNode;
227231
}
228232

229-
@ExplodeLoop
230-
private void performAssignments(VirtualFrame frame) {
231-
for (int i = 0; i < assignments.length; i++) {
232-
assignments[i].executeVoid(frame);
233+
private PythonObjectFactory factory() {
234+
if (factory == null) {
235+
CompilerDirectives.transferToInterpreterAndInvalidate();
236+
factory = insert(PythonObjectFactory.create());
233237
}
238+
return factory;
234239
}
235240
}

0 commit comments

Comments
 (0)