Skip to content

Commit b402916

Browse files
committed
same id for empty tuples / frozensets / bytes objects
- added relevant unittests
1 parent 6af95f0 commit b402916

File tree

6 files changed

+66
-14
lines changed

6 files changed

+66
-14
lines changed

graalpython/com.oracle.graal.python.test/src/tests/test_bytes.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -436,3 +436,8 @@ def test_find():
436436
assert b.find(i, 6) == 7
437437
assert b.find(i, 1, 3) == 1
438438
assert b.find(w, 1, 3) == -1
439+
440+
441+
def test_same_id():
442+
empty_ids = set([id(bytes()) for i in range(100)])
443+
assert len(empty_ids) == 1

graalpython/com.oracle.graal.python.test/src/tests/test_set.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -210,3 +210,8 @@ def test_intersection():
210210
# assert id(s) == id(z)
211211
# else:
212212
# assert id(s) != id(z)
213+
214+
215+
def test_same_id():
216+
empty_ids = set([id(frozenset()) for i in range(100)])
217+
assert len(empty_ids) == 1

graalpython/com.oracle.graal.python.test/src/tests/test_tuple.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@
33
#
44
# Licensed under the PYTHON SOFTWARE FOUNDATION LICENSE VERSION 2
55
import seq_tests
6-
import unittest
76
#import pickle
87
from compare import CompareTest
98

@@ -374,3 +373,8 @@ def test_slice(self):
374373
t1 = tuple(range (1, 22, 2))
375374
s = slice(2, 6)
376375
self.assertEqual(t1[s], (5, 7, 9, 11))
376+
377+
378+
def test_same_id():
379+
empty_ids = set([id(tuple()) for i in range(100)])
380+
assert len(empty_ids) == 1

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/BuiltinConstructors.java

Lines changed: 22 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@
4444
import static com.oracle.graal.python.nodes.BuiltinNames.TUPLE;
4545
import static com.oracle.graal.python.nodes.BuiltinNames.TYPE;
4646
import static com.oracle.graal.python.nodes.BuiltinNames.ZIP;
47+
import static com.oracle.graal.python.nodes.HiddenAttributes.ID_KEY;
4748
import static com.oracle.graal.python.nodes.SpecialAttributeNames.__FILE__;
4849
import static com.oracle.graal.python.runtime.exception.PythonErrorType.NotImplementedError;
4950
import static com.oracle.graal.python.runtime.exception.PythonErrorType.OverflowError;
@@ -169,9 +170,17 @@ protected List<com.oracle.truffle.api.dsl.NodeFactory<? extends PythonBuiltinBas
169170
@GenerateNodeFactory
170171
public abstract static class BytesNode extends PythonBuiltinNode {
171172

172-
@Specialization
173-
public PBytes bytes(PythonClass cls, @SuppressWarnings("unused") PNone source, @SuppressWarnings("unused") PNone encoding, @SuppressWarnings("unused") PNone errors) {
174-
return factory().createBytes(cls, new byte[0]);
173+
protected long getEmptyId() {
174+
return getContext().getEmptyBytesId();
175+
}
176+
177+
@Specialization(guards = "isNoValue(source)")
178+
public PBytes bytes(PythonClass cls, @SuppressWarnings("unused") PNone source, @SuppressWarnings("unused") PNone encoding, @SuppressWarnings("unused") PNone errors,
179+
@Cached("create()") WriteAttributeToObjectNode writeId,
180+
@Cached("getEmptyId()") long emptyId) {
181+
PBytes emptyBytes = factory().createBytes(cls, new byte[0]);
182+
writeId.execute(emptyBytes, ID_KEY, emptyId);
183+
return emptyBytes;
175184
}
176185

177186
@Specialization
@@ -553,9 +562,17 @@ public abstract static class FrozenSetNode extends PythonBuiltinNode {
553562

554563
@Child private HashingStorageNodes.SetItemNode setItemNode;
555564

565+
protected long getEmptyId() {
566+
return getContext().getEmptyFrozenSetId();
567+
}
568+
556569
@Specialization(guards = "isNoValue(arg)")
557-
public PFrozenSet frozensetEmpty(PythonClass cls, @SuppressWarnings("unused") PNone arg) {
558-
return factory().createFrozenSet(cls);
570+
public PFrozenSet frozensetEmpty(PythonClass cls, @SuppressWarnings("unused") PNone arg,
571+
@Cached("create()") WriteAttributeToObjectNode writeId,
572+
@Cached("getEmptyId()") long emptyId) {
573+
PFrozenSet frozenSet = factory().createFrozenSet(cls);
574+
writeId.execute(frozenSet, ID_KEY, emptyId);
575+
return frozenSet;
559576
}
560577

561578
@Specialization

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/builtins/TupleNodes.java

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,8 @@
4040
*/
4141
package com.oracle.graal.python.nodes.builtins;
4242

43+
import static com.oracle.graal.python.nodes.HiddenAttributes.ID_KEY;
44+
4345
import java.util.ArrayList;
4446
import java.util.List;
4547

@@ -50,6 +52,7 @@
5052
import com.oracle.graal.python.nodes.PBaseNode;
5153
import com.oracle.graal.python.nodes.PGuards;
5254
import com.oracle.graal.python.nodes.SpecialMethodNames;
55+
import com.oracle.graal.python.nodes.attributes.WriteAttributeToObjectNode;
5356
import com.oracle.graal.python.nodes.control.GetIteratorNode;
5457
import com.oracle.graal.python.nodes.control.GetNextNode;
5558
import com.oracle.graal.python.nodes.object.GetClassNode;
@@ -84,10 +87,17 @@ public final PTuple execute(Object value) {
8487

8588
public abstract PTuple execute(Object cls, Object value);
8689

90+
protected long getEmptyId() {
91+
return getContext().getEmptyTupleId();
92+
}
93+
8794
@Specialization(guards = "isNoValue(none)")
88-
@SuppressWarnings("unused")
89-
public PTuple tuple(PythonClass cls, PNone none) {
90-
return factory().createEmptyTuple(cls);
95+
public PTuple tuple(PythonClass cls, @SuppressWarnings("unused") PNone none,
96+
@Cached("create()") WriteAttributeToObjectNode writeId,
97+
@Cached("getEmptyId()") long emptyId) {
98+
PTuple emptyTuple = factory().createEmptyTuple(cls);
99+
writeId.execute(emptyTuple, ID_KEY, emptyId);
100+
return emptyTuple;
91101
}
92102

93103
@Specialization

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/PythonContext.java

Lines changed: 16 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -58,14 +58,13 @@ public class PythonContext {
5858
private final HashMap<Object, CallTarget> atExitHooks = new HashMap<>();
5959
private final AtomicLong globalId = new AtomicLong(Integer.MAX_VALUE * 2L + 4L);
6060

61-
enum PythonBuiltinImmutableType {
61+
public enum PythonImmutableBuiltinType {
6262
PFrozenSet,
6363
PTuple,
64-
PBytes,
65-
PString
64+
PBytes
6665
}
6766

68-
private final long[] emptyImmutableObjectsIdCache = new long[PythonBuiltinImmutableType.values().length];
67+
private final long[] emptyImmutableObjectsIdCache = new long[PythonImmutableBuiltinType.values().length];
6968

7069
@CompilationFinal private TruffleLanguage.Env env;
7170

@@ -100,7 +99,19 @@ public PythonContext(PythonLanguage language, TruffleLanguage.Env env, PythonCor
10099
}
101100
}
102101

103-
public long getEmptyImmutableObjectGlobalId(PythonBuiltinImmutableType immutableType) {
102+
public long getEmptyFrozenSetId() {
103+
return getEmptyImmutableObjectGlobalId(PythonImmutableBuiltinType.PFrozenSet);
104+
}
105+
106+
public long getEmptyTupleId() {
107+
return getEmptyImmutableObjectGlobalId(PythonImmutableBuiltinType.PTuple);
108+
}
109+
110+
public long getEmptyBytesId() {
111+
return getEmptyImmutableObjectGlobalId(PythonImmutableBuiltinType.PBytes);
112+
}
113+
114+
private long getEmptyImmutableObjectGlobalId(PythonImmutableBuiltinType immutableType) {
104115
int idx = immutableType.ordinal();
105116
if (emptyImmutableObjectsIdCache[idx] == 0) {
106117
synchronized (emptyImmutableObjectsIdCache) {

0 commit comments

Comments
 (0)