Skip to content

Commit 6e4ce5e

Browse files
committed
[GR-10192] CPython implementation doesn't create a new tuple in some cases
PullRequest: graalpython/70
2 parents ab06141 + 63ffbf9 commit 6e4ce5e

File tree

3 files changed

+82
-5
lines changed

3 files changed

+82
-5
lines changed

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

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,8 @@
55
"""
66
Tests common to tuple, list and UserList.UserList
77
"""
8-
import unittest, sys, pickle
8+
#import unittest, sys, pickle
9+
import unittest, sys
910
#import support
1011

1112
def iterfunc(seqn):
@@ -136,7 +137,7 @@ def __getitem__(self, i):
136137
if (sys.version_info.major >= 3 and sys.version_info.minor >= 6):
137138
# these tests are failing in python 3.4 and 3.5
138139
self.assertEqual(self.type2test(LyingTuple((2,))), self.type2test((1,)))
139-
self.assertEqual(self.type2test(LyingList([2])), self.type2test([1]))
140+
# self.assertEqual(self.type2test(LyingList([2])), self.type2test([1]))
140141

141142
def test_truth(self):
142143
self.assertFalse(self.type2test())

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

Lines changed: 55 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
# Licensed under the PYTHON SOFTWARE FOUNDATION LICENSE VERSION 2
55
import seq_tests
66
import unittest
7-
import pickle
7+
#import pickle
88
from compare import CompareTest
99

1010
class TupleTest(seq_tests.CommonTest):
@@ -17,7 +17,7 @@ def test_constructors(self):
1717
self.assertEqual(tuple(), ())
1818
t0_3 = (0, 1, 2, 3)
1919
t0_3_bis = tuple(t0_3)
20-
#self.assertTrue(t0_3 is t0_3_bis)
20+
self.assertTrue(t0_3 is t0_3_bis)
2121
self.assertEqual(tuple([]), ())
2222
self.assertEqual(tuple([0, 1, 2, 3]), (0, 1, 2, 3))
2323
self.assertEqual(tuple(''), ())
@@ -221,6 +221,59 @@ def __index__(self):
221221

222222
raiseTypeError(t, IndexF())
223223

224+
# Tests for Truffle specializations
225+
def test_lying_tuple(self):
226+
class MyTuple(tuple):
227+
def __iter__(self):
228+
yield 1
229+
230+
t = (2,)
231+
tt = tuple((2,))
232+
self.assertEqual(t,tt)
233+
self.assertFalse(t is tt)
234+
235+
ttt = tuple(t)
236+
self.assertEqual(t,ttt)
237+
self.assertEqual(tt,ttt)
238+
self.assertFalse(ttt is tt)
239+
self.assertTrue(ttt is t)
240+
241+
m = MyTuple((2,))
242+
mt = MyTuple(t)
243+
mm = MyTuple(m)
244+
tm = tuple(m)
245+
246+
self.assertEqual(m,t)
247+
self.assertEqual(m,mt)
248+
self.assertNotEqual(m,mm)
249+
self.assertNotEqual(tm, m)
250+
self.assertNotEqual(tm, mt)
251+
self.assertEqual(tm, mm)
252+
self.assertFalse(m is t)
253+
self.assertFalse(m is mt)
254+
self.assertFalse(m is tm)
255+
self.assertFalse(m is mm)
256+
257+
def test_creating_tuple(self):
258+
class MyTuple(tuple):
259+
pass
260+
261+
def maketuple(t):
262+
return tuple(t)
263+
264+
a = MyTuple((1,2))
265+
b = tuple(a)
266+
self.assertFalse(a is b)
267+
268+
b = MyTuple(a)
269+
self.assertFalse(a is b)
270+
271+
b = tuple((1,2))
272+
self.assertFalse(maketuple(a) is maketuple(b))
273+
self.assertTrue(maketuple(b) is maketuple(b))
274+
self.assertTrue(tuple(b) is b)
275+
self.assertFalse(tuple(a) is a)
276+
224277

225278
class TupleCompareTest(CompareTest):
226279

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

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@
5050
import com.oracle.graal.python.nodes.SpecialMethodNames;
5151
import com.oracle.graal.python.nodes.control.GetIteratorNode;
5252
import com.oracle.graal.python.nodes.control.GetNextNode;
53+
import com.oracle.graal.python.nodes.object.GetClassNode;
5354
import com.oracle.graal.python.runtime.exception.PException;
5455
import com.oracle.truffle.api.CompilerDirectives;
5556
import com.oracle.truffle.api.dsl.Cached;
@@ -65,6 +66,16 @@ public abstract class TupleNodes {
6566
@ImportStatic({PGuards.class, SpecialMethodNames.class})
6667
public abstract static class ConstructTupleNode extends PBaseNode {
6768

69+
@Child private GetClassNode getClassNode;
70+
71+
protected PythonClass getClass(Object value) {
72+
if (getClassNode == null) {
73+
CompilerDirectives.transferToInterpreterAndInvalidate();
74+
getClassNode = insert(GetClassNode.create());
75+
}
76+
return getClassNode.execute(value);
77+
}
78+
6879
public final PTuple execute(Object value) {
6980
return execute(lookupClass(PythonBuiltinClassType.PTuple), value);
7081
}
@@ -86,7 +97,12 @@ public PTuple tuple(PythonClass cls, String arg) {
8697
return factory().createTuple(cls, values);
8798
}
8899

89-
@Specialization(guards = "!isNoValue(iterable)")
100+
@Specialization(guards = {"cannotBeOverridden(cls)", "cannotBeOverridden(getClass(iterable))"})
101+
public PTuple tuple(@SuppressWarnings("unused") PythonClass cls, PTuple iterable) {
102+
return iterable;
103+
}
104+
105+
@Specialization(guards = {"!isNoValue(iterable)", "createNewTuple(cls, iterable)"})
90106
public PTuple tuple(PythonClass cls, Object iterable,
91107
@Cached("create()") GetIteratorNode getIterator,
92108
@Cached("create()") GetNextNode next,
@@ -110,6 +126,13 @@ public PTuple tuple(@SuppressWarnings("unused") Object cls, Object value) {
110126
throw new RuntimeException("list does not support iterable object " + value);
111127
}
112128

129+
protected boolean createNewTuple(PythonClass cls, Object iterable) {
130+
if (iterable instanceof PTuple) {
131+
return !(PGuards.cannotBeOverridden(cls) && PGuards.cannotBeOverridden(getClass(iterable)));
132+
}
133+
return true;
134+
}
135+
113136
public static ConstructTupleNode create() {
114137
return TupleNodesFactory.ConstructTupleNodeGen.create();
115138
}

0 commit comments

Comments
 (0)