[json] Always internalize json string values to avoid memory overhead
Bug: Change-Id: Ie8b269467c8b1c5e97d1da9879f41319a49d5407 Reviewed-on: https://chromium-review.googlesource.com/911793 Commit-Queue: Toon Verwaest <verwaest@chromium.org> Reviewed-by: Igor Sheludko <ishell@chromium.org> Cr-Commit-Position: refs/heads/master@{#51310}
This commit is contained in:
parent
313e33a709
commit
2a5791ce2d
@ -416,7 +416,7 @@ Handle<Object> JsonParser<seq_one_byte>::ParseJsonObject() {
|
|||||||
if (!follow_expected) {
|
if (!follow_expected) {
|
||||||
// If the expected transition failed, parse an internalized string and
|
// If the expected transition failed, parse an internalized string and
|
||||||
// try to find a matching transition.
|
// try to find a matching transition.
|
||||||
key = ParseJsonInternalizedString();
|
key = ParseJsonString();
|
||||||
if (key.is_null()) return ReportUnexpectedCharacter();
|
if (key.is_null()) return ReportUnexpectedCharacter();
|
||||||
|
|
||||||
target = TransitionsAccessor(map).FindTransitionToField(key);
|
target = TransitionsAccessor(map).FindTransitionToField(key);
|
||||||
@ -491,7 +491,7 @@ Handle<Object> JsonParser<seq_one_byte>::ParseJsonObject() {
|
|||||||
Handle<String> key;
|
Handle<String> key;
|
||||||
Handle<Object> value;
|
Handle<Object> value;
|
||||||
|
|
||||||
key = ParseJsonInternalizedString();
|
key = ParseJsonString();
|
||||||
if (key.is_null() || c0_ != ':') return ReportUnexpectedCharacter();
|
if (key.is_null() || c0_ != ':') return ReportUnexpectedCharacter();
|
||||||
|
|
||||||
AdvanceSkipWhitespace();
|
AdvanceSkipWhitespace();
|
||||||
@ -812,7 +812,6 @@ Handle<String> JsonParser<seq_one_byte>::SlowScanJsonString(
|
|||||||
}
|
}
|
||||||
|
|
||||||
template <bool seq_one_byte>
|
template <bool seq_one_byte>
|
||||||
template <bool is_internalized>
|
|
||||||
Handle<String> JsonParser<seq_one_byte>::ScanJsonString() {
|
Handle<String> JsonParser<seq_one_byte>::ScanJsonString() {
|
||||||
DCHECK_EQ('"', c0_);
|
DCHECK_EQ('"', c0_);
|
||||||
Advance();
|
Advance();
|
||||||
@ -821,7 +820,7 @@ Handle<String> JsonParser<seq_one_byte>::ScanJsonString() {
|
|||||||
return factory()->empty_string();
|
return factory()->empty_string();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (seq_one_byte && is_internalized) {
|
if (seq_one_byte) {
|
||||||
// Fast path for existing internalized strings. If the the string being
|
// Fast path for existing internalized strings. If the the string being
|
||||||
// parsed is not a known internalized string, contains backslashes or
|
// parsed is not a known internalized string, contains backslashes or
|
||||||
// unexpectedly reaches the end of string, return with an empty handle.
|
// unexpectedly reaches the end of string, return with an empty handle.
|
||||||
@ -829,9 +828,13 @@ Handle<String> JsonParser<seq_one_byte>::ScanJsonString() {
|
|||||||
// We intentionally use local variables instead of fields, compute hash
|
// We intentionally use local variables instead of fields, compute hash
|
||||||
// while we are iterating a string and manually inline StringTable lookup
|
// while we are iterating a string and manually inline StringTable lookup
|
||||||
// here.
|
// here.
|
||||||
uint32_t running_hash = isolate()->heap()->HashSeed();
|
|
||||||
int position = position_;
|
int position = position_;
|
||||||
uc32 c0 = c0_;
|
uc32 c0 = c0_;
|
||||||
|
uint32_t running_hash = isolate()->heap()->HashSeed();
|
||||||
|
uint32_t index = 0;
|
||||||
|
bool is_array_index = true;
|
||||||
|
|
||||||
do {
|
do {
|
||||||
if (c0 == '\\') {
|
if (c0 == '\\') {
|
||||||
c0_ = c0;
|
c0_ = c0;
|
||||||
@ -845,6 +848,16 @@ Handle<String> JsonParser<seq_one_byte>::ScanJsonString() {
|
|||||||
position_ = position;
|
position_ = position;
|
||||||
return Handle<String>::null();
|
return Handle<String>::null();
|
||||||
}
|
}
|
||||||
|
if (is_array_index) {
|
||||||
|
// With leading zero, the string has to be "0" to be a valid index.
|
||||||
|
if (!IsDecimalDigit(c0) || (position > position_ && index == 0)) {
|
||||||
|
is_array_index = false;
|
||||||
|
} else {
|
||||||
|
int d = c0 - '0';
|
||||||
|
is_array_index = index <= 429496729U - ((d + 3) >> 3);
|
||||||
|
index = (index * 10) + d;
|
||||||
|
}
|
||||||
|
}
|
||||||
running_hash = StringHasher::AddCharacterCore(running_hash,
|
running_hash = StringHasher::AddCharacterCore(running_hash,
|
||||||
static_cast<uint16_t>(c0));
|
static_cast<uint16_t>(c0));
|
||||||
position++;
|
position++;
|
||||||
@ -856,9 +869,15 @@ Handle<String> JsonParser<seq_one_byte>::ScanJsonString() {
|
|||||||
c0 = seq_source_->SeqOneByteStringGet(position);
|
c0 = seq_source_->SeqOneByteStringGet(position);
|
||||||
} while (c0 != '"');
|
} while (c0 != '"');
|
||||||
int length = position - position_;
|
int length = position - position_;
|
||||||
uint32_t hash = (length <= String::kMaxHashCalcLength)
|
uint32_t hash;
|
||||||
? StringHasher::GetHashCore(running_hash)
|
if (is_array_index) {
|
||||||
: static_cast<uint32_t>(length);
|
hash =
|
||||||
|
StringHasher::MakeArrayIndexHash(index, length) >> String::kHashShift;
|
||||||
|
} else if (length <= String::kMaxHashCalcLength) {
|
||||||
|
hash = StringHasher::GetHashCore(running_hash);
|
||||||
|
} else {
|
||||||
|
hash = static_cast<uint32_t>(length);
|
||||||
|
}
|
||||||
Vector<const uint8_t> string_vector(seq_source_->GetChars() + position_,
|
Vector<const uint8_t> string_vector(seq_source_->GetChars() + position_,
|
||||||
length);
|
length);
|
||||||
StringTable* string_table = isolate()->heap()->string_table();
|
StringTable* string_table = isolate()->heap()->string_table();
|
||||||
@ -877,12 +896,8 @@ Handle<String> JsonParser<seq_one_byte>::ScanJsonString() {
|
|||||||
if (!element->IsTheHole(isolate()) &&
|
if (!element->IsTheHole(isolate()) &&
|
||||||
String::cast(element)->IsOneByteEqualTo(string_vector)) {
|
String::cast(element)->IsOneByteEqualTo(string_vector)) {
|
||||||
result = Handle<String>(String::cast(element), isolate());
|
result = Handle<String>(String::cast(element), isolate());
|
||||||
#ifdef DEBUG
|
DCHECK_EQ(result->Hash(),
|
||||||
uint32_t hash_field =
|
(hash << String::kHashShift) >> String::kHashShift);
|
||||||
(hash << String::kHashShift) | String::kIsNotArrayIndexMask;
|
|
||||||
DCHECK_EQ(static_cast<int>(result->Hash()),
|
|
||||||
static_cast<int>(hash_field >> String::kHashShift));
|
|
||||||
#endif
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
entry = StringTable::NextProbe(entry, count++, capacity);
|
entry = StringTable::NextProbe(entry, count++, capacity);
|
||||||
|
@ -75,19 +75,14 @@ class JsonParser BASE_EMBEDDED {
|
|||||||
// literals. The string must only be double-quoted (not single-quoted), and
|
// literals. The string must only be double-quoted (not single-quoted), and
|
||||||
// the only allowed backslash-escapes are ", /, \, b, f, n, r, t and
|
// the only allowed backslash-escapes are ", /, \, b, f, n, r, t and
|
||||||
// four-digit hex escapes (uXXXX). Any other use of backslashes is invalid.
|
// four-digit hex escapes (uXXXX). Any other use of backslashes is invalid.
|
||||||
Handle<String> ParseJsonString() {
|
|
||||||
return ScanJsonString<false>();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool ParseJsonString(Handle<String> expected);
|
bool ParseJsonString(Handle<String> expected);
|
||||||
|
|
||||||
Handle<String> ParseJsonInternalizedString() {
|
Handle<String> ParseJsonString() {
|
||||||
Handle<String> result = ScanJsonString<true>();
|
Handle<String> result = ScanJsonString();
|
||||||
if (result.is_null()) return result;
|
if (result.is_null()) return result;
|
||||||
return factory()->InternalizeString(result);
|
return factory()->InternalizeString(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <bool is_internalized>
|
|
||||||
Handle<String> ScanJsonString();
|
Handle<String> ScanJsonString();
|
||||||
// Creates a new string and copies prefix[start..end] into the beginning
|
// Creates a new string and copies prefix[start..end] into the beginning
|
||||||
// of it. Then scans the rest of the string, adding characters after the
|
// of it. Then scans the rest of the string, adding characters after the
|
||||||
|
Loading…
Reference in New Issue
Block a user