Skip to content

Commit 2f0d108

Browse files
committed
[GR-44456] Use new TStringBuilder in JSON encoding.
PullRequest: graalpython/2787
2 parents c531673 + b98ebfd commit 2f0d108

File tree

4 files changed

+253
-124
lines changed

4 files changed

+253
-124
lines changed

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/json/JSONEncoderBuiltins.java

Lines changed: 49 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -16,13 +16,6 @@
1616
import static com.oracle.graal.python.nodes.PGuards.isPInt;
1717
import static com.oracle.graal.python.nodes.PGuards.isString;
1818
import static com.oracle.graal.python.nodes.SpecialMethodNames.J___CALL__;
19-
import static com.oracle.graal.python.nodes.StringLiterals.T_DOUBLE_QUOTE;
20-
import static com.oracle.graal.python.nodes.StringLiterals.T_EMPTY_BRACES;
21-
import static com.oracle.graal.python.nodes.StringLiterals.T_EMPTY_BRACKETS;
22-
import static com.oracle.graal.python.nodes.StringLiterals.T_LBRACE;
23-
import static com.oracle.graal.python.nodes.StringLiterals.T_LBRACKET;
24-
import static com.oracle.graal.python.nodes.StringLiterals.T_RBRACE;
25-
import static com.oracle.graal.python.nodes.StringLiterals.T_RBRACKET;
2619
import static com.oracle.graal.python.nodes.truffle.TruffleStringMigrationHelpers.isJavaString;
2720
import static com.oracle.graal.python.util.PythonUtils.TS_ENCODING;
2821
import static com.oracle.graal.python.util.PythonUtils.toTruffleStringUncached;
@@ -71,23 +64,24 @@
7164
import com.oracle.graal.python.runtime.sequence.PSequence;
7265
import com.oracle.graal.python.runtime.sequence.storage.SequenceStorage;
7366
import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
74-
import com.oracle.truffle.api.dsl.Cached;
7567
import com.oracle.truffle.api.dsl.GenerateNodeFactory;
7668
import com.oracle.truffle.api.dsl.NodeFactory;
7769
import com.oracle.truffle.api.dsl.Specialization;
7870
import com.oracle.truffle.api.strings.TruffleString;
7971
import com.oracle.truffle.api.strings.TruffleStringBuilder;
80-
import com.oracle.truffle.api.strings.TruffleStringIterator;
72+
import com.oracle.truffle.api.strings.TruffleStringBuilderUTF32;
8173

8274
@CoreFunctions(extendClasses = PythonBuiltinClassType.JSONEncoder)
8375
public class JSONEncoderBuiltins extends PythonBuiltins {
8476

8577
private static final TruffleString T_NULL = tsLiteral("null");
86-
private static final TruffleString T_JSON_TRUE = tsLiteral("true");
87-
private static final TruffleString T_JSON_FALSE = tsLiteral("false");
78+
private static final TruffleString T_TRUE = tsLiteral("true");
79+
private static final TruffleString T_FALSE = tsLiteral("false");
8880
private static final TruffleString T_POSITIVE_INFINITY = tsLiteral("Infinity");
8981
private static final TruffleString T_NEGATIVE_INFINITY = tsLiteral("-Infinity");
9082
private static final TruffleString T_NAN = tsLiteral("NaN");
83+
private static final TruffleString T_BRACES = tsLiteral("{}");
84+
private static final TruffleString T_BRACKETS = tsLiteral("[]");
9185

9286
@Override
9387
protected List<? extends NodeFactory<? extends PythonBuiltinBaseNode>> getNodeFactories() {
@@ -102,46 +96,49 @@ public abstract static class CallEncoderNode extends PythonTernaryClinicBuiltinN
10296
@Child private LookupAndCallUnaryNode callGetDictIter = LookupAndCallUnaryNode.create(SpecialMethodSlot.Iter);
10397
@Child private LookupAndCallUnaryNode callGetListIter = LookupAndCallUnaryNode.create(SpecialMethodSlot.Iter);
10498
@Child private ListSortNode sortList = ListSortNode.create();
105-
private static final TruffleStringBuilder.AppendStringNode appendStringNode = TruffleStringBuilder.AppendStringNode.getUncached();
10699

107100
@Override
108101
protected ArgumentClinicProvider getArgumentClinic() {
109102
return JSONEncoderBuiltinsClinicProviders.CallEncoderNodeClinicProviderGen.INSTANCE;
110103
}
111104

112105
@Specialization
113-
protected PTuple call(PJSONEncoder self, Object obj, @SuppressWarnings("unused") int indent,
114-
@Cached TruffleStringBuilder.ToStringNode toStringNode) {
115-
TruffleStringBuilder builder = TruffleStringBuilder.create(TS_ENCODING);
116-
appendListObj(self, builder, obj);
117-
return factory().createTuple(new Object[]{toStringNode.execute(builder)});
106+
protected PTuple call(PJSONEncoder self, Object obj, @SuppressWarnings("unused") int indent) {
107+
return factory().createTuple(new Object[]{jsonEncode(self, obj)});
118108
}
119109

120-
private void appendConst(TruffleStringBuilder builder, Object obj) {
110+
@TruffleBoundary
111+
private TruffleString jsonEncode(PJSONEncoder encoder, Object obj) {
112+
TruffleStringBuilderUTF32 builder = TruffleStringBuilder.createUTF32();
113+
appendListObj(encoder, builder, obj);
114+
return TruffleStringBuilder.ToStringNode.getUncached().execute(builder);
115+
}
116+
117+
private void appendConst(TruffleStringBuilderUTF32 builder, Object obj) {
121118
if (obj == PNone.NONE) {
122-
appendStringNode.execute(builder, T_NULL);
119+
builder.appendStringUncached(T_NULL);
123120
} else if (obj == Boolean.TRUE) {
124-
appendStringNode.execute(builder, T_JSON_TRUE);
121+
builder.appendStringUncached(T_TRUE);
125122
} else {
126123
assert obj == Boolean.FALSE;
127-
appendStringNode.execute(builder, T_JSON_FALSE);
124+
builder.appendStringUncached(T_FALSE);
128125
}
129126
}
130127

131-
private void appendFloat(PJSONEncoder encoder, TruffleStringBuilder builder, double obj) {
128+
private void appendFloat(PJSONEncoder encoder, TruffleStringBuilderUTF32 builder, double obj) {
132129
if (!Double.isFinite(obj)) {
133130
if (!encoder.allowNan) {
134131
throw raise(ValueError, ErrorMessages.OUT_OF_RANGE_FLOAT_NOT_JSON_COMPLIANT);
135132
}
136133
if (obj > 0) {
137-
appendStringNode.execute(builder, T_POSITIVE_INFINITY);
134+
builder.appendStringUncached(T_POSITIVE_INFINITY);
138135
} else if (obj < 0) {
139-
appendStringNode.execute(builder, T_NEGATIVE_INFINITY);
136+
builder.appendStringUncached(T_NEGATIVE_INFINITY);
140137
} else {
141-
appendStringNode.execute(builder, T_NAN);
138+
builder.appendStringUncached(T_NAN);
142139
}
143140
} else {
144-
appendStringNode.execute(builder, formatDouble(obj));
141+
builder.appendStringUncached(formatDouble(obj));
145142
}
146143
}
147144

@@ -151,37 +148,32 @@ private static TruffleString formatDouble(double obj) {
151148
return FloatBuiltins.StrNode.doFormat(obj, f);
152149
}
153150

154-
private void appendString(PJSONEncoder encoder, TruffleStringBuilder builder, TruffleString obj) {
151+
private void appendString(PJSONEncoder encoder, TruffleStringBuilderUTF32 builder, TruffleString obj) {
155152
switch (encoder.fastEncode) {
156153
case FastEncode:
157-
appendString(obj, builder, false);
154+
JSONUtils.appendStringUncached(obj, builder, false);
158155
break;
159156
case FastEncodeAscii:
160-
appendString(obj, builder, true);
157+
JSONUtils.appendStringUncached(obj, builder, true);
161158
break;
162159
case None:
163160
Object result = CallUnaryMethodNode.getUncached().executeObject(encoder.encoder, obj);
164161
if (!isString(result)) {
165162
throw raise(TypeError, ErrorMessages.ENCODER_MUST_RETURN_STR, result);
166163
}
167-
appendStringNode.execute(builder, CastToTruffleStringNode.getUncached().execute(result));
164+
builder.appendStringUncached(CastToTruffleStringNode.getUncached().execute(result));
168165
break;
169166
default:
170167
assert false;
171168
break;
172169
}
173170
}
174171

175-
private static void appendString(TruffleString obj, TruffleStringBuilder builder, boolean asciiOnly) {
176-
JSONModuleBuiltins.appendString(TruffleString.CreateCodePointIteratorNode.getUncached().execute(obj, TS_ENCODING), builder, asciiOnly,
177-
TruffleStringIterator.NextNode.getUncached(), TruffleStringBuilder.AppendCodePointNode.getUncached());
178-
}
179-
180172
private static boolean isSimpleObj(Object obj) {
181173
return obj == PNone.NONE || obj == Boolean.TRUE || obj == Boolean.FALSE || isString(obj) || isInteger(obj) || isPInt(obj) || obj instanceof Float || isDouble(obj) || isPFloat(obj);
182174
}
183175

184-
private boolean appendSimpleObj(PJSONEncoder encoder, TruffleStringBuilder builder, Object obj) {
176+
private boolean appendSimpleObj(PJSONEncoder encoder, TruffleStringBuilderUTF32 builder, Object obj) {
185177
if (obj == PNone.NONE || obj == Boolean.TRUE || obj == Boolean.FALSE) {
186178
appendConst(builder, obj);
187179
} else if (isJavaString(obj)) {
@@ -191,11 +183,11 @@ private boolean appendSimpleObj(PJSONEncoder encoder, TruffleStringBuilder build
191183
} else if (obj instanceof PString) {
192184
appendString(encoder, builder, StringNodes.StringMaterializeNode.executeUncached((PString) obj));
193185
} else if (obj instanceof Integer) {
194-
TruffleStringBuilder.AppendLongNumberNode.getUncached().execute(builder, (int) obj);
186+
builder.appendIntNumberUncached((int) obj);
195187
} else if (obj instanceof Long) {
196-
TruffleStringBuilder.AppendLongNumberNode.getUncached().execute(builder, (long) obj);
188+
builder.appendLongNumberUncached((long) obj);
197189
} else if (obj instanceof PInt) {
198-
appendStringNode.execute(builder, TruffleString.FromJavaStringNode.getUncached().execute(castExact(obj, PInt.class).toString(), TS_ENCODING));
190+
builder.appendStringUncached(TruffleString.FromJavaStringNode.getUncached().execute(castExact(obj, PInt.class).toString(), TS_ENCODING));
199191
} else if (obj instanceof Float) {
200192
appendFloat(encoder, builder, (float) obj);
201193
} else if (obj instanceof Double) {
@@ -208,8 +200,7 @@ private boolean appendSimpleObj(PJSONEncoder encoder, TruffleStringBuilder build
208200
return true;
209201
}
210202

211-
@TruffleBoundary
212-
private void appendListObj(PJSONEncoder encoder, TruffleStringBuilder builder, Object obj) {
203+
private void appendListObj(PJSONEncoder encoder, TruffleStringBuilderUTF32 builder, Object obj) {
213204
if (appendSimpleObj(encoder, builder, obj)) {
214205
// done
215206
} else if (obj instanceof PList || obj instanceof PTuple) {
@@ -238,14 +229,14 @@ private void startRecursion(PJSONEncoder encoder, Object obj) {
238229
}
239230
}
240231

241-
private void appendDict(PJSONEncoder encoder, TruffleStringBuilder builder, PDict dict) {
232+
private void appendDict(PJSONEncoder encoder, TruffleStringBuilderUTF32 builder, PDict dict) {
242233
HashingStorage storage = dict.getDictStorage();
243234

244235
if (HashingStorageLen.executeUncached(storage) == 0) {
245-
appendStringNode.execute(builder, T_EMPTY_BRACES);
236+
builder.appendStringUncached(T_BRACES);
246237
} else {
247238
startRecursion(encoder, dict);
248-
appendStringNode.execute(builder, T_LBRACE);
239+
builder.appendCodePointUncached('{');
249240

250241
if (!encoder.sortKeys && IsBuiltinObjectProfile.profileObjectUncached(dict, PDict)) {
251242
HashingStorageIterator it = HashingStorageGetIterator.executeUncached(storage);
@@ -259,12 +250,12 @@ private void appendDict(PJSONEncoder encoder, TruffleStringBuilder builder, PDic
259250
appendDictSlowPath(encoder, builder, dict);
260251
}
261252

262-
appendStringNode.execute(builder, T_RBRACE);
253+
builder.appendCodePointUncached('}');
263254
endRecursion(encoder, dict);
264255
}
265256
}
266257

267-
private void appendDictSlowPath(PJSONEncoder encoder, TruffleStringBuilder builder, com.oracle.graal.python.builtins.objects.dict.PDict dict) {
258+
private void appendDictSlowPath(PJSONEncoder encoder, TruffleStringBuilderUTF32 builder, com.oracle.graal.python.builtins.objects.dict.PDict dict) {
268259
PList items = ConstructListNode.getUncached().execute(null, callGetItems.executeObject(null, dict));
269260
if (encoder.sortKeys) {
270261
sortList.execute(null, items);
@@ -289,9 +280,9 @@ private void appendDictSlowPath(PJSONEncoder encoder, TruffleStringBuilder build
289280
}
290281
}
291282

292-
private boolean appendDictEntry(PJSONEncoder encoder, TruffleStringBuilder builder, boolean first, Object key, Object value) {
283+
private boolean appendDictEntry(PJSONEncoder encoder, TruffleStringBuilderUTF32 builder, boolean first, Object key, Object value) {
293284
if (!first) {
294-
appendStringNode.execute(builder, encoder.itemSeparator);
285+
builder.appendStringUncached(encoder.itemSeparator);
295286
}
296287
if (isString(key)) {
297288
appendSimpleObj(encoder, builder, key);
@@ -302,41 +293,41 @@ private boolean appendDictEntry(PJSONEncoder encoder, TruffleStringBuilder build
302293
}
303294
throw raise(TypeError, ErrorMessages.KEYS_MUST_BE_STR_INT___NOT_P, key);
304295
}
305-
appendStringNode.execute(builder, T_DOUBLE_QUOTE);
296+
builder.appendCodePointUncached('"');
306297
appendSimpleObj(encoder, builder, key);
307-
appendStringNode.execute(builder, T_DOUBLE_QUOTE);
298+
builder.appendCodePointUncached('"');
308299
}
309-
appendStringNode.execute(builder, encoder.keySeparator);
300+
builder.appendStringUncached(encoder.keySeparator);
310301
appendListObj(encoder, builder, value);
311302
return false;
312303
}
313304

314-
private void appendList(PJSONEncoder encoder, TruffleStringBuilder builder, PSequence list) {
305+
private void appendList(PJSONEncoder encoder, TruffleStringBuilderUTF32 builder, PSequence list) {
315306
SequenceStorage storage = list.getSequenceStorage();
316307

317308
if (storage.length() == 0) {
318-
appendStringNode.execute(builder, T_EMPTY_BRACKETS);
309+
builder.appendStringUncached(T_BRACKETS);
319310
} else {
320311
startRecursion(encoder, list);
321-
appendStringNode.execute(builder, T_LBRACKET);
312+
builder.appendCodePointUncached('[');
322313

323314
if (IsBuiltinObjectProfile.profileObjectUncached(list, PTuple) || IsBuiltinObjectProfile.profileObjectUncached(list, PList)) {
324315
for (int i = 0; i < storage.length(); i++) {
325316
if (i > 0) {
326-
appendStringNode.execute(builder, encoder.itemSeparator);
317+
builder.appendStringUncached(encoder.itemSeparator);
327318
}
328319
appendListObj(encoder, builder, storage.getItemNormalized(i));
329320
}
330321
} else {
331322
appendListSlowPath(encoder, builder, list);
332323
}
333324

334-
appendStringNode.execute(builder, T_RBRACKET);
325+
builder.appendCodePointUncached(']');
335326
endRecursion(encoder, list);
336327
}
337328
}
338329

339-
private void appendListSlowPath(PJSONEncoder encoder, TruffleStringBuilder builder, PSequence list) {
330+
private void appendListSlowPath(PJSONEncoder encoder, TruffleStringBuilderUTF32 builder, PSequence list) {
340331
Object iter = callGetListIter.executeObject(null, list);
341332
boolean first = true;
342333
while (true) {
@@ -348,7 +339,7 @@ private void appendListSlowPath(PJSONEncoder encoder, TruffleStringBuilder build
348339
break;
349340
}
350341
if (!first) {
351-
appendStringNode.execute(builder, encoder.itemSeparator);
342+
builder.appendStringUncached(encoder.itemSeparator);
352343
}
353344
first = false;
354345
appendListObj(encoder, builder, item);

0 commit comments

Comments
 (0)