Skip to content

Commit 50daa39

Browse files
AnthonyCalandrazherczeg
authored andcommitted
Optimize JSON Quote operation. (#2420)
JerryScript-DCO-1.0-Signed-off-by: Anthony Calandra [email protected]
1 parent 0c6b5ea commit 50daa39

File tree

3 files changed

+92
-66
lines changed

3 files changed

+92
-66
lines changed

jerry-core/ecma/builtin-objects/ecma-builtin-json.c

Lines changed: 92 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -1213,107 +1213,137 @@ ecma_builtin_json_stringify (ecma_value_t this_arg, /**< 'this' argument */
12131213
static ecma_value_t
12141214
ecma_builtin_json_quote (ecma_string_t *string_p) /**< string that should be quoted*/
12151215
{
1216-
/* 1. */
1217-
ecma_string_t *product_str_p = ecma_get_magic_string (LIT_MAGIC_STRING_DOUBLE_QUOTE_CHAR);
1218-
12191216
ECMA_STRING_TO_UTF8_STRING (string_p, string_buff, string_buff_size);
1220-
12211217
const lit_utf8_byte_t *str_p = string_buff;
1222-
const lit_utf8_byte_t *str_end_p = string_buff + string_buff_size;
1218+
const lit_utf8_byte_t *str_end_p = str_p + string_buff_size;
1219+
size_t n_bytes = 2; /* Start with 2 for surrounding quotes. */
12231220

12241221
while (str_p < str_end_p)
12251222
{
1226-
ecma_char_t current_char = lit_utf8_read_next (&str_p);
1223+
lit_utf8_byte_t c = *str_p++;
12271224

1228-
/* 2.a, b */
1229-
if (current_char == LIT_CHAR_BACKSLASH
1230-
|| current_char == LIT_CHAR_DOUBLE_QUOTE
1231-
|| current_char == LIT_CHAR_BS
1232-
|| current_char == LIT_CHAR_FF
1233-
|| current_char == LIT_CHAR_LF
1234-
|| current_char == LIT_CHAR_CR
1235-
|| current_char == LIT_CHAR_TAB)
1225+
if (c == LIT_CHAR_BACKSLASH || c == LIT_CHAR_DOUBLE_QUOTE)
1226+
{
1227+
n_bytes += 2;
1228+
}
1229+
else if (c >= LIT_CHAR_SP && c < LIT_UTF8_1_BYTE_CODE_POINT_MAX)
1230+
{
1231+
n_bytes++;
1232+
}
1233+
else if (c > LIT_UTF8_1_BYTE_CODE_POINT_MAX)
12361234
{
1237-
lit_utf8_byte_t abbrev = (lit_utf8_byte_t) current_char;
1235+
lit_utf8_size_t sz = lit_get_unicode_char_size_by_utf8_first_byte (c);
1236+
n_bytes += sz;
1237+
str_p += sz - 1;
1238+
}
1239+
else
1240+
{
1241+
switch (c)
1242+
{
1243+
case LIT_CHAR_BS:
1244+
case LIT_CHAR_FF:
1245+
case LIT_CHAR_LF:
1246+
case LIT_CHAR_CR:
1247+
case LIT_CHAR_TAB:
1248+
{
1249+
n_bytes += 2;
1250+
break;
1251+
}
1252+
default: /* Hexadecimal. */
1253+
{
1254+
n_bytes += 2 + 4;
1255+
break;
1256+
}
1257+
}
1258+
}
1259+
}
1260+
1261+
lit_utf8_byte_t *buf_begin = jmem_heap_alloc_block (n_bytes);
1262+
JERRY_ASSERT (buf_begin != NULL);
1263+
lit_utf8_byte_t *buf = buf_begin;
1264+
str_p = string_buff;
1265+
1266+
*buf++ = LIT_CHAR_DOUBLE_QUOTE;
1267+
1268+
while (str_p < str_end_p)
1269+
{
1270+
lit_utf8_byte_t c = *str_p++;
12381271

1239-
switch (current_char)
1272+
if (c == LIT_CHAR_BACKSLASH || c == LIT_CHAR_DOUBLE_QUOTE)
1273+
{
1274+
*buf++ = LIT_CHAR_BACKSLASH;
1275+
*buf++ = c;
1276+
}
1277+
else if (c >= LIT_CHAR_SP && c < LIT_UTF8_1_BYTE_CODE_POINT_MAX)
1278+
{
1279+
*buf++ = c;
1280+
}
1281+
else if (c > LIT_UTF8_1_BYTE_CODE_POINT_MAX)
1282+
{
1283+
str_p--;
1284+
ecma_char_t current_char = lit_utf8_read_next (&str_p);
1285+
buf += lit_code_unit_to_utf8 (current_char, (lit_utf8_byte_t *) buf);
1286+
}
1287+
else
1288+
{
1289+
switch (c)
12401290
{
12411291
case LIT_CHAR_BS:
12421292
{
1243-
abbrev = LIT_CHAR_LOWERCASE_B;
1293+
*buf++ = LIT_CHAR_BACKSLASH;
1294+
*buf++ = LIT_CHAR_LOWERCASE_B;
12441295
break;
12451296
}
12461297
case LIT_CHAR_FF:
12471298
{
1248-
abbrev = LIT_CHAR_LOWERCASE_F;
1299+
*buf++ = LIT_CHAR_BACKSLASH;
1300+
*buf++ = LIT_CHAR_LOWERCASE_F;
12491301
break;
12501302
}
12511303
case LIT_CHAR_LF:
12521304
{
1253-
abbrev = LIT_CHAR_LOWERCASE_N;
1305+
*buf++ = LIT_CHAR_BACKSLASH;
1306+
*buf++ = LIT_CHAR_LOWERCASE_N;
12541307
break;
12551308
}
12561309
case LIT_CHAR_CR:
12571310
{
1258-
abbrev = LIT_CHAR_LOWERCASE_R;
1311+
*buf++ = LIT_CHAR_BACKSLASH;
1312+
*buf++ = LIT_CHAR_LOWERCASE_R;
12591313
break;
12601314
}
12611315
case LIT_CHAR_TAB:
12621316
{
1263-
abbrev = LIT_CHAR_LOWERCASE_T;
1317+
*buf++ = LIT_CHAR_BACKSLASH;
1318+
*buf++ = LIT_CHAR_LOWERCASE_T;
12641319
break;
12651320
}
1266-
default:
1321+
default: /* Hexadecimal. */
12671322
{
1268-
JERRY_ASSERT (current_char == LIT_CHAR_BACKSLASH || current_char == LIT_CHAR_DOUBLE_QUOTE);
1269-
1323+
JERRY_ASSERT (c < 0x9f);
1324+
*buf++ = LIT_CHAR_BACKSLASH;
1325+
*buf++ = LIT_CHAR_LOWERCASE_U;
1326+
*buf++ = LIT_CHAR_0;
1327+
*buf++ = LIT_CHAR_0;
1328+
*buf++ = (lit_utf8_byte_t) (LIT_CHAR_0 + (c >> 4)); /* Max range 0-9, hex digits unnecessary. */
1329+
lit_utf8_byte_t c2 = (c & 0xf);
1330+
*buf++ = (lit_utf8_byte_t) (c2 + ((c2 <= 9) ? LIT_CHAR_0 : (LIT_CHAR_LOWERCASE_A - 10)));
12701331
break;
12711332
}
12721333
}
1273-
1274-
lit_utf8_byte_t chars[2] = { LIT_CHAR_BACKSLASH, abbrev };
1275-
1276-
product_str_p = ecma_append_chars_to_string (product_str_p, chars, 2, 2);
12771334
}
1278-
/* 2.c */
1279-
else if (current_char < LIT_CHAR_SP)
1280-
{
1281-
lit_utf8_byte_t chars[6] = { LIT_CHAR_BACKSLASH, LIT_CHAR_LOWERCASE_U, LIT_CHAR_0, LIT_CHAR_0 };
1282-
1283-
JERRY_ASSERT (current_char < 0x9f);
1284-
1285-
chars[4] = (lit_utf8_byte_t) (LIT_CHAR_0 + (current_char >> 4));
1286-
1287-
int last_char = current_char & 0xf;
1288-
last_char += (last_char <= 9) ? LIT_CHAR_0 : (LIT_CHAR_LOWERCASE_A - 10);
1289-
1290-
chars[5] = (lit_utf8_byte_t) last_char;
1291-
1292-
product_str_p = ecma_append_chars_to_string (product_str_p, chars, 6, 6);
1293-
}
1294-
/* 2.d */
1295-
else if (current_char < LIT_UTF8_1_BYTE_CODE_POINT_MAX)
1296-
{
1297-
/* Fast case for ascii characters. */
1298-
lit_utf8_byte_t chars[1] = { (lit_utf8_byte_t) current_char };
1335+
}
12991336

1300-
product_str_p = ecma_append_chars_to_string (product_str_p, chars, 1, 1);
1301-
}
1302-
else
1303-
{
1304-
ecma_string_t *current_char_str_p = ecma_new_ecma_string_from_code_unit (current_char);
1337+
*buf++ = LIT_CHAR_DOUBLE_QUOTE;
13051338

1306-
product_str_p = ecma_concat_ecma_strings (product_str_p, current_char_str_p);
1307-
ecma_deref_ecma_string (current_char_str_p);
1308-
}
1309-
}
1339+
/* Make sure we didn't run off the end or allocated more than we actually wanted. */
1340+
JERRY_ASSERT ((size_t) (buf - buf_begin) == n_bytes);
13101341

1342+
ecma_string_t *product_str_p = ecma_new_ecma_string_from_utf8 ((const lit_utf8_byte_t *) buf_begin,
1343+
(lit_utf8_size_t) (buf - buf_begin));
1344+
jmem_heap_free_block (buf_begin, n_bytes);
13111345
ECMA_FINALIZE_UTF8_STRING (string_buff, string_buff_size);
13121346

1313-
/* 3. */
1314-
product_str_p = ecma_append_magic_string_to_string (product_str_p, LIT_MAGIC_STRING_DOUBLE_QUOTE_CHAR);
1315-
1316-
/* 4. */
13171347
return ecma_make_string_value (product_str_p);
13181348
} /* ecma_builtin_json_quote */
13191349

jerry-core/lit/lit-magic-strings.inc.h

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,9 +19,6 @@
1919

2020
LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING__EMPTY, "")
2121
LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_SPACE_CHAR, " ")
22-
#if !defined (CONFIG_DISABLE_JSON_BUILTIN)
23-
LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_DOUBLE_QUOTE_CHAR, "\"")
24-
#endif
2522
LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_COMMA_CHAR, ",")
2623
#if !defined (CONFIG_DISABLE_REGEXP_BUILTIN)
2724
LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_SLASH_CHAR, "/")

jerry-core/lit/lit-magic-strings.ini

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,6 @@
2424

2525
LIT_MAGIC_STRING__EMPTY = ""
2626
LIT_MAGIC_STRING_SPACE_CHAR = " "
27-
LIT_MAGIC_STRING_DOUBLE_QUOTE_CHAR = "\""
2827
LIT_MAGIC_STRING_COMMA_CHAR = ","
2928
LIT_MAGIC_STRING_SLASH_CHAR = "/"
3029
LIT_MAGIC_STRING_COLON_CHAR = ":"

0 commit comments

Comments
 (0)