16
16
import static com .oracle .graal .python .nodes .PGuards .isPInt ;
17
17
import static com .oracle .graal .python .nodes .PGuards .isString ;
18
18
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 ;
26
19
import static com .oracle .graal .python .nodes .truffle .TruffleStringMigrationHelpers .isJavaString ;
27
20
import static com .oracle .graal .python .util .PythonUtils .TS_ENCODING ;
28
21
import static com .oracle .graal .python .util .PythonUtils .toTruffleStringUncached ;
71
64
import com .oracle .graal .python .runtime .sequence .PSequence ;
72
65
import com .oracle .graal .python .runtime .sequence .storage .SequenceStorage ;
73
66
import com .oracle .truffle .api .CompilerDirectives .TruffleBoundary ;
74
- import com .oracle .truffle .api .dsl .Cached ;
75
67
import com .oracle .truffle .api .dsl .GenerateNodeFactory ;
76
68
import com .oracle .truffle .api .dsl .NodeFactory ;
77
69
import com .oracle .truffle .api .dsl .Specialization ;
78
70
import com .oracle .truffle .api .strings .TruffleString ;
79
71
import com .oracle .truffle .api .strings .TruffleStringBuilder ;
80
- import com .oracle .truffle .api .strings .TruffleStringIterator ;
72
+ import com .oracle .truffle .api .strings .TruffleStringBuilderUTF32 ;
81
73
82
74
@ CoreFunctions (extendClasses = PythonBuiltinClassType .JSONEncoder )
83
75
public class JSONEncoderBuiltins extends PythonBuiltins {
84
76
85
77
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" );
88
80
private static final TruffleString T_POSITIVE_INFINITY = tsLiteral ("Infinity" );
89
81
private static final TruffleString T_NEGATIVE_INFINITY = tsLiteral ("-Infinity" );
90
82
private static final TruffleString T_NAN = tsLiteral ("NaN" );
83
+ private static final TruffleString T_BRACES = tsLiteral ("{}" );
84
+ private static final TruffleString T_BRACKETS = tsLiteral ("[]" );
91
85
92
86
@ Override
93
87
protected List <? extends NodeFactory <? extends PythonBuiltinBaseNode >> getNodeFactories () {
@@ -102,46 +96,49 @@ public abstract static class CallEncoderNode extends PythonTernaryClinicBuiltinN
102
96
@ Child private LookupAndCallUnaryNode callGetDictIter = LookupAndCallUnaryNode .create (SpecialMethodSlot .Iter );
103
97
@ Child private LookupAndCallUnaryNode callGetListIter = LookupAndCallUnaryNode .create (SpecialMethodSlot .Iter );
104
98
@ Child private ListSortNode sortList = ListSortNode .create ();
105
- private static final TruffleStringBuilder .AppendStringNode appendStringNode = TruffleStringBuilder .AppendStringNode .getUncached ();
106
99
107
100
@ Override
108
101
protected ArgumentClinicProvider getArgumentClinic () {
109
102
return JSONEncoderBuiltinsClinicProviders .CallEncoderNodeClinicProviderGen .INSTANCE ;
110
103
}
111
104
112
105
@ 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 )});
118
108
}
119
109
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 ) {
121
118
if (obj == PNone .NONE ) {
122
- appendStringNode . execute ( builder , T_NULL );
119
+ builder . appendStringUncached ( T_NULL );
123
120
} else if (obj == Boolean .TRUE ) {
124
- appendStringNode . execute ( builder , T_JSON_TRUE );
121
+ builder . appendStringUncached ( T_TRUE );
125
122
} else {
126
123
assert obj == Boolean .FALSE ;
127
- appendStringNode . execute ( builder , T_JSON_FALSE );
124
+ builder . appendStringUncached ( T_FALSE );
128
125
}
129
126
}
130
127
131
- private void appendFloat (PJSONEncoder encoder , TruffleStringBuilder builder , double obj ) {
128
+ private void appendFloat (PJSONEncoder encoder , TruffleStringBuilderUTF32 builder , double obj ) {
132
129
if (!Double .isFinite (obj )) {
133
130
if (!encoder .allowNan ) {
134
131
throw raise (ValueError , ErrorMessages .OUT_OF_RANGE_FLOAT_NOT_JSON_COMPLIANT );
135
132
}
136
133
if (obj > 0 ) {
137
- appendStringNode . execute ( builder , T_POSITIVE_INFINITY );
134
+ builder . appendStringUncached ( T_POSITIVE_INFINITY );
138
135
} else if (obj < 0 ) {
139
- appendStringNode . execute ( builder , T_NEGATIVE_INFINITY );
136
+ builder . appendStringUncached ( T_NEGATIVE_INFINITY );
140
137
} else {
141
- appendStringNode . execute ( builder , T_NAN );
138
+ builder . appendStringUncached ( T_NAN );
142
139
}
143
140
} else {
144
- appendStringNode . execute ( builder , formatDouble (obj ));
141
+ builder . appendStringUncached ( formatDouble (obj ));
145
142
}
146
143
}
147
144
@@ -151,37 +148,32 @@ private static TruffleString formatDouble(double obj) {
151
148
return FloatBuiltins .StrNode .doFormat (obj , f );
152
149
}
153
150
154
- private void appendString (PJSONEncoder encoder , TruffleStringBuilder builder , TruffleString obj ) {
151
+ private void appendString (PJSONEncoder encoder , TruffleStringBuilderUTF32 builder , TruffleString obj ) {
155
152
switch (encoder .fastEncode ) {
156
153
case FastEncode :
157
- appendString (obj , builder , false );
154
+ JSONUtils . appendStringUncached (obj , builder , false );
158
155
break ;
159
156
case FastEncodeAscii :
160
- appendString (obj , builder , true );
157
+ JSONUtils . appendStringUncached (obj , builder , true );
161
158
break ;
162
159
case None :
163
160
Object result = CallUnaryMethodNode .getUncached ().executeObject (encoder .encoder , obj );
164
161
if (!isString (result )) {
165
162
throw raise (TypeError , ErrorMessages .ENCODER_MUST_RETURN_STR , result );
166
163
}
167
- appendStringNode . execute ( builder , CastToTruffleStringNode .getUncached ().execute (result ));
164
+ builder . appendStringUncached ( CastToTruffleStringNode .getUncached ().execute (result ));
168
165
break ;
169
166
default :
170
167
assert false ;
171
168
break ;
172
169
}
173
170
}
174
171
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
-
180
172
private static boolean isSimpleObj (Object obj ) {
181
173
return obj == PNone .NONE || obj == Boolean .TRUE || obj == Boolean .FALSE || isString (obj ) || isInteger (obj ) || isPInt (obj ) || obj instanceof Float || isDouble (obj ) || isPFloat (obj );
182
174
}
183
175
184
- private boolean appendSimpleObj (PJSONEncoder encoder , TruffleStringBuilder builder , Object obj ) {
176
+ private boolean appendSimpleObj (PJSONEncoder encoder , TruffleStringBuilderUTF32 builder , Object obj ) {
185
177
if (obj == PNone .NONE || obj == Boolean .TRUE || obj == Boolean .FALSE ) {
186
178
appendConst (builder , obj );
187
179
} else if (isJavaString (obj )) {
@@ -191,11 +183,11 @@ private boolean appendSimpleObj(PJSONEncoder encoder, TruffleStringBuilder build
191
183
} else if (obj instanceof PString ) {
192
184
appendString (encoder , builder , StringNodes .StringMaterializeNode .executeUncached ((PString ) obj ));
193
185
} else if (obj instanceof Integer ) {
194
- TruffleStringBuilder . AppendLongNumberNode . getUncached (). execute ( builder , (int ) obj );
186
+ builder . appendIntNumberUncached ( (int ) obj );
195
187
} else if (obj instanceof Long ) {
196
- TruffleStringBuilder . AppendLongNumberNode . getUncached (). execute ( builder , (long ) obj );
188
+ builder . appendLongNumberUncached ( (long ) obj );
197
189
} 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 ));
199
191
} else if (obj instanceof Float ) {
200
192
appendFloat (encoder , builder , (float ) obj );
201
193
} else if (obj instanceof Double ) {
@@ -208,8 +200,7 @@ private boolean appendSimpleObj(PJSONEncoder encoder, TruffleStringBuilder build
208
200
return true ;
209
201
}
210
202
211
- @ TruffleBoundary
212
- private void appendListObj (PJSONEncoder encoder , TruffleStringBuilder builder , Object obj ) {
203
+ private void appendListObj (PJSONEncoder encoder , TruffleStringBuilderUTF32 builder , Object obj ) {
213
204
if (appendSimpleObj (encoder , builder , obj )) {
214
205
// done
215
206
} else if (obj instanceof PList || obj instanceof PTuple ) {
@@ -238,14 +229,14 @@ private void startRecursion(PJSONEncoder encoder, Object obj) {
238
229
}
239
230
}
240
231
241
- private void appendDict (PJSONEncoder encoder , TruffleStringBuilder builder , PDict dict ) {
232
+ private void appendDict (PJSONEncoder encoder , TruffleStringBuilderUTF32 builder , PDict dict ) {
242
233
HashingStorage storage = dict .getDictStorage ();
243
234
244
235
if (HashingStorageLen .executeUncached (storage ) == 0 ) {
245
- appendStringNode . execute ( builder , T_EMPTY_BRACES );
236
+ builder . appendStringUncached ( T_BRACES );
246
237
} else {
247
238
startRecursion (encoder , dict );
248
- appendStringNode . execute ( builder , T_LBRACE );
239
+ builder . appendCodePointUncached ( '{' );
249
240
250
241
if (!encoder .sortKeys && IsBuiltinObjectProfile .profileObjectUncached (dict , PDict )) {
251
242
HashingStorageIterator it = HashingStorageGetIterator .executeUncached (storage );
@@ -259,12 +250,12 @@ private void appendDict(PJSONEncoder encoder, TruffleStringBuilder builder, PDic
259
250
appendDictSlowPath (encoder , builder , dict );
260
251
}
261
252
262
- appendStringNode . execute ( builder , T_RBRACE );
253
+ builder . appendCodePointUncached ( '}' );
263
254
endRecursion (encoder , dict );
264
255
}
265
256
}
266
257
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 ) {
268
259
PList items = ConstructListNode .getUncached ().execute (null , callGetItems .executeObject (null , dict ));
269
260
if (encoder .sortKeys ) {
270
261
sortList .execute (null , items );
@@ -289,9 +280,9 @@ private void appendDictSlowPath(PJSONEncoder encoder, TruffleStringBuilder build
289
280
}
290
281
}
291
282
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 ) {
293
284
if (!first ) {
294
- appendStringNode . execute ( builder , encoder .itemSeparator );
285
+ builder . appendStringUncached ( encoder .itemSeparator );
295
286
}
296
287
if (isString (key )) {
297
288
appendSimpleObj (encoder , builder , key );
@@ -302,41 +293,41 @@ private boolean appendDictEntry(PJSONEncoder encoder, TruffleStringBuilder build
302
293
}
303
294
throw raise (TypeError , ErrorMessages .KEYS_MUST_BE_STR_INT___NOT_P , key );
304
295
}
305
- appendStringNode . execute ( builder , T_DOUBLE_QUOTE );
296
+ builder . appendCodePointUncached ( '"' );
306
297
appendSimpleObj (encoder , builder , key );
307
- appendStringNode . execute ( builder , T_DOUBLE_QUOTE );
298
+ builder . appendCodePointUncached ( '"' );
308
299
}
309
- appendStringNode . execute ( builder , encoder .keySeparator );
300
+ builder . appendStringUncached ( encoder .keySeparator );
310
301
appendListObj (encoder , builder , value );
311
302
return false ;
312
303
}
313
304
314
- private void appendList (PJSONEncoder encoder , TruffleStringBuilder builder , PSequence list ) {
305
+ private void appendList (PJSONEncoder encoder , TruffleStringBuilderUTF32 builder , PSequence list ) {
315
306
SequenceStorage storage = list .getSequenceStorage ();
316
307
317
308
if (storage .length () == 0 ) {
318
- appendStringNode . execute ( builder , T_EMPTY_BRACKETS );
309
+ builder . appendStringUncached ( T_BRACKETS );
319
310
} else {
320
311
startRecursion (encoder , list );
321
- appendStringNode . execute ( builder , T_LBRACKET );
312
+ builder . appendCodePointUncached ( '[' );
322
313
323
314
if (IsBuiltinObjectProfile .profileObjectUncached (list , PTuple ) || IsBuiltinObjectProfile .profileObjectUncached (list , PList )) {
324
315
for (int i = 0 ; i < storage .length (); i ++) {
325
316
if (i > 0 ) {
326
- appendStringNode . execute ( builder , encoder .itemSeparator );
317
+ builder . appendStringUncached ( encoder .itemSeparator );
327
318
}
328
319
appendListObj (encoder , builder , storage .getItemNormalized (i ));
329
320
}
330
321
} else {
331
322
appendListSlowPath (encoder , builder , list );
332
323
}
333
324
334
- appendStringNode . execute ( builder , T_RBRACKET );
325
+ builder . appendCodePointUncached ( ']' );
335
326
endRecursion (encoder , list );
336
327
}
337
328
}
338
329
339
- private void appendListSlowPath (PJSONEncoder encoder , TruffleStringBuilder builder , PSequence list ) {
330
+ private void appendListSlowPath (PJSONEncoder encoder , TruffleStringBuilderUTF32 builder , PSequence list ) {
340
331
Object iter = callGetListIter .executeObject (null , list );
341
332
boolean first = true ;
342
333
while (true ) {
@@ -348,7 +339,7 @@ private void appendListSlowPath(PJSONEncoder encoder, TruffleStringBuilder build
348
339
break ;
349
340
}
350
341
if (!first ) {
351
- appendStringNode . execute ( builder , encoder .itemSeparator );
342
+ builder . appendStringUncached ( encoder .itemSeparator );
352
343
}
353
344
first = false ;
354
345
appendListObj (encoder , builder , item );
0 commit comments