Skip to content

Commit 2d2970f

Browse files
committed
better dict literal construction
1 parent a767343 commit 2d2970f

File tree

3 files changed

+127
-45
lines changed

3 files changed

+127
-45
lines changed

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

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,10 @@ public Shape getStoreShape() {
113113
return store.getShape();
114114
}
115115

116+
public DynamicObject getStore() {
117+
return store;
118+
}
119+
116120
protected static Object[] keyArray(DynamicObjectStorage self) {
117121
return DynamicObjectStorage.keyArray(self.store.getShape());
118122
}

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

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,7 @@
7676
import com.oracle.graal.python.nodes.literal.BooleanLiteralNode;
7777
import com.oracle.graal.python.nodes.literal.BuiltinsLiteralNode;
7878
import com.oracle.graal.python.nodes.literal.BytesLiteralNode;
79-
import com.oracle.graal.python.nodes.literal.DictLiteralNodeFactory;
79+
import com.oracle.graal.python.nodes.literal.DictLiteralNode;
8080
import com.oracle.graal.python.nodes.literal.DoubleLiteralNode;
8181
import com.oracle.graal.python.nodes.literal.FormatStringLiteralNode;
8282
import com.oracle.graal.python.nodes.literal.IntegerLiteralNode;
@@ -245,11 +245,11 @@ public ExpressionNode createBytesLiteral(byte[] value) {
245245
}
246246

247247
public ExpressionNode createDictLiteral() {
248-
return DictLiteralNodeFactory.create(new ExpressionNode[0], new ExpressionNode[0]);
248+
return DictLiteralNode.create(new ExpressionNode[0], new ExpressionNode[0]);
249249
}
250250

251251
public ExpressionNode createDictLiteral(ExpressionNode[] keys, ExpressionNode[] values) {
252-
return DictLiteralNodeFactory.create(keys, values);
252+
return DictLiteralNode.create(keys, values);
253253
}
254254

255255
public TupleLiteralNode createTupleLiteral(ExpressionNode... values) {

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/literal/DictLiteralNode.java

Lines changed: 120 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -26,73 +26,151 @@
2626
package com.oracle.graal.python.nodes.literal;
2727

2828
import com.oracle.graal.python.PythonLanguage;
29+
import com.oracle.graal.python.builtins.objects.common.DynamicObjectStorage;
30+
import com.oracle.graal.python.builtins.objects.common.EmptyStorage;
2931
import com.oracle.graal.python.builtins.objects.common.HashingStorage;
3032
import com.oracle.graal.python.builtins.objects.common.HashingStorageLibrary;
3133
import com.oracle.graal.python.builtins.objects.dict.PDict;
3234
import com.oracle.graal.python.nodes.expression.ExpressionNode;
35+
import com.oracle.graal.python.nodes.literal.DictLiteralNodeFactory.DynamicDictLiteralNodeGen;
36+
import com.oracle.graal.python.nodes.literal.DictLiteralNodeFactory.FixedDictLiteralNodeGen;
3337
import com.oracle.graal.python.runtime.object.PythonObjectFactory;
38+
import com.oracle.truffle.api.CompilerDirectives;
39+
import com.oracle.truffle.api.CompilerDirectives.CompilationFinal;
3440
import com.oracle.truffle.api.dsl.Cached;
3541
import com.oracle.truffle.api.dsl.CachedLanguage;
36-
import com.oracle.truffle.api.dsl.GenerateNodeFactory;
3742
import com.oracle.truffle.api.dsl.Specialization;
3843
import com.oracle.truffle.api.frame.VirtualFrame;
39-
import com.oracle.truffle.api.library.CachedLibrary;
4044
import com.oracle.truffle.api.nodes.ExplodeLoop;
45+
import com.oracle.truffle.api.object.DynamicObject;
46+
import com.oracle.truffle.api.object.DynamicObjectLibrary;
4147
import com.oracle.truffle.api.profiles.ConditionProfile;
4248

43-
@GenerateNodeFactory
44-
public abstract class DictLiteralNode extends LiteralNode {
45-
@Child private PythonObjectFactory factory = PythonObjectFactory.create();
46-
@Children private final ExpressionNode[] keys;
47-
@Children private final ExpressionNode[] values;
49+
public abstract class DictLiteralNode {
4850

49-
protected DictLiteralNode(ExpressionNode[] keys, ExpressionNode[] values) {
50-
this.keys = keys;
51-
this.values = values;
52-
assert keys.length == values.length;
51+
abstract static class FixedDictLiteralNode extends LiteralNode {
52+
53+
@Child private PythonObjectFactory factory = PythonObjectFactory.create();
54+
@Children private final ExpressionNode[] values;
55+
@Children private final DynamicObjectLibrary[] libs;
56+
57+
@CompilationFinal(dimensions = 1) private final String[] keys;
58+
59+
protected FixedDictLiteralNode(ExpressionNode[] keys, ExpressionNode[] values) {
60+
this.keys = new String[keys.length];
61+
for (int i = 0; i < keys.length; i++) {
62+
this.keys[i] = ((StringLiteralNode) keys[i]).getValue();
63+
}
64+
this.values = values;
65+
this.libs = new DynamicObjectLibrary[keys.length];
66+
}
67+
68+
@Specialization
69+
@ExplodeLoop
70+
public PDict create(VirtualFrame frame,
71+
@CachedLanguage PythonLanguage lang) {
72+
DynamicObjectStorage dictStorage = new DynamicObjectStorage(lang);
73+
DynamicObject storage = dictStorage.getStore();
74+
for (int i = 0; i < values.length; i++) {
75+
Object value = values[i].execute(frame);
76+
DynamicObjectLibrary lib = libs[i];
77+
if (lib == null) {
78+
CompilerDirectives.transferToInterpreterAndInvalidate();
79+
libs[i] = lib = insert(DynamicObjectLibrary.getFactory().create(storage));
80+
}
81+
if (!lib.accepts(storage)) {
82+
CompilerDirectives.transferToInterpreterAndInvalidate();
83+
libs[i] = lib = insert(DynamicObjectLibrary.getFactory().createDispatched(2));
84+
}
85+
lib.put(storage, keys[i], value);
86+
}
87+
return factory.createDict(dictStorage);
88+
}
5389
}
5490

55-
static final class Keys {
56-
public final Object[] keys;
57-
public final boolean allStrings;
91+
abstract static class DynamicDictLiteralNode extends LiteralNode {
5892

59-
Keys(Object[] keys, boolean allStrings) {
93+
@Child private PythonObjectFactory factory = PythonObjectFactory.create();
94+
@Children private final ExpressionNode[] keys;
95+
@Children private final ExpressionNode[] values;
96+
@Children private final HashingStorageLibrary[] libs;
97+
98+
protected DynamicDictLiteralNode(ExpressionNode[] keys, ExpressionNode[] values) {
6099
this.keys = keys;
61-
this.allStrings = allStrings;
100+
this.values = values;
101+
this.libs = new HashingStorageLibrary[keys.length];
102+
for (int i = 0; i < this.libs.length; i++) {
103+
this.libs[i] = HashingStorageLibrary.getFactory().createDispatched(2);
104+
}
105+
}
106+
107+
static final class Keys {
108+
public final Object[] keys;
109+
public final boolean allStrings;
110+
111+
Keys(Object[] keys, boolean allStrings) {
112+
this.keys = keys;
113+
this.allStrings = allStrings;
114+
}
62115
}
63-
}
64116

65-
@ExplodeLoop
66-
private Keys evalKeys(VirtualFrame frame) {
67-
boolean allStrings = true;
68-
Object[] evalKeys = new Object[this.keys.length];
69-
for (int i = 0; i < values.length; i++) {
70-
evalKeys[i] = keys[i].execute(frame);
71-
if (!(evalKeys[i] instanceof String)) {
72-
allStrings = false;
117+
@ExplodeLoop
118+
private Keys evalKeys(VirtualFrame frame) {
119+
boolean allStrings = true;
120+
Object[] evalKeys = new Object[this.keys.length];
121+
for (int i = 0; i < values.length; i++) {
122+
evalKeys[i] = keys[i].execute(frame);
123+
if (!(evalKeys[i] instanceof String)) {
124+
allStrings = false;
125+
}
73126
}
127+
return new Keys(evalKeys, allStrings);
128+
}
129+
130+
@ExplodeLoop
131+
private HashingStorage evalAndSetValues(VirtualFrame frame, HashingStorage dictStorage, Keys evalKeys, ConditionProfile hasFrame) {
132+
HashingStorage storage = dictStorage;
133+
for (int i = 0; i < values.length; i++) {
134+
Object val = values[i].execute(frame);
135+
storage = libs[i].setItemWithFrame(storage, evalKeys.keys[i], val, hasFrame, frame);
136+
}
137+
return storage;
138+
}
139+
140+
@Specialization
141+
public PDict create(VirtualFrame frame,
142+
@CachedLanguage PythonLanguage lang,
143+
@Cached("createBinaryProfile()") ConditionProfile hasFrame) {
144+
Keys evalKeys = evalKeys(frame);
145+
HashingStorage dictStorage = PDict.createNewStorage(lang, evalKeys.allStrings, evalKeys.keys.length);
146+
dictStorage = evalAndSetValues(frame, dictStorage, evalKeys, hasFrame);
147+
return factory.createDict(dictStorage);
74148
}
75-
return new Keys(evalKeys, allStrings);
76149
}
77150

78-
@ExplodeLoop
79-
private HashingStorage evalAndSetValues(VirtualFrame frame, HashingStorage dictStorage, Keys evalKeys, ConditionProfile hasFrame, HashingStorageLibrary lib) {
80-
HashingStorage storage = dictStorage;
81-
for (int i = 0; i < values.length; i++) {
82-
final Object val = values[i].execute(frame);
83-
storage = lib.setItemWithFrame(storage, evalKeys.keys[i], val, hasFrame, frame);
151+
static final class EmptyDictLiteralNode extends LiteralNode {
152+
153+
@Child private PythonObjectFactory factory = PythonObjectFactory.create();
154+
155+
@Override
156+
public Object execute(VirtualFrame frame) {
157+
return factory.createDict(new EmptyStorage());
84158
}
85-
return storage;
86159
}
87160

88-
@Specialization
89-
public PDict create(VirtualFrame frame,
90-
@CachedLanguage PythonLanguage lang,
91-
@Cached("createBinaryProfile()") ConditionProfile hasFrame,
92-
@CachedLibrary(limit = "3") HashingStorageLibrary lib) {
93-
Keys evalKeys = evalKeys(frame);
94-
HashingStorage dictStorage = PDict.createNewStorage(lang, evalKeys.allStrings, evalKeys.keys.length);
95-
dictStorage = evalAndSetValues(frame, dictStorage, evalKeys, hasFrame, lib);
96-
return factory.createDict(dictStorage);
161+
public static ExpressionNode create(ExpressionNode[] keys, ExpressionNode[] values) {
162+
assert keys.length == values.length;
163+
if (keys.length == 0) {
164+
return new EmptyDictLiteralNode();
165+
}
166+
if (keys.length > DynamicObjectStorage.SIZE_THRESHOLD) {
167+
return DynamicDictLiteralNodeGen.create(keys, values);
168+
}
169+
for (ExpressionNode key : keys) {
170+
if (!(key instanceof StringLiteralNode)) {
171+
return DynamicDictLiteralNodeGen.create(keys, values);
172+
}
173+
}
174+
return FixedDictLiteralNodeGen.create(keys, values);
97175
}
98176
}

0 commit comments

Comments
 (0)