@ -4546,42 +4546,53 @@ static MaybeObject* Runtime_URIUnescape(Arguments args) {
static const unsigned int kQuoteTableLength = 128u ;
static const unsigned int kQuoteTableLength = 128u ;
static const char * const JsonQuotes [ kQuoteTableLength ] = {
static const int kJsonQuotesCharactersPerEntry = 8 ;
" \\ u0000 " , " \\ u0001 " , " \\ u0002 " , " \\ u0003 " ,
static const char * const JsonQuotes =
" \\ u0004 " , " \\ u0005 " , " \\ u0006 " , " \\ u0007 " ,
" \\ u0000 \\ u0001 \\ u0002 \\ u0003 "
" \\ b " , " \\ t " , " \\ n " , " \\ u000b " ,
" \\ u0004 \\ u0005 \\ u0006 \\ u0007 "
" \\ f " , " \\ r " , " \\ u000e " , " \\ u000f " ,
" \\ b \\ t \\ n \\ u000b "
" \\ u0010 " , " \\ u0011 " , " \\ u0012 " , " \\ u0013 " ,
" \\ f \\ r \\ u000e \\ u000f "
" \\ u0014 " , " \\ u0015 " , " \\ u0016 " , " \\ u0017 " ,
" \\ u0010 \\ u0011 \\ u0012 \\ u0013 "
" \\ u0018 " , " \\ u0019 " , " \\ u001a " , " \\ u001b " ,
" \\ u0014 \\ u0015 \\ u0016 \\ u0017 "
" \\ u001c " , " \\ u001d " , " \\ u001e " , " \\ u001f " ,
" \\ u0018 \\ u0019 \\ u001a \\ u001b "
NULL , NULL , " \\ \" " , NULL ,
" \\ u001c \\ u001d \\ u001e \\ u001f "
NULL , NULL , NULL , NULL ,
" ! \\ \" # "
NULL , NULL , NULL , NULL ,
" $ % & ' "
NULL , NULL , NULL , NULL ,
" ( ) * + "
NULL , NULL , NULL , NULL ,
" , - . / "
NULL , NULL , NULL , NULL ,
" 0 1 2 3 "
NULL , NULL , NULL , NULL ,
" 4 5 6 7 "
NULL , NULL , NULL , NULL ,
" 8 9 : ; "
NULL , NULL , NULL , NULL ,
" < = > ? "
NULL , NULL , NULL , NULL ,
" @ A B C "
NULL , NULL , NULL , NULL ,
" D E F G "
NULL , NULL , NULL , NULL ,
" H I J K "
NULL , NULL , NULL , NULL ,
" L M N O "
NULL , NULL , NULL , NULL ,
" P Q R S "
NULL , NULL , NULL , NULL ,
" T U V W "
" \\ \\ " , NULL , NULL , NULL ,
" X Y Z [ "
NULL , NULL , NULL , NULL ,
" \\ \\ ] ^ _ "
NULL , NULL , NULL , NULL ,
" ` a b c "
NULL , NULL , NULL , NULL ,
" d e f g "
NULL , NULL , NULL , NULL ,
" h i j k "
NULL , NULL , NULL , NULL ,
" l m n o "
NULL , NULL , NULL , NULL ,
" p q r s "
NULL , NULL , NULL , NULL ,
" t u v w "
NULL , NULL , NULL , NULL ,
" x y z { "
} ;
" | } ~ \177 " ;
// For a string that is less than 32k characters it should always be
// possible to allocate it in new space.
static const int kMaxGuaranteedNewSpaceString = 32 * 1024 ;
// Doing JSON quoting cannot make the string more than this many times larger.
static const int kJsonQuoteWorstCaseBlowup = 6 ;
// Covers the entire ASCII range (all other characters are unchanged by JSON
// quoting).
static const byte JsonQuoteLengths [ kQuoteTableLength ] = {
static const byte JsonQuoteLengths [ kQuoteTableLength ] = {
6 , 6 , 6 , 6 , 6 , 6 , 6 , 6 ,
6 , 6 , 6 , 6 , 6 , 6 , 6 , 6 ,
2 , 2 , 2 , 6 , 2 , 2 , 6 , 6 ,
2 , 2 , 2 , 6 , 2 , 2 , 6 , 6 ,
@ -4602,18 +4613,6 @@ static const byte JsonQuoteLengths[kQuoteTableLength] = {
} ;
} ;
template < typename Char >
Char * WriteString ( Char * dst , const char * src_string ) {
char c ;
for ( c = * src_string ; c ; c = * src_string ) {
* dst = c ;
dst + + ;
src_string + + ;
}
return dst ;
}
template < typename StringType >
template < typename StringType >
MaybeObject * AllocateRawString ( int length ) ;
MaybeObject * AllocateRawString ( int length ) ;
@ -4631,58 +4630,104 @@ MaybeObject* AllocateRawString<SeqAsciiString>(int length) {
template < typename Char , typename StringType >
template < typename Char , typename StringType >
static MaybeObject * QuoteJsonString ( Vector < const Char > characters ) {
static MaybeObject * Slow QuoteJsonString( Vector < const Char > characters ) {
int length = characters . length ( ) ;
int length = characters . length ( ) ;
int quoted_length = 0 ;
const Char * read_cursor = characters . start ( ) ;
for ( int i = 0 ; i < length ; i + + ) {
const Char * end = read_cursor + length ;
unsigned int c = characters [ i ] ;
const int kSpaceForQuotes = 2 ;
if ( sizeof ( Char ) > 1u ) {
int quoted_length = kSpaceForQuotes ;
quoted_length + = ( c > = kQuoteTableLength ) ? 1 : JsonQuoteLengths [ c ] ;
while ( read_cursor < end ) {
Char c = * ( read_cursor + + ) ;
if ( sizeof ( Char ) > 1u & & static_cast < unsigned > ( c ) > = kQuoteTableLength ) {
quoted_length + + ;
} else {
} else {
quoted_length + = JsonQuoteLengths [ c ] ;
quoted_length + = JsonQuoteLengths [ static_cast < unsigned > ( c ) ] ;
}
}
}
}
Counters : : quote_json_char_count . Increment ( length ) ;
// Add space for quotes.
quoted_length + = 2 ;
MaybeObject * new_alloc = AllocateRawString < StringType > ( quoted_length ) ;
MaybeObject * new_alloc = AllocateRawString < StringType > ( quoted_length ) ;
Object * new_object ;
Object * new_object ;
if ( ! new_alloc - > ToObject ( & new_object ) ) {
if ( ! new_alloc - > ToObject ( & new_object ) ) {
Counters : : quote_json_char_recount . Increment ( length ) ;
return new_alloc ;
return new_alloc ;
}
}
StringType * new_string = StringType : : cast ( new_object ) ;
StringType * new_string = StringType : : cast ( new_object ) ;
Char * write_cursor = reinterpret_cast < Char * > (
new_string - > address ( ) + SeqAsciiString : : kHeaderSize ) ;
* ( write_cursor + + ) = ' " ' ;
read_cursor = characters . start ( ) ;
while ( read_cursor < end ) {
Char c = * ( read_cursor + + ) ;
if ( sizeof ( Char ) > 1u & & static_cast < unsigned > ( c ) > = kQuoteTableLength ) {
* ( write_cursor + + ) = c ;
} else {
int len = JsonQuoteLengths [ static_cast < unsigned > ( c ) ] ;
const char * replacement = JsonQuotes +
static_cast < unsigned > ( c ) * kJsonQuotesCharactersPerEntry ;
for ( int i = 0 ; i < len ; i + + ) {
* write_cursor + + = * replacement + + ;
}
}
}
* ( write_cursor + + ) = ' " ' ;
return new_string ;
}
template < typename Char , typename StringType >
static MaybeObject * QuoteJsonString ( Vector < const Char > characters ) {
int length = characters . length ( ) ;
Counters : : quote_json_char_count . Increment ( length ) ;
const int kSpaceForQuotes = 2 ;
int worst_case_length = length * kJsonQuoteWorstCaseBlowup + kSpaceForQuotes ;
if ( worst_case_length > kMaxGuaranteedNewSpaceString ) {
return SlowQuoteJsonString < Char , StringType > ( characters ) ;
}
MaybeObject * new_alloc = AllocateRawString < StringType > ( worst_case_length ) ;
Object * new_object ;
if ( ! new_alloc - > ToObject ( & new_object ) ) {
return new_alloc ;
}
StringType * new_string = StringType : : cast ( new_object ) ;
ASSERT ( Heap : : new_space ( ) - > Contains ( new_string ) ) ;
STATIC_ASSERT ( SeqTwoByteString : : kHeaderSize = = SeqAsciiString : : kHeaderSize ) ;
STATIC_ASSERT ( SeqTwoByteString : : kHeaderSize = = SeqAsciiString : : kHeaderSize ) ;
Char * write_cursor = reinterpret_cast < Char * > (
Char * write_cursor = reinterpret_cast < Char * > (
new_string - > address ( ) + SeqAsciiString : : kHeaderSize ) ;
new_string - > address ( ) + SeqAsciiString : : kHeaderSize ) ;
* ( write_cursor + + ) = ' " ' ;
* ( write_cursor + + ) = ' " ' ;
const Char * read_cursor = characters . start ( ) ;
const Char * read_cursor = characters . start ( ) ;
if ( quoted_length = = length + 2 ) {
CopyChars ( write_cursor , read_cursor , length ) ;
write_cursor + = length ;
} else {
const Char * end = read_cursor + length ;
const Char * end = read_cursor + length ;
while ( read_cursor < end ) {
while ( read_cursor < end ) {
Char c = * ( read_cursor + + ) ;
Char c = * ( read_cursor + + ) ;
if ( sizeof ( Char ) > 1u & & static_cast < unsigned > ( c ) > = kQuoteTableLength ) {
if ( sizeof ( Char ) > 1u & & static_cast < unsigned > ( c ) > = kQuoteTableLength ) {
* ( write_cursor + + ) = c ;
* ( write_cursor + + ) = c ;
} else {
} else {
const char * replacement = JsonQuotes [ static_cast < unsigned > ( c ) ] ;
int len = JsonQuoteLengths [ static_cast < unsigned > ( c ) ] ;
if ( ! replacement ) {
const char * replacement = JsonQuotes +
* ( write_cursor + + ) = c ;
static_cast < unsigned > ( c ) * kJsonQuotesCharactersPerEntry ;
} else {
write_cursor [ 0 ] = replacement [ 0 ] ;
write_cursor = WriteString ( write_cursor , replacement ) ;
if ( len > 1 ) {
write_cursor [ 1 ] = replacement [ 1 ] ;
if ( len > 2 ) {
ASSERT ( len = = 6 ) ;
write_cursor [ 2 ] = replacement [ 2 ] ;
write_cursor [ 3 ] = replacement [ 3 ] ;
write_cursor [ 4 ] = replacement [ 4 ] ;
write_cursor [ 5 ] = replacement [ 5 ] ;
}
}
}
}
write_cursor + = len ;
}
}
}
}
* ( write_cursor + + ) = ' " ' ;
* ( write_cursor + + ) = ' " ' ;
ASSERT_EQ ( SeqAsciiString : : kHeaderSize + quoted_length * sizeof ( Char ) ,
reinterpret_cast < Address > ( write_cursor ) - new_string - > address ( ) ) ;
int final_length =
write_cursor - reinterpret_cast < Char * > (
new_string - > address ( ) + SeqAsciiString : : kHeaderSize ) ;
Heap : : new_space ( ) - > ShrinkStringAtAllocationBoundary < StringType > ( new_string ,
final_length ) ;
return new_string ;
return new_string ;
}
}