Commit fd42f40b authored by Toon Verwaest's avatar Toon Verwaest Committed by Commit Bot

[json] Specialize json parser on chartype rather than bool seq_one_byte

Change-Id: I34dc911d205ab507f668bfd422eb1838f660a6bf
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/1571624
Commit-Queue: Toon Verwaest <verwaest@chromium.org>
Reviewed-by: 's avatarIgor Sheludko <ishell@chromium.org>
Reviewed-by: 's avatarUlan Degenbaev <ulan@chromium.org>
Cr-Commit-Position: refs/heads/master@{#60964}
parent 30028461
...@@ -3033,9 +3033,9 @@ MaybeLocal<Value> JSON::Parse(Local<Context> context, ...@@ -3033,9 +3033,9 @@ MaybeLocal<Value> JSON::Parse(Local<Context> context,
i::Handle<i::String> string = Utils::OpenHandle(*json_string); i::Handle<i::String> string = Utils::OpenHandle(*json_string);
i::Handle<i::String> source = i::String::Flatten(isolate, string); i::Handle<i::String> source = i::String::Flatten(isolate, string);
i::Handle<i::Object> undefined = isolate->factory()->undefined_value(); i::Handle<i::Object> undefined = isolate->factory()->undefined_value();
auto maybe = source->IsSeqOneByteString() auto maybe = source->IsOneByteRepresentation()
? i::JsonParser<true>::Parse(isolate, source, undefined) ? i::JsonParser<uint8_t>::Parse(isolate, source, undefined)
: i::JsonParser<false>::Parse(isolate, source, undefined); : i::JsonParser<uint16_t>::Parse(isolate, source, undefined);
Local<Value> result; Local<Value> result;
has_pending_exception = !ToLocal<Value>(maybe, &result); has_pending_exception = !ToLocal<Value>(maybe, &result);
RETURN_ON_FAILED_EXECUTION(Value); RETURN_ON_FAILED_EXECUTION(Value);
......
...@@ -22,9 +22,9 @@ BUILTIN(JsonParse) { ...@@ -22,9 +22,9 @@ BUILTIN(JsonParse) {
Object::ToString(isolate, source)); Object::ToString(isolate, source));
string = String::Flatten(isolate, string); string = String::Flatten(isolate, string);
RETURN_RESULT_OR_FAILURE( RETURN_RESULT_OR_FAILURE(
isolate, string->IsSeqOneByteString() isolate, string->IsOneByteRepresentation()
? JsonParser<true>::Parse(isolate, string, reviver) ? JsonParser<uint8_t>::Parse(isolate, string, reviver)
: JsonParser<false>::Parse(isolate, string, reviver)); : JsonParser<uint16_t>::Parse(isolate, string, reviver));
} }
// ES6 section 24.3.2 JSON.stringify. // ES6 section 24.3.2 JSON.stringify.
......
This diff is collapsed.
...@@ -35,9 +35,12 @@ class JsonParseInternalizer { ...@@ -35,9 +35,12 @@ class JsonParseInternalizer {
}; };
// A simple json parser. // A simple json parser.
template <bool seq_one_byte> template <typename Char>
class JsonParser { class JsonParser final {
public: public:
using SeqString = typename CharTraits<Char>::String;
using SeqExternalString = typename CharTraits<Char>::ExternalString;
V8_WARN_UNUSED_RESULT static MaybeHandle<Object> Parse( V8_WARN_UNUSED_RESULT static MaybeHandle<Object> Parse(
Isolate* isolate, Handle<String> source, Handle<Object> reviver) { Isolate* isolate, Handle<String> source, Handle<Object> reviver) {
Handle<Object> result; Handle<Object> result;
...@@ -52,7 +55,10 @@ class JsonParser { ...@@ -52,7 +55,10 @@ class JsonParser {
static const int kEndOfString = -1; static const int kEndOfString = -1;
private: private:
Handle<String> Internalize(int start, int length);
JsonParser(Isolate* isolate, Handle<String> source); JsonParser(Isolate* isolate, Handle<String> source);
~JsonParser();
// Parse a string containing a single JSON value. // Parse a string containing a single JSON value.
MaybeHandle<Object> ParseJson(); MaybeHandle<Object> ParseJson();
...@@ -136,20 +142,44 @@ class JsonParser { ...@@ -136,20 +142,44 @@ class JsonParser {
static const int kInitialSpecialStringLength = 32; static const int kInitialSpecialStringLength = 32;
static const int kPretenureTreshold = 100 * 1024; static const int kPretenureTreshold = 100 * 1024;
static void UpdatePointersCallback(v8::Isolate* v8_isolate, v8::GCType type,
v8::GCCallbackFlags flags, void* parser) {
reinterpret_cast<JsonParser<Char>*>(parser)->UpdatePointers();
}
void UpdatePointers() {
DisallowHeapAllocation no_gc;
const Char* chars = Handle<SeqString>::cast(source_)->GetChars(no_gc);
if (chars_ != chars) {
chars_ = chars;
}
}
private: private:
static const bool kIsOneByte = sizeof(Char) == 1;
Zone* zone() { return &zone_; } Zone* zone() { return &zone_; }
void CommitStateToJsonObject(Handle<JSObject> json_object, Handle<Map> map, void CommitStateToJsonObject(Handle<JSObject> json_object, Handle<Map> map,
Vector<const Handle<Object>> properties); Vector<const Handle<Object>> properties);
Handle<String> source_;
int source_length_;
Handle<SeqOneByteString> seq_source_;
AllocationType allocation_;
Isolate* isolate_; Isolate* isolate_;
Zone zone_; Zone zone_;
AllocationType allocation_;
Handle<JSFunction> object_constructor_; Handle<JSFunction> object_constructor_;
Handle<String> source_;
int offset_;
int length_;
// Cached pointer to the raw chars in source. In case source is on-heap, we
// register an UpdatePointers callback. For this reason, chars_ should never
// be locally cached across a possible allocation. The scope in which we
// cache chars has to be guarded by a DisallowHeapAllocation scope.
// TODO(verwaest): Move chars_ and functions that operate over chars to a
// separate helper class that makes it clear that all functions need to be
// guarded.
const Char* chars_;
uc32 c0_; uc32 c0_;
int position_; int position_;
...@@ -157,9 +187,15 @@ class JsonParser { ...@@ -157,9 +187,15 @@ class JsonParser {
ZoneVector<Handle<Object>> properties_; ZoneVector<Handle<Object>> properties_;
}; };
template <>
Handle<String> JsonParser<uint8_t>::Internalize(int start, int length);
template <>
Handle<String> JsonParser<uint16_t>::Internalize(int start, int length);
// Explicit instantiation declarations. // Explicit instantiation declarations.
extern template class JsonParser<true>; extern template class JsonParser<uint8_t>;
extern template class JsonParser<false>; extern template class JsonParser<uint16_t>;
} // namespace internal } // namespace internal
} // namespace v8 } // namespace v8
......
...@@ -6292,7 +6292,7 @@ JSRegExp::Flags RegExpFlagsFromString(Isolate* isolate, Handle<String> flags, ...@@ -6292,7 +6292,7 @@ JSRegExp::Flags RegExpFlagsFromString(Isolate* isolate, Handle<String> flags,
DisallowHeapAllocation no_gc; DisallowHeapAllocation no_gc;
SeqOneByteString seq_flags = SeqOneByteString::cast(*flags); SeqOneByteString seq_flags = SeqOneByteString::cast(*flags);
for (int i = 0; i < length; i++) { for (int i = 0; i < length; i++) {
JSRegExp::Flag flag = CharToFlag(seq_flags.SeqOneByteStringGet(i)); JSRegExp::Flag flag = CharToFlag(seq_flags.Get(i));
// Duplicate or invalid flag. // Duplicate or invalid flag.
if (value & flag) return JSRegExp::Flags(0); if (value & flag) return JSRegExp::Flags(0);
value |= flag; value |= flag;
......
...@@ -323,24 +323,22 @@ uint16_t String::Get(int index) { ...@@ -323,24 +323,22 @@ uint16_t String::Get(int index) {
DCHECK(index >= 0 && index < length()); DCHECK(index >= 0 && index < length());
switch (StringShape(*this).full_representation_tag()) { switch (StringShape(*this).full_representation_tag()) {
case kSeqStringTag | kOneByteStringTag: case kSeqStringTag | kOneByteStringTag:
return SeqOneByteString::cast(*this)->SeqOneByteStringGet(index); return SeqOneByteString::cast(*this)->Get(index);
case kSeqStringTag | kTwoByteStringTag: case kSeqStringTag | kTwoByteStringTag:
return SeqTwoByteString::cast(*this)->SeqTwoByteStringGet(index); return SeqTwoByteString::cast(*this)->Get(index);
case kConsStringTag | kOneByteStringTag: case kConsStringTag | kOneByteStringTag:
case kConsStringTag | kTwoByteStringTag: case kConsStringTag | kTwoByteStringTag:
return ConsString::cast(*this)->ConsStringGet(index); return ConsString::cast(*this)->Get(index);
case kExternalStringTag | kOneByteStringTag: case kExternalStringTag | kOneByteStringTag:
return ExternalOneByteString::cast(*this)->ExternalOneByteStringGet( return ExternalOneByteString::cast(*this)->Get(index);
index);
case kExternalStringTag | kTwoByteStringTag: case kExternalStringTag | kTwoByteStringTag:
return ExternalTwoByteString::cast(*this)->ExternalTwoByteStringGet( return ExternalTwoByteString::cast(*this)->Get(index);
index);
case kSlicedStringTag | kOneByteStringTag: case kSlicedStringTag | kOneByteStringTag:
case kSlicedStringTag | kTwoByteStringTag: case kSlicedStringTag | kTwoByteStringTag:
return SlicedString::cast(*this)->SlicedStringGet(index); return SlicedString::cast(*this)->Get(index);
case kThinStringTag | kOneByteStringTag: case kThinStringTag | kOneByteStringTag:
case kThinStringTag | kTwoByteStringTag: case kThinStringTag | kTwoByteStringTag:
return ThinString::cast(*this)->ThinStringGet(index); return ThinString::cast(*this)->Get(index);
default: default:
break; break;
} }
...@@ -455,7 +453,7 @@ uint32_t String::ToValidIndex(Object number) { ...@@ -455,7 +453,7 @@ uint32_t String::ToValidIndex(Object number) {
return index; return index;
} }
uint16_t SeqOneByteString::SeqOneByteStringGet(int index) { uint8_t SeqOneByteString::Get(int index) {
DCHECK(index >= 0 && index < length()); DCHECK(index >= 0 && index < length());
return READ_BYTE_FIELD(*this, kHeaderSize + index * kCharSize); return READ_BYTE_FIELD(*this, kHeaderSize + index * kCharSize);
} }
...@@ -484,7 +482,7 @@ uc16* SeqTwoByteString::GetChars(const DisallowHeapAllocation& no_gc) { ...@@ -484,7 +482,7 @@ uc16* SeqTwoByteString::GetChars(const DisallowHeapAllocation& no_gc) {
return reinterpret_cast<uc16*>(FIELD_ADDR(*this, kHeaderSize)); return reinterpret_cast<uc16*>(FIELD_ADDR(*this, kHeaderSize));
} }
uint16_t SeqTwoByteString::SeqTwoByteStringGet(int index) { uint16_t SeqTwoByteString::Get(int index) {
DCHECK(index >= 0 && index < length()); DCHECK(index >= 0 && index < length());
return READ_UINT16_FIELD(*this, kHeaderSize + index * kShortSize); return READ_UINT16_FIELD(*this, kHeaderSize + index * kShortSize);
} }
...@@ -618,7 +616,7 @@ const uint8_t* ExternalOneByteString::GetChars() { ...@@ -618,7 +616,7 @@ const uint8_t* ExternalOneByteString::GetChars() {
return reinterpret_cast<const uint8_t*>(resource()->data()); return reinterpret_cast<const uint8_t*>(resource()->data());
} }
uint16_t ExternalOneByteString::ExternalOneByteStringGet(int index) { uint8_t ExternalOneByteString::Get(int index) {
DCHECK(index >= 0 && index < length()); DCHECK(index >= 0 && index < length());
return GetChars()[index]; return GetChars()[index];
} }
...@@ -652,7 +650,7 @@ void ExternalTwoByteString::set_resource( ...@@ -652,7 +650,7 @@ void ExternalTwoByteString::set_resource(
const uint16_t* ExternalTwoByteString::GetChars() { return resource()->data(); } const uint16_t* ExternalTwoByteString::GetChars() { return resource()->data(); }
uint16_t ExternalTwoByteString::ExternalTwoByteStringGet(int index) { uint16_t ExternalTwoByteString::Get(int index) {
DCHECK(index >= 0 && index < length()); DCHECK(index >= 0 && index < length());
return GetChars()[index]; return GetChars()[index];
} }
......
...@@ -90,7 +90,7 @@ class StringTable : public HashTable<StringTable, StringTableShape> { ...@@ -90,7 +90,7 @@ class StringTable : public HashTable<StringTable, StringTableShape> {
static const int kMinShrinkCapacity = kMinCapacity; static const int kMinShrinkCapacity = kMinCapacity;
private: private:
template <bool seq_one_byte> template <typename char_type>
friend class JsonParser; friend class JsonParser;
OBJECT_CONSTRUCTORS(StringTable, HashTable<StringTable, StringTableShape>); OBJECT_CONSTRUCTORS(StringTable, HashTable<StringTable, StringTableShape>);
......
...@@ -1325,7 +1325,7 @@ void SeqTwoByteString::clear_padding() { ...@@ -1325,7 +1325,7 @@ void SeqTwoByteString::clear_padding() {
SizeFor(length()) - data_size); SizeFor(length()) - data_size);
} }
uint16_t ConsString::ConsStringGet(int index) { uint16_t ConsString::Get(int index) {
DCHECK(index >= 0 && index < this->length()); DCHECK(index >= 0 && index < this->length());
// Check for a flattened cons string // Check for a flattened cons string
...@@ -1354,9 +1354,9 @@ uint16_t ConsString::ConsStringGet(int index) { ...@@ -1354,9 +1354,9 @@ uint16_t ConsString::ConsStringGet(int index) {
UNREACHABLE(); UNREACHABLE();
} }
uint16_t ThinString::ThinStringGet(int index) { return actual()->Get(index); } uint16_t ThinString::Get(int index) { return actual()->Get(index); }
uint16_t SlicedString::SlicedStringGet(int index) { uint16_t SlicedString::Get(int index) {
return parent()->Get(offset() + index); return parent()->Get(offset() + index);
} }
......
...@@ -507,7 +507,7 @@ class SeqOneByteString : public SeqString { ...@@ -507,7 +507,7 @@ class SeqOneByteString : public SeqString {
static const bool kHasOneByteEncoding = true; static const bool kHasOneByteEncoding = true;
// Dispatched behavior. // Dispatched behavior.
inline uint16_t SeqOneByteStringGet(int index); inline uint8_t Get(int index);
inline void SeqOneByteStringSet(int index, uint16_t value); inline void SeqOneByteStringSet(int index, uint16_t value);
// Get the address of the characters in this string. // Get the address of the characters in this string.
...@@ -548,7 +548,7 @@ class SeqTwoByteString : public SeqString { ...@@ -548,7 +548,7 @@ class SeqTwoByteString : public SeqString {
static const bool kHasOneByteEncoding = false; static const bool kHasOneByteEncoding = false;
// Dispatched behavior. // Dispatched behavior.
inline uint16_t SeqTwoByteStringGet(int index); inline uint16_t Get(int index);
inline void SeqTwoByteStringSet(int index, uint16_t value); inline void SeqTwoByteStringSet(int index, uint16_t value);
// Get the address of the characters in this string. // Get the address of the characters in this string.
...@@ -610,7 +610,7 @@ class ConsString : public String { ...@@ -610,7 +610,7 @@ class ConsString : public String {
WriteBarrierMode mode = UPDATE_WRITE_BARRIER); WriteBarrierMode mode = UPDATE_WRITE_BARRIER);
// Dispatched behavior. // Dispatched behavior.
V8_EXPORT_PRIVATE uint16_t ConsStringGet(int index); V8_EXPORT_PRIVATE uint16_t Get(int index);
DECL_CAST(ConsString) DECL_CAST(ConsString)
...@@ -642,7 +642,7 @@ class ThinString : public String { ...@@ -642,7 +642,7 @@ class ThinString : public String {
inline void set_actual(String s, inline void set_actual(String s,
WriteBarrierMode mode = UPDATE_WRITE_BARRIER); WriteBarrierMode mode = UPDATE_WRITE_BARRIER);
V8_EXPORT_PRIVATE uint16_t ThinStringGet(int index); V8_EXPORT_PRIVATE uint16_t Get(int index);
DECL_CAST(ThinString) DECL_CAST(ThinString)
DECL_VERIFIER(ThinString) DECL_VERIFIER(ThinString)
...@@ -676,7 +676,7 @@ class SlicedString : public String { ...@@ -676,7 +676,7 @@ class SlicedString : public String {
inline void set_offset(int offset); inline void set_offset(int offset);
// Dispatched behavior. // Dispatched behavior.
V8_EXPORT_PRIVATE uint16_t SlicedStringGet(int index); V8_EXPORT_PRIVATE uint16_t Get(int index);
DECL_CAST(SlicedString) DECL_CAST(SlicedString)
...@@ -758,7 +758,7 @@ class ExternalOneByteString : public ExternalString { ...@@ -758,7 +758,7 @@ class ExternalOneByteString : public ExternalString {
inline const uint8_t* GetChars(); inline const uint8_t* GetChars();
// Dispatched behavior. // Dispatched behavior.
inline uint16_t ExternalOneByteStringGet(int index); inline uint8_t Get(int index);
DECL_CAST(ExternalOneByteString) DECL_CAST(ExternalOneByteString)
...@@ -793,7 +793,7 @@ class ExternalTwoByteString : public ExternalString { ...@@ -793,7 +793,7 @@ class ExternalTwoByteString : public ExternalString {
inline const uint16_t* GetChars(); inline const uint16_t* GetChars();
// Dispatched behavior. // Dispatched behavior.
inline uint16_t ExternalTwoByteStringGet(int index); inline uint16_t Get(int index);
// For regexp code. // For regexp code.
inline const uint16_t* ExternalTwoByteStringGetData(unsigned start); inline const uint16_t* ExternalTwoByteStringGetData(unsigned start);
...@@ -895,6 +895,21 @@ class StringCharacterStream { ...@@ -895,6 +895,21 @@ class StringCharacterStream {
DISALLOW_COPY_AND_ASSIGN(StringCharacterStream); DISALLOW_COPY_AND_ASSIGN(StringCharacterStream);
}; };
template <typename Char>
struct CharTraits;
template <>
struct CharTraits<uint8_t> {
using String = SeqOneByteString;
using ExternalString = ExternalOneByteString;
};
template <>
struct CharTraits<uint16_t> {
using String = SeqTwoByteString;
using ExternalString = ExternalTwoByteString;
};
} // namespace internal } // namespace internal
} // namespace v8 } // namespace v8
......
...@@ -49,21 +49,6 @@ namespace { ...@@ -49,21 +49,6 @@ namespace {
const unibrow::uchar kUtf8Bom = 0xFEFF; const unibrow::uchar kUtf8Bom = 0xFEFF;
} // namespace } // namespace
template <typename Char>
struct CharTraits;
template <>
struct CharTraits<uint8_t> {
using String = SeqOneByteString;
using ExternalString = ExternalOneByteString;
};
template <>
struct CharTraits<uint16_t> {
using String = SeqTwoByteString;
using ExternalString = ExternalTwoByteString;
};
template <typename Char> template <typename Char>
struct Range { struct Range {
const Char* start; const Char* start;
......
// Copyright 2019 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
var s = 'abcabcabcabcabc["possibly a sliced string"]'.slice(15)
assertEquals(["possibly a sliced string"], JSON.parse(s));
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment