Skip to content

Commit bb2f85c

Browse files
committed
builtin ID function: add specializations for empty instances of the builtin immutable types: tuple / frozenset / bytes
1 parent afc2486 commit bb2f85c

File tree

7 files changed

+105
-65
lines changed

7 files changed

+105
-65
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
/*
2+
* Copyright (c) 2017, Oracle and/or its affiliates.
3+
*
4+
* The Universal Permissive License (UPL), Version 1.0
5+
*
6+
* Subject to the condition set forth below, permission is hereby granted to any
7+
* person obtaining a copy of this software, associated documentation and/or data
8+
* (collectively the "Software"), free of charge and under any and all copyright
9+
* rights in the Software, and any and all patent rights owned or freely
10+
* licensable by each licensor hereunder covering either (i) the unmodified
11+
* Software as contributed to or provided by such licensor, or (ii) the Larger
12+
* Works (as defined below), to deal in both
13+
*
14+
* (a) the Software, and
15+
* (b) any piece of software and/or hardware listed in the lrgrwrks.txt file if
16+
* one is included with the Software (each a "Larger Work" to which the
17+
* Software is contributed by such licensors),
18+
*
19+
* without restriction, including without limitation the rights to copy, create
20+
* derivative works of, display, perform, and distribute the Software and make,
21+
* use, sell, offer for sale, import, export, have made, and have sold the
22+
* Software and the Larger Work(s), and to sublicense the foregoing rights on
23+
* either these or other terms.
24+
*
25+
* This license is subject to the following condition:
26+
*
27+
* The above copyright notice and either this complete permission notice or at a
28+
* minimum a reference to the UPL must be included in all copies or substantial
29+
* portions of the Software.
30+
*
31+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
32+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
33+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
34+
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
35+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
36+
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
37+
* SOFTWARE.
38+
*/
39+
package com.oracle.graal.python.builtins;
40+
41+
public enum PythonImmutableBuiltinType {
42+
PFrozenSet,
43+
PTuple,
44+
PBytes
45+
}

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

Lines changed: 4 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,6 @@
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;
4847
import static com.oracle.graal.python.nodes.SpecialAttributeNames.__FILE__;
4948
import static com.oracle.graal.python.runtime.exception.PythonErrorType.NotImplementedError;
5049
import static com.oracle.graal.python.runtime.exception.PythonErrorType.OverflowError;
@@ -170,17 +169,9 @@ protected List<com.oracle.truffle.api.dsl.NodeFactory<? extends PythonBuiltinBas
170169
@GenerateNodeFactory
171170
public abstract static class BytesNode extends PythonBuiltinNode {
172171

173-
protected long getEmptyId() {
174-
return getContext().getEmptyBytesId();
175-
}
176-
177172
@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;
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]);
184175
}
185176

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

563554
@Child private HashingStorageNodes.SetItemNode setItemNode;
564555

565-
protected long getEmptyId() {
566-
return getContext().getEmptyFrozenSetId();
567-
}
568-
569556
@Specialization(guards = "isNoValue(arg)")
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;
557+
public PFrozenSet frozensetEmpty(PythonClass cls, @SuppressWarnings("unused") PNone arg) {
558+
return factory().createFrozenSet(cls);
576559
}
577560

578561
@Specialization

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

Lines changed: 33 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,7 @@
7575
import com.oracle.graal.python.builtins.Builtin;
7676
import com.oracle.graal.python.builtins.CoreFunctions;
7777
import com.oracle.graal.python.builtins.PythonBuiltins;
78+
import com.oracle.graal.python.builtins.PythonImmutableBuiltinType;
7879
import com.oracle.graal.python.builtins.objects.PNone;
7980
import com.oracle.graal.python.builtins.objects.PNotImplemented;
8081
import com.oracle.graal.python.builtins.objects.bytes.PBytes;
@@ -88,6 +89,7 @@
8889
import com.oracle.graal.python.builtins.objects.list.PList;
8990
import com.oracle.graal.python.builtins.objects.module.PythonModule;
9091
import com.oracle.graal.python.builtins.objects.object.PythonObject;
92+
import com.oracle.graal.python.builtins.objects.set.PFrozenSet;
9193
import com.oracle.graal.python.builtins.objects.str.PString;
9294
import com.oracle.graal.python.builtins.objects.tuple.PTuple;
9395
import com.oracle.graal.python.builtins.objects.type.PythonClass;
@@ -688,7 +690,28 @@ int doId(double value) {
688690
return Double.hashCode(value);
689691
}
690692

691-
@Specialization(guards = {"!isPInt(obj)", "!isPString(obj)", "!isPFloat(obj)"})
693+
@Specialization(guards = "isEmpty(value)")
694+
Object doEmptyTuple(PTuple value) {
695+
return getId(value, PythonImmutableBuiltinType.PTuple);
696+
}
697+
698+
@Specialization(guards = "isEmpty(value)")
699+
Object doEmptyBytes(PBytes value) {
700+
return getId(value, PythonImmutableBuiltinType.PBytes);
701+
}
702+
703+
@Specialization(guards = "isEmpty(value)")
704+
Object doEmptyFrozenSet(PFrozenSet value) {
705+
return getId(value, PythonImmutableBuiltinType.PFrozenSet);
706+
}
707+
708+
protected boolean isEmptyImmutableBuiltin(Object object) {
709+
return (object instanceof PTuple && PGuards.isEmpty((PTuple) object)) ||
710+
(object instanceof PBytes && PGuards.isEmpty((PBytes) object)) ||
711+
(object instanceof PFrozenSet && PGuards.isEmpty((PFrozenSet) object));
712+
}
713+
714+
@Specialization(guards = {"!isPInt(obj)", "!isPString(obj)", "!isPFloat(obj)", "!isEmptyImmutableBuiltin(obj)"})
692715
Object doId(PythonObject obj) {
693716
return getId(obj);
694717
}
@@ -699,14 +722,22 @@ Object doId(Object obj) {
699722
}
700723

701724
private Object getId(PythonObject obj) {
725+
return getId(obj, null);
726+
}
727+
728+
private Object getId(PythonObject obj, PythonImmutableBuiltinType immutableType) {
702729
if (readId == null) {
703730
CompilerDirectives.transferToInterpreterAndInvalidate();
704731
readId = insert(ReadAttributeFromObjectNode.create());
705732
writeId = insert(WriteAttributeToObjectNode.create());
706733
}
707734
Object id = readId.execute(obj, ID_KEY);
708735
if (id == NO_VALUE) {
709-
id = getContext().getNextGlobalId();
736+
if (immutableType != null) {
737+
id = getContext().getEmptyImmutableObjectGlobalId(immutableType);
738+
} else {
739+
id = getContext().getNextGlobalId();
740+
}
710741
writeId.execute(obj, ID_KEY, id);
711742
}
712743
return id;

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/PGuards.java

Lines changed: 16 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@
4242

4343
import com.oracle.graal.python.builtins.objects.PNone;
4444
import com.oracle.graal.python.builtins.objects.PythonAbstractObject;
45+
import com.oracle.graal.python.builtins.objects.array.PArray;
4546
import com.oracle.graal.python.builtins.objects.bytes.PByteArray;
4647
import com.oracle.graal.python.builtins.objects.bytes.PBytes;
4748
import com.oracle.graal.python.builtins.objects.cext.PythonNativeClass;
@@ -90,6 +91,14 @@ public static boolean isEmpty(PBaseSet set) {
9091
return set.size() == 0;
9192
}
9293

94+
public static boolean isEmpty(PTuple tuple) {
95+
return tuple.isEmpty();
96+
}
97+
98+
public static boolean isEmpty(PBytes bytes) {
99+
return bytes.len() == 0;
100+
}
101+
93102
public static boolean isNone(Object value) {
94103
return value == PNone.NONE;
95104
}
@@ -106,11 +115,11 @@ public static boolean isClass(Object value) {
106115
return value instanceof PythonClass;
107116
}
108117

109-
public static boolean isEmptyStorage(PList list) {
110-
return list.getSequenceStorage() instanceof EmptySequenceStorage;
118+
public static boolean isEmptyStorage(PSequence seq) {
119+
return seq.getSequenceStorage() instanceof EmptySequenceStorage;
111120
}
112121

113-
public static boolean isEmptyStorage(PByteArray byteArray) {
122+
public static boolean isEmptyStorage(PArray byteArray) {
114123
return byteArray.getSequenceStorage() instanceof EmptySequenceStorage;
115124
}
116125

@@ -122,12 +131,12 @@ public static boolean isIntStorage(PList list) {
122131
return list.getSequenceStorage() instanceof IntSequenceStorage;
123132
}
124133

125-
public static boolean isIntStorage(PByteArray byteArray) {
126-
return byteArray.getSequenceStorage() instanceof IntSequenceStorage;
134+
public static boolean isIntStorage(PArray array) {
135+
return array.getSequenceStorage() instanceof IntSequenceStorage;
127136
}
128137

129-
public static boolean isByteStorage(PByteArray byteArray) {
130-
return byteArray.getSequenceStorage() instanceof ByteSequenceStorage;
138+
public static boolean isByteStorage(PArray array) {
139+
return array.getSequenceStorage() instanceof ByteSequenceStorage;
131140
}
132141

133142
public static boolean areBothIntStorage(PSequence first, PSequence second) {

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/argument/positional/ExecutePositionalStarargsNode.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -119,9 +119,9 @@ Object[] starargs(PNone none) {
119119

120120
@Specialization
121121
Object[] starargs(Object object,
122-
@Cached("create()") GetIteratorNode getIterator,
123-
@Cached("create()") GetNextNode next,
124-
@Cached("createBinaryProfile()") ConditionProfile errorProfile) {
122+
@Cached("create()") GetIteratorNode getIterator,
123+
@Cached("create()") GetNextNode next,
124+
@Cached("createBinaryProfile()") ConditionProfile errorProfile) {
125125
Object iterator = getIterator.executeWith(object);
126126
if (iterator != PNone.NO_VALUE && iterator != PNone.NONE) {
127127
List<Object> internalStorage = new ArrayList<>();

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

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

43-
import static com.oracle.graal.python.nodes.HiddenAttributes.ID_KEY;
44-
4543
import java.util.ArrayList;
4644
import java.util.List;
4745

@@ -52,7 +50,6 @@
5250
import com.oracle.graal.python.nodes.PBaseNode;
5351
import com.oracle.graal.python.nodes.PGuards;
5452
import com.oracle.graal.python.nodes.SpecialMethodNames;
55-
import com.oracle.graal.python.nodes.attributes.WriteAttributeToObjectNode;
5653
import com.oracle.graal.python.nodes.control.GetIteratorNode;
5754
import com.oracle.graal.python.nodes.control.GetNextNode;
5855
import com.oracle.graal.python.nodes.object.GetClassNode;
@@ -87,17 +84,9 @@ public final PTuple execute(Object value) {
8784

8885
public abstract PTuple execute(Object cls, Object value);
8986

90-
protected long getEmptyId() {
91-
return getContext().getEmptyTupleId();
92-
}
93-
9487
@Specialization(guards = "isNoValue(none)")
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;
88+
public PTuple tuple(PythonClass cls, @SuppressWarnings("unused") PNone none) {
89+
return factory().createEmptyTuple(cls);
10190
}
10291

10392
@Specialization

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

Lines changed: 2 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@
3737
import org.graalvm.options.OptionValues;
3838

3939
import com.oracle.graal.python.PythonLanguage;
40+
import com.oracle.graal.python.builtins.PythonImmutableBuiltinType;
4041
import com.oracle.graal.python.builtins.objects.common.HashingStorage;
4142
import com.oracle.graal.python.builtins.objects.dict.PDict;
4243
import com.oracle.graal.python.builtins.objects.module.PythonModule;
@@ -58,12 +59,6 @@ public class PythonContext {
5859
private final HashMap<Object, CallTarget> atExitHooks = new HashMap<>();
5960
private final AtomicLong globalId = new AtomicLong(Integer.MAX_VALUE * 2L + 4L);
6061

61-
public enum PythonImmutableBuiltinType {
62-
PFrozenSet,
63-
PTuple,
64-
PBytes
65-
}
66-
6762
private final long[] emptyImmutableObjectsIdCache = new long[PythonImmutableBuiltinType.values().length];
6863

6964
@CompilationFinal private TruffleLanguage.Env env;
@@ -99,19 +94,7 @@ public PythonContext(PythonLanguage language, TruffleLanguage.Env env, PythonCor
9994
}
10095
}
10196

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) {
97+
public long getEmptyImmutableObjectGlobalId(PythonImmutableBuiltinType immutableType) {
11598
int idx = immutableType.ordinal();
11699
if (emptyImmutableObjectsIdCache[idx] == 0) {
117100
synchronized (emptyImmutableObjectsIdCache) {

0 commit comments

Comments
 (0)