Skip to content

Commit 6f2b9b0

Browse files
committed
Improve list allocation
1 parent 7eb3638 commit 6f2b9b0

File tree

7 files changed

+124
-13
lines changed

7 files changed

+124
-13
lines changed

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/generator/PGenerator.java

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2017, 2019, Oracle and/or its affiliates.
2+
* Copyright (c) 2017, 2020, Oracle and/or its affiliates.
33
* Copyright (c) 2013, Regents of the University of California
44
*
55
* All rights reserved.
@@ -29,6 +29,7 @@
2929
import com.oracle.graal.python.builtins.objects.code.PCode;
3030
import com.oracle.graal.python.builtins.objects.frame.PFrame;
3131
import com.oracle.graal.python.builtins.objects.function.PArguments;
32+
import com.oracle.graal.python.builtins.objects.iterator.PRangeIterator;
3233
import com.oracle.graal.python.builtins.objects.object.PythonBuiltinObject;
3334
import com.oracle.graal.python.builtins.objects.type.LazyPythonClass;
3435
import com.oracle.graal.python.parser.ExecutionCellSlots;
@@ -59,9 +60,11 @@ public final class PGenerator extends PythonBuiltinObject {
5960
private boolean finished;
6061
private PCode code;
6162
private int currentCallTarget;
63+
private final Object iterator;
64+
private final boolean isPRangeIterator;
6265

6366
public static PGenerator create(LazyPythonClass clazz, String name, RootCallTarget[] callTargets, FrameDescriptor frameDescriptor, Object[] arguments, PCell[] closure,
64-
ExecutionCellSlots cellSlots, int numOfActiveFlags, int numOfGeneratorBlockNode, int numOfGeneratorForNode, PythonObjectFactory factory) {
67+
ExecutionCellSlots cellSlots, int numOfActiveFlags, int numOfGeneratorBlockNode, int numOfGeneratorForNode, PythonObjectFactory factory, Object iterator) {
6568
/*
6669
* Setting up the persistent frame in {@link #arguments}.
6770
*/
@@ -90,10 +93,10 @@ public static PGenerator create(LazyPythonClass clazz, String name, RootCallTarg
9093
generatorFrame.setObject(cellVarSlots[i], new PCell(cellVarAssumptions[i]));
9194
}
9295
PArguments.setGeneratorFrameLocals(generatorFrameArguments, factory.createDictLocals(generatorFrame));
93-
return new PGenerator(clazz, name, callTargets, frameDescriptor, arguments, closure);
96+
return new PGenerator(clazz, name, callTargets, frameDescriptor, arguments, closure, iterator);
9497
}
9598

96-
private PGenerator(LazyPythonClass clazz, String name, RootCallTarget[] callTargets, FrameDescriptor frameDescriptor, Object[] arguments, PCell[] closure) {
99+
private PGenerator(LazyPythonClass clazz, String name, RootCallTarget[] callTargets, FrameDescriptor frameDescriptor, Object[] arguments, PCell[] closure, Object iterator) {
97100
super(clazz);
98101
this.name = name;
99102
this.callTargets = callTargets;
@@ -102,6 +105,8 @@ private PGenerator(LazyPythonClass clazz, String name, RootCallTarget[] callTarg
102105
this.arguments = arguments;
103106
this.closure = closure;
104107
this.finished = false;
108+
this.iterator = iterator;
109+
this.isPRangeIterator = iterator != null && iterator instanceof PRangeIterator;
105110
}
106111

107112
public FrameDescriptor getFrameDescriptor() {
@@ -137,6 +142,14 @@ public PCell[] getClosure() {
137142
return closure;
138143
}
139144

145+
public Object getIterator() {
146+
return iterator;
147+
}
148+
149+
public boolean isPRangeIterator() {
150+
return isPRangeIterator;
151+
}
152+
140153
@Override
141154
public String toString() {
142155
return "<generator object '" + name + "' at " + hashCode() + ">";

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/iterator/PRangeIterator.java

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2017, 2018, Oracle and/or its affiliates.
2+
* Copyright (c) 2017, 2020, Oracle and/or its affiliates.
33
* Copyright (c) 2013, Regents of the University of California
44
*
55
* All rights reserved.
@@ -25,8 +25,10 @@
2525
*/
2626
package com.oracle.graal.python.builtins.objects.iterator;
2727

28+
import com.oracle.graal.python.builtins.objects.range.PRange;
2829
import com.oracle.graal.python.builtins.objects.type.LazyPythonClass;
2930
import com.oracle.truffle.api.CompilerDirectives;
31+
import com.oracle.truffle.api.profiles.ConditionProfile;
3032

3133
public final class PRangeIterator extends PIntegerIterator {
3234

@@ -53,6 +55,17 @@ public int getStep() {
5355
return step;
5456
}
5557

58+
public int getLength(ConditionProfile stepProfile, ConditionProfile positveRangeProfile) {
59+
if (stepProfile.profile(step > 0)) {
60+
if (positveRangeProfile.profile(index >= 0 && index < stop)) {
61+
return (stop - index) / step;
62+
}
63+
return PRange.getLenOfRange(index, stop, step);
64+
} else {
65+
return PRange.getLenOfRange(stop, index, -step);
66+
}
67+
}
68+
5669
@Override
5770
public int next() {
5871
assert hasNext();

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/list/ListBuiltins.java

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,10 +64,12 @@
6464
import com.oracle.graal.python.builtins.objects.common.SequenceStorageNodes.ListGeneralizationNode;
6565
import com.oracle.graal.python.builtins.objects.function.PArguments;
6666
import com.oracle.graal.python.builtins.objects.function.PArguments.ThreadState;
67+
import com.oracle.graal.python.builtins.objects.generator.PGenerator;
6768
import com.oracle.graal.python.builtins.objects.ints.PInt;
6869
import com.oracle.graal.python.builtins.objects.iterator.PDoubleSequenceIterator;
6970
import com.oracle.graal.python.builtins.objects.iterator.PIntegerSequenceIterator;
7071
import com.oracle.graal.python.builtins.objects.iterator.PLongSequenceIterator;
72+
import com.oracle.graal.python.builtins.objects.iterator.PRangeIterator;
7173
import com.oracle.graal.python.builtins.objects.iterator.PSequenceIterator;
7274
import com.oracle.graal.python.builtins.objects.list.ListBuiltinsFactory.ListReverseNodeFactory;
7375
import com.oracle.graal.python.builtins.objects.object.PythonObjectLibrary;
@@ -81,21 +83,25 @@
8183
import com.oracle.graal.python.nodes.builtins.ListNodes.IndexNode;
8284
import com.oracle.graal.python.nodes.call.special.LookupAndCallUnaryNode;
8385
import com.oracle.graal.python.nodes.control.GetIteratorExpressionNode.GetIteratorNode;
86+
import com.oracle.graal.python.nodes.control.GetNextNode;
8487
import com.oracle.graal.python.nodes.function.PythonBuiltinBaseNode;
8588
import com.oracle.graal.python.nodes.function.PythonBuiltinNode;
8689
import com.oracle.graal.python.nodes.function.builtins.PythonBinaryBuiltinNode;
8790
import com.oracle.graal.python.nodes.function.builtins.PythonTernaryBuiltinNode;
8891
import com.oracle.graal.python.nodes.function.builtins.PythonUnaryBuiltinNode;
8992
import com.oracle.graal.python.nodes.object.GetLazyClassNode;
93+
import com.oracle.graal.python.nodes.object.IsBuiltinClassProfile;
9094
import com.oracle.graal.python.nodes.truffle.PythonArithmeticTypes;
9195
import com.oracle.graal.python.runtime.PythonCore;
96+
import com.oracle.graal.python.runtime.exception.PException;
9297
import com.oracle.graal.python.runtime.exception.PythonErrorType;
9398
import com.oracle.graal.python.runtime.sequence.PSequence;
9499
import com.oracle.graal.python.runtime.sequence.storage.DoubleSequenceStorage;
95100
import com.oracle.graal.python.runtime.sequence.storage.EmptySequenceStorage;
96101
import com.oracle.graal.python.runtime.sequence.storage.IntSequenceStorage;
97102
import com.oracle.graal.python.runtime.sequence.storage.LongSequenceStorage;
98103
import com.oracle.graal.python.runtime.sequence.storage.SequenceStorage;
104+
import com.oracle.graal.python.runtime.sequence.storage.SequenceStorageFactory;
99105
import com.oracle.truffle.api.CompilerDirectives;
100106
import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
101107
import com.oracle.truffle.api.dsl.Cached;
@@ -211,6 +217,38 @@ PNone listRange(PList list, PRange range) {
211217
return PNone.NONE;
212218
}
213219

220+
@Specialization(guards = "iterable.isPRangeIterator()")
221+
PNone listPGenerator(VirtualFrame frame, PList list, PGenerator iterable,
222+
@Cached GetIteratorNode getIteratorNode,
223+
@Cached SequenceStorageNodes.AppendNode appendNode,
224+
@Cached GetNextNode getNextNode,
225+
@Cached IsBuiltinClassProfile errorProfile,
226+
@Cached("createBinaryProfile()") ConditionProfile stepProfile,
227+
@Cached("createBinaryProfile()") ConditionProfile positiveRangeProfile) {
228+
clearStorage(list);
229+
Object iterObj = getIteratorNode.executeWith(frame, iterable);
230+
SequenceStorage storage = EmptySequenceStorage.INSTANCE;
231+
232+
PRangeIterator range = (PRangeIterator) iterable.getIterator();
233+
final int len = range.getLength(stepProfile, positiveRangeProfile);
234+
if (len > 0) {
235+
Object value = getNextNode.execute(frame, iterObj);
236+
storage = SequenceStorageFactory.createStorage(value, len);
237+
storage = appendNode.execute(storage, value, ListGeneralizationNode.SUPPLIER);
238+
while (true) {
239+
try {
240+
storage = appendNode.execute(storage, getNextNode.execute(frame, iterObj), ListGeneralizationNode.SUPPLIER);
241+
} catch (PException e) {
242+
e.expectStopIteration(errorProfile);
243+
break;
244+
}
245+
}
246+
}
247+
248+
list.setSequenceStorage(storage);
249+
return PNone.NONE;
250+
}
251+
214252
@Specialization(guards = {"!isNoValue(iterable)", "!isString(iterable)"})
215253
PNone listIterable(VirtualFrame frame, PList list, Object iterable,
216254
@Cached("create()") GetIteratorNode getIteratorNode,

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/function/GeneratorExpressionNode.java

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2017, 2019, Oracle and/or its affiliates.
2+
* Copyright (c) 2017, 2020, Oracle and/or its affiliates.
33
* Copyright (c) 2013, Regents of the University of California
44
*
55
* All rights reserved.
@@ -126,11 +126,13 @@ public RootNode getFunctionRootNode() {
126126
@Override
127127
public Object execute(VirtualFrame frame) {
128128
Object[] arguments;
129+
Object iterator = null;
129130
if (getIterator == null) {
130131
arguments = PArguments.create(0);
131132
} else {
132133
arguments = PArguments.create(1);
133-
PArguments.setArgument(arguments, 0, getIterator.execute(frame));
134+
iterator = getIterator.execute(frame);
135+
PArguments.setArgument(arguments, 0, iterator);
134136
}
135137
PArguments.setGlobals(arguments, PArguments.getGlobals(frame));
136138

@@ -143,7 +145,7 @@ public Object execute(VirtualFrame frame) {
143145

144146
PCell[] closure = getClosureFromGeneratorOrFunctionLocals(frame);
145147
return factory.createGenerator(name, callTargets, frameDescriptor, arguments, closure, executionCellSlots,
146-
numOfActiveFlags, numOfGeneratorBlockNode, numOfGeneratorForNode);
148+
numOfActiveFlags, numOfGeneratorBlockNode, numOfGeneratorForNode, iterator);
147149
}
148150

149151
@Override

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/generator/GeneratorFunctionRootNode.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2018, 2019, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 2018, 2020, Oracle and/or its affiliates. All rights reserved.
33
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
44
*
55
* The Universal Permissive License (UPL), Version 1.0
@@ -90,7 +90,7 @@ public Object execute(VirtualFrame frame) {
9090
callTargets = createYieldTargets(callTarget);
9191
}
9292
return factory.createGenerator(getName(), callTargets, frameDescriptor, frame.getArguments(), PArguments.getClosure(frame), cellSlots, numOfActiveFlags, numOfGeneratorBlockNode,
93-
numOfGeneratorForNode);
93+
numOfGeneratorForNode, null);
9494
}
9595

9696
public static RootCallTarget[] createYieldTargets(RootCallTarget callTarget) {

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/object/PythonObjectFactory.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -531,9 +531,9 @@ public PDictView createDictItemsView(PHashingCollection dict) {
531531
*/
532532

533533
public PGenerator createGenerator(String name, RootCallTarget[] callTargets, FrameDescriptor frameDescriptor, Object[] arguments, PCell[] closure, ExecutionCellSlots cellSlots,
534-
int numOfActiveFlags, int numOfGeneratorBlockNode, int numOfGeneratorForNode) {
534+
int numOfActiveFlags, int numOfGeneratorBlockNode, int numOfGeneratorForNode, Object iterator) {
535535
return trace(PGenerator.create(PythonBuiltinClassType.PGenerator, name, callTargets, frameDescriptor, arguments, closure, cellSlots, numOfActiveFlags, numOfGeneratorBlockNode,
536-
numOfGeneratorForNode, this));
536+
numOfGeneratorForNode, this, iterator));
537537
}
538538

539539
public PGeneratorFunction createGeneratorFunction(String name, String enclosingClassName, PCode code, PythonObject globals, PCell[] closure, Object[] defaultValues,

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/sequence/storage/SequenceStorageFactory.java

Lines changed: 46 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2017, 2019, Oracle and/or its affiliates.
2+
* Copyright (c) 2017, 2020, Oracle and/or its affiliates.
33
* Copyright (c) 2013, Regents of the University of California
44
*
55
* All rights reserved.
@@ -49,6 +49,8 @@ public static SequenceStorage createStorage(Object[] values) {
4949
return new LongSequenceStorage(specializeToLong(values));
5050
} else if (canSpecializeToBool(values)) {
5151
return new BoolSequenceStorage(specializeToBool(values));
52+
} else if (canSpecializeToByte(values)) {
53+
return new ByteSequenceStorage(specializeToByte(values));
5254
} else if (canSpecializeToList(values)) {
5355
return new ListSequenceStorage(specializeToList(values));
5456
} else if (canSpecializeToTuple(values)) {
@@ -58,6 +60,29 @@ public static SequenceStorage createStorage(Object[] values) {
5860
}
5961
}
6062

63+
public static BasicSequenceStorage createStorage(Object baseValue, int len) {
64+
assert baseValue != null;
65+
66+
if (baseValue instanceof Integer) {
67+
return new IntSequenceStorage(len);
68+
} else if (baseValue instanceof Byte) {
69+
return new ByteSequenceStorage(len);
70+
} else if (baseValue instanceof Long) {
71+
return new LongSequenceStorage(len);
72+
} else if (baseValue instanceof Double) {
73+
return new DoubleSequenceStorage(len);
74+
} else if (baseValue instanceof Boolean) {
75+
return new BoolSequenceStorage(len);
76+
} else if (baseValue instanceof PList) {
77+
return new ListSequenceStorage(len);
78+
} else if (baseValue instanceof PTuple) {
79+
return new TupleSequenceStorage(len);
80+
} else {
81+
return new ObjectSequenceStorage(len);
82+
}
83+
84+
}
85+
6186
public static boolean canSpecializeToInt(Object[] values) {
6287
for (Object item : values) {
6388
if (!(item instanceof Integer)) {
@@ -78,6 +103,26 @@ public static int[] specializeToInt(Object[] values) {
78103
return intVals;
79104
}
80105

106+
public static boolean canSpecializeToByte(Object[] values) {
107+
for (Object item : values) {
108+
if (!(item instanceof Byte)) {
109+
return false;
110+
}
111+
}
112+
113+
return true;
114+
}
115+
116+
public static byte[] specializeToByte(Object[] values) {
117+
final byte[] byteVals = new byte[values.length];
118+
119+
for (int i = 0; i < values.length; i++) {
120+
byteVals[i] = (byte) values[i];
121+
}
122+
123+
return byteVals;
124+
}
125+
81126
public static boolean canSpecializeToLong(Object[] values) {
82127
for (Object item : values) {
83128
if (!(item instanceof Long || item instanceof Integer)) {

0 commit comments

Comments
 (0)