Skip to content

Commit 636f280

Browse files
committed
[GR-19973] Improve list overallocation
PullRequest: graalpython/865
2 parents 4151920 + 253d83a commit 636f280

25 files changed

+332
-269
lines changed

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

Lines changed: 122 additions & 166 deletions
Large diffs are not rendered by default.

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/BasicSequenceStorage.java

Lines changed: 5 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.
@@ -27,6 +27,10 @@
2727

2828
public abstract class BasicSequenceStorage extends SequenceStorage {
2929

30+
public BasicSequenceStorage(ListStorageType type) {
31+
super(type);
32+
}
33+
3034
// nominated storage length
3135
protected int length;
3236

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

Lines changed: 4 additions & 6 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.
@@ -32,6 +32,7 @@ public final class BoolSequenceStorage extends TypedSequenceStorage {
3232
private boolean[] values;
3333

3434
public BoolSequenceStorage() {
35+
super(ListStorageType.Boolean);
3536
values = new boolean[]{};
3637
}
3738

@@ -40,12 +41,14 @@ public BoolSequenceStorage(boolean[] elements) {
4041
}
4142

4243
public BoolSequenceStorage(boolean[] elements, int length) {
44+
super(ListStorageType.Boolean);
4345
this.values = elements;
4446
this.capacity = values.length;
4547
this.length = length;
4648
}
4749

4850
public BoolSequenceStorage(int capacity) {
51+
super(ListStorageType.Boolean);
4952
this.values = new boolean[capacity];
5053
this.capacity = capacity;
5154
this.length = 0;
@@ -259,9 +262,4 @@ public Object getCopyOfInternalArrayObject() {
259262
public void setInternalArrayObject(Object arrayObject) {
260263
this.values = (boolean[]) arrayObject;
261264
}
262-
263-
@Override
264-
public ListStorageType getElementType() {
265-
return ListStorageType.Boolean;
266-
}
267265
}

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

Lines changed: 3 additions & 6 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.
@@ -44,12 +44,14 @@ public ByteSequenceStorage(byte[] elements) {
4444
}
4545

4646
public ByteSequenceStorage(byte[] elements, int length) {
47+
super(ListStorageType.Byte);
4748
this.values = elements;
4849
this.capacity = values.length;
4950
this.length = length;
5051
}
5152

5253
public ByteSequenceStorage(int capacity) {
54+
super(ListStorageType.Byte);
5355
this.values = new byte[capacity];
5456
this.capacity = capacity;
5557
this.length = 0;
@@ -366,9 +368,4 @@ public Object getCopyOfInternalArrayObject() {
366368
public void setInternalArrayObject(Object arrayObject) {
367369
this.values = (byte[]) arrayObject;
368370
}
369-
370-
@Override
371-
public ListStorageType getElementType() {
372-
return ListStorageType.Byte;
373-
}
374371
}

0 commit comments

Comments
 (0)