| OLD | NEW |
| 1 // Copyright 2011 the V8 project authors. All rights reserved. | 1 // Copyright 2011 the V8 project authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #ifndef V8_JSON_PARSER_H_ | 5 #ifndef V8_JSON_PARSER_H_ |
| 6 #define V8_JSON_PARSER_H_ | 6 #define V8_JSON_PARSER_H_ |
| 7 | 7 |
| 8 #include "src/v8.h" | 8 #include "src/v8.h" |
| 9 | 9 |
| 10 #include "src/char-predicates-inl.h" | 10 #include "src/char-predicates-inl.h" |
| 11 #include "src/conversions.h" | 11 #include "src/conversions.h" |
| 12 #include "src/heap/spaces-inl.h" | 12 #include "src/heap/spaces-inl.h" |
| 13 #include "src/messages.h" | 13 #include "src/messages.h" |
| 14 #include "src/token.h" | 14 #include "src/token.h" |
| 15 | 15 |
| 16 namespace v8 { | 16 namespace v8 { |
| 17 namespace internal { | 17 namespace internal { |
| 18 | 18 |
| 19 // A simple json parser. | 19 // A simple json parser. |
| 20 template <bool seq_ascii> | 20 template <bool seq_one_byte> |
| 21 class JsonParser BASE_EMBEDDED { | 21 class JsonParser BASE_EMBEDDED { |
| 22 public: | 22 public: |
| 23 MUST_USE_RESULT static MaybeHandle<Object> Parse(Handle<String> source) { | 23 MUST_USE_RESULT static MaybeHandle<Object> Parse(Handle<String> source) { |
| 24 return JsonParser(source).ParseJson(); | 24 return JsonParser(source).ParseJson(); |
| 25 } | 25 } |
| 26 | 26 |
| 27 static const int kEndOfString = -1; | 27 static const int kEndOfString = -1; |
| 28 | 28 |
| 29 private: | 29 private: |
| 30 explicit JsonParser(Handle<String> source) | 30 explicit JsonParser(Handle<String> source) |
| 31 : source_(source), | 31 : source_(source), |
| 32 source_length_(source->length()), | 32 source_length_(source->length()), |
| 33 isolate_(source->map()->GetHeap()->isolate()), | 33 isolate_(source->map()->GetHeap()->isolate()), |
| 34 factory_(isolate_->factory()), | 34 factory_(isolate_->factory()), |
| 35 zone_(isolate_), | 35 zone_(isolate_), |
| 36 object_constructor_(isolate_->native_context()->object_function(), | 36 object_constructor_(isolate_->native_context()->object_function(), |
| 37 isolate_), | 37 isolate_), |
| 38 position_(-1) { | 38 position_(-1) { |
| 39 source_ = String::Flatten(source_); | 39 source_ = String::Flatten(source_); |
| 40 pretenure_ = (source_length_ >= kPretenureTreshold) ? TENURED : NOT_TENURED; | 40 pretenure_ = (source_length_ >= kPretenureTreshold) ? TENURED : NOT_TENURED; |
| 41 | 41 |
| 42 // Optimized fast case where we only have ASCII characters. | 42 // Optimized fast case where we only have Latin1 characters. |
| 43 if (seq_ascii) { | 43 if (seq_one_byte) { |
| 44 seq_source_ = Handle<SeqOneByteString>::cast(source_); | 44 seq_source_ = Handle<SeqOneByteString>::cast(source_); |
| 45 } | 45 } |
| 46 } | 46 } |
| 47 | 47 |
| 48 // Parse a string containing a single JSON value. | 48 // Parse a string containing a single JSON value. |
| 49 MaybeHandle<Object> ParseJson(); | 49 MaybeHandle<Object> ParseJson(); |
| 50 | 50 |
| 51 inline void Advance() { | 51 inline void Advance() { |
| 52 position_++; | 52 position_++; |
| 53 if (position_ >= source_length_) { | 53 if (position_ >= source_length_) { |
| 54 c0_ = kEndOfString; | 54 c0_ = kEndOfString; |
| 55 } else if (seq_ascii) { | 55 } else if (seq_one_byte) { |
| 56 c0_ = seq_source_->SeqOneByteStringGet(position_); | 56 c0_ = seq_source_->SeqOneByteStringGet(position_); |
| 57 } else { | 57 } else { |
| 58 c0_ = source_->Get(position_); | 58 c0_ = source_->Get(position_); |
| 59 } | 59 } |
| 60 } | 60 } |
| 61 | 61 |
| 62 // The JSON lexical grammar is specified in the ECMAScript 5 standard, | 62 // The JSON lexical grammar is specified in the ECMAScript 5 standard, |
| 63 // section 15.12.1.1. The only allowed whitespace characters between tokens | 63 // section 15.12.1.1. The only allowed whitespace characters between tokens |
| 64 // are tab, carriage-return, newline and space. | 64 // are tab, carriage-return, newline and space. |
| 65 | 65 |
| (...skipping 30 matching lines...) Expand all Loading... |
| 96 // four-digit hex escapes (uXXXX). Any other use of backslashes is invalid. | 96 // four-digit hex escapes (uXXXX). Any other use of backslashes is invalid. |
| 97 Handle<String> ParseJsonString() { | 97 Handle<String> ParseJsonString() { |
| 98 return ScanJsonString<false>(); | 98 return ScanJsonString<false>(); |
| 99 } | 99 } |
| 100 | 100 |
| 101 bool ParseJsonString(Handle<String> expected) { | 101 bool ParseJsonString(Handle<String> expected) { |
| 102 int length = expected->length(); | 102 int length = expected->length(); |
| 103 if (source_->length() - position_ - 1 > length) { | 103 if (source_->length() - position_ - 1 > length) { |
| 104 DisallowHeapAllocation no_gc; | 104 DisallowHeapAllocation no_gc; |
| 105 String::FlatContent content = expected->GetFlatContent(); | 105 String::FlatContent content = expected->GetFlatContent(); |
| 106 if (content.IsAscii()) { | 106 if (content.IsOneByte()) { |
| 107 DCHECK_EQ('"', c0_); | 107 DCHECK_EQ('"', c0_); |
| 108 const uint8_t* input_chars = seq_source_->GetChars() + position_ + 1; | 108 const uint8_t* input_chars = seq_source_->GetChars() + position_ + 1; |
| 109 const uint8_t* expected_chars = content.ToOneByteVector().start(); | 109 const uint8_t* expected_chars = content.ToOneByteVector().start(); |
| 110 for (int i = 0; i < length; i++) { | 110 for (int i = 0; i < length; i++) { |
| 111 uint8_t c0 = input_chars[i]; | 111 uint8_t c0 = input_chars[i]; |
| 112 if (c0 != expected_chars[i] || | 112 if (c0 != expected_chars[i] || |
| 113 c0 == '"' || c0 < 0x20 || c0 == '\\') { | 113 c0 == '"' || c0 < 0x20 || c0 == '\\') { |
| 114 return false; | 114 return false; |
| 115 } | 115 } |
| 116 } | 116 } |
| 117 if (input_chars[length] == '"') { | 117 if (input_chars[length] == '"') { |
| 118 position_ = position_ + length + 1; | 118 position_ = position_ + length + 1; |
| 119 AdvanceSkipWhitespace(); | 119 AdvanceSkipWhitespace(); |
| 120 return true; | 120 return true; |
| 121 } | 121 } |
| 122 } | 122 } |
| 123 } | 123 } |
| 124 return false; | 124 return false; |
| 125 } | 125 } |
| 126 | 126 |
| 127 Handle<String> ParseJsonInternalizedString() { | 127 Handle<String> ParseJsonInternalizedString() { |
| 128 return ScanJsonString<true>(); | 128 return ScanJsonString<true>(); |
| 129 } | 129 } |
| 130 | 130 |
| 131 template <bool is_internalized> | 131 template <bool is_internalized> |
| 132 Handle<String> ScanJsonString(); | 132 Handle<String> ScanJsonString(); |
| 133 // Creates a new string and copies prefix[start..end] into the beginning | 133 // Creates a new string and copies prefix[start..end] into the beginning |
| 134 // of it. Then scans the rest of the string, adding characters after the | 134 // of it. Then scans the rest of the string, adding characters after the |
| 135 // prefix. Called by ScanJsonString when reaching a '\' or non-ASCII char. | 135 // prefix. Called by ScanJsonString when reaching a '\' or non-Latin1 char. |
| 136 template <typename StringType, typename SinkChar> | 136 template <typename StringType, typename SinkChar> |
| 137 Handle<String> SlowScanJsonString(Handle<String> prefix, int start, int end); | 137 Handle<String> SlowScanJsonString(Handle<String> prefix, int start, int end); |
| 138 | 138 |
| 139 // A JSON number (production JSONNumber) is a subset of the valid JavaScript | 139 // A JSON number (production JSONNumber) is a subset of the valid JavaScript |
| 140 // decimal number literals. | 140 // decimal number literals. |
| 141 // It includes an optional minus sign, must have at least one | 141 // It includes an optional minus sign, must have at least one |
| 142 // digit before and after a decimal point, may not have prefixed zeros (unless | 142 // digit before and after a decimal point, may not have prefixed zeros (unless |
| 143 // the integer part is zero), and may include an exponent part (e.g., "e-10"). | 143 // the integer part is zero), and may include an exponent part (e.g., "e-10"). |
| 144 // Hexadecimal and octal numbers are not allowed. | 144 // Hexadecimal and octal numbers are not allowed. |
| 145 Handle<Object> ParseJsonNumber(); | 145 Handle<Object> ParseJsonNumber(); |
| (...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 188 | 188 |
| 189 PretenureFlag pretenure_; | 189 PretenureFlag pretenure_; |
| 190 Isolate* isolate_; | 190 Isolate* isolate_; |
| 191 Factory* factory_; | 191 Factory* factory_; |
| 192 Zone zone_; | 192 Zone zone_; |
| 193 Handle<JSFunction> object_constructor_; | 193 Handle<JSFunction> object_constructor_; |
| 194 uc32 c0_; | 194 uc32 c0_; |
| 195 int position_; | 195 int position_; |
| 196 }; | 196 }; |
| 197 | 197 |
| 198 template <bool seq_ascii> | 198 template <bool seq_one_byte> |
| 199 MaybeHandle<Object> JsonParser<seq_ascii>::ParseJson() { | 199 MaybeHandle<Object> JsonParser<seq_one_byte>::ParseJson() { |
| 200 // Advance to the first character (possibly EOS) | 200 // Advance to the first character (possibly EOS) |
| 201 AdvanceSkipWhitespace(); | 201 AdvanceSkipWhitespace(); |
| 202 Handle<Object> result = ParseJsonValue(); | 202 Handle<Object> result = ParseJsonValue(); |
| 203 if (result.is_null() || c0_ != kEndOfString) { | 203 if (result.is_null() || c0_ != kEndOfString) { |
| 204 // Some exception (for example stack overflow) is already pending. | 204 // Some exception (for example stack overflow) is already pending. |
| 205 if (isolate_->has_pending_exception()) return Handle<Object>::null(); | 205 if (isolate_->has_pending_exception()) return Handle<Object>::null(); |
| 206 | 206 |
| 207 // Parse failed. Current character is the unexpected token. | 207 // Parse failed. Current character is the unexpected token. |
| 208 const char* message; | 208 const char* message; |
| 209 Factory* factory = this->factory(); | 209 Factory* factory = this->factory(); |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 247 Handle<Object> error; | 247 Handle<Object> error; |
| 248 ASSIGN_RETURN_ON_EXCEPTION(isolate(), error, | 248 ASSIGN_RETURN_ON_EXCEPTION(isolate(), error, |
| 249 factory->NewSyntaxError(message, array), Object); | 249 factory->NewSyntaxError(message, array), Object); |
| 250 return isolate()->template Throw<Object>(error, &location); | 250 return isolate()->template Throw<Object>(error, &location); |
| 251 } | 251 } |
| 252 return result; | 252 return result; |
| 253 } | 253 } |
| 254 | 254 |
| 255 | 255 |
| 256 // Parse any JSON value. | 256 // Parse any JSON value. |
| 257 template <bool seq_ascii> | 257 template <bool seq_one_byte> |
| 258 Handle<Object> JsonParser<seq_ascii>::ParseJsonValue() { | 258 Handle<Object> JsonParser<seq_one_byte>::ParseJsonValue() { |
| 259 StackLimitCheck stack_check(isolate_); | 259 StackLimitCheck stack_check(isolate_); |
| 260 if (stack_check.HasOverflowed()) { | 260 if (stack_check.HasOverflowed()) { |
| 261 isolate_->StackOverflow(); | 261 isolate_->StackOverflow(); |
| 262 return Handle<Object>::null(); | 262 return Handle<Object>::null(); |
| 263 } | 263 } |
| 264 | 264 |
| 265 if (c0_ == '"') return ParseJsonString(); | 265 if (c0_ == '"') return ParseJsonString(); |
| 266 if ((c0_ >= '0' && c0_ <= '9') || c0_ == '-') return ParseJsonNumber(); | 266 if ((c0_ >= '0' && c0_ <= '9') || c0_ == '-') return ParseJsonNumber(); |
| 267 if (c0_ == '{') return ParseJsonObject(); | 267 if (c0_ == '{') return ParseJsonObject(); |
| 268 if (c0_ == '[') return ParseJsonArray(); | 268 if (c0_ == '[') return ParseJsonArray(); |
| (...skipping 19 matching lines...) Expand all Loading... |
| 288 AdvanceSkipWhitespace(); | 288 AdvanceSkipWhitespace(); |
| 289 return factory()->null_value(); | 289 return factory()->null_value(); |
| 290 } | 290 } |
| 291 return ReportUnexpectedCharacter(); | 291 return ReportUnexpectedCharacter(); |
| 292 } | 292 } |
| 293 return ReportUnexpectedCharacter(); | 293 return ReportUnexpectedCharacter(); |
| 294 } | 294 } |
| 295 | 295 |
| 296 | 296 |
| 297 // Parse a JSON object. Position must be right at '{'. | 297 // Parse a JSON object. Position must be right at '{'. |
| 298 template <bool seq_ascii> | 298 template <bool seq_one_byte> |
| 299 Handle<Object> JsonParser<seq_ascii>::ParseJsonObject() { | 299 Handle<Object> JsonParser<seq_one_byte>::ParseJsonObject() { |
| 300 HandleScope scope(isolate()); | 300 HandleScope scope(isolate()); |
| 301 Handle<JSObject> json_object = | 301 Handle<JSObject> json_object = |
| 302 factory()->NewJSObject(object_constructor(), pretenure_); | 302 factory()->NewJSObject(object_constructor(), pretenure_); |
| 303 Handle<Map> map(json_object->map()); | 303 Handle<Map> map(json_object->map()); |
| 304 ZoneList<Handle<Object> > properties(8, zone()); | 304 ZoneList<Handle<Object> > properties(8, zone()); |
| 305 DCHECK_EQ(c0_, '{'); | 305 DCHECK_EQ(c0_, '{'); |
| 306 | 306 |
| 307 bool transitioning = true; | 307 bool transitioning = true; |
| 308 | 308 |
| 309 AdvanceSkipWhitespace(); | 309 AdvanceSkipWhitespace(); |
| (...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 352 Handle<String> key; | 352 Handle<String> key; |
| 353 Handle<Object> value; | 353 Handle<Object> value; |
| 354 | 354 |
| 355 // Try to follow existing transitions as long as possible. Once we stop | 355 // Try to follow existing transitions as long as possible. Once we stop |
| 356 // transitioning, no transition can be found anymore. | 356 // transitioning, no transition can be found anymore. |
| 357 if (transitioning) { | 357 if (transitioning) { |
| 358 // First check whether there is a single expected transition. If so, try | 358 // First check whether there is a single expected transition. If so, try |
| 359 // to parse it first. | 359 // to parse it first. |
| 360 bool follow_expected = false; | 360 bool follow_expected = false; |
| 361 Handle<Map> target; | 361 Handle<Map> target; |
| 362 if (seq_ascii) { | 362 if (seq_one_byte) { |
| 363 key = Map::ExpectedTransitionKey(map); | 363 key = Map::ExpectedTransitionKey(map); |
| 364 follow_expected = !key.is_null() && ParseJsonString(key); | 364 follow_expected = !key.is_null() && ParseJsonString(key); |
| 365 } | 365 } |
| 366 // If the expected transition hits, follow it. | 366 // If the expected transition hits, follow it. |
| 367 if (follow_expected) { | 367 if (follow_expected) { |
| 368 target = Map::ExpectedTransitionTarget(map); | 368 target = Map::ExpectedTransitionTarget(map); |
| 369 } else { | 369 } else { |
| 370 // If the expected transition failed, parse an internalized string and | 370 // If the expected transition failed, parse an internalized string and |
| 371 // try to find a matching transition. | 371 // try to find a matching transition. |
| 372 key = ParseJsonInternalizedString(); | 372 key = ParseJsonInternalizedString(); |
| (...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 442 FieldIndex index = FieldIndex::ForPropertyIndex(*map, i); | 442 FieldIndex index = FieldIndex::ForPropertyIndex(*map, i); |
| 443 json_object->FastPropertyAtPut(index, *value); | 443 json_object->FastPropertyAtPut(index, *value); |
| 444 } | 444 } |
| 445 } | 445 } |
| 446 } | 446 } |
| 447 AdvanceSkipWhitespace(); | 447 AdvanceSkipWhitespace(); |
| 448 return scope.CloseAndEscape(json_object); | 448 return scope.CloseAndEscape(json_object); |
| 449 } | 449 } |
| 450 | 450 |
| 451 // Parse a JSON array. Position must be right at '['. | 451 // Parse a JSON array. Position must be right at '['. |
| 452 template <bool seq_ascii> | 452 template <bool seq_one_byte> |
| 453 Handle<Object> JsonParser<seq_ascii>::ParseJsonArray() { | 453 Handle<Object> JsonParser<seq_one_byte>::ParseJsonArray() { |
| 454 HandleScope scope(isolate()); | 454 HandleScope scope(isolate()); |
| 455 ZoneList<Handle<Object> > elements(4, zone()); | 455 ZoneList<Handle<Object> > elements(4, zone()); |
| 456 DCHECK_EQ(c0_, '['); | 456 DCHECK_EQ(c0_, '['); |
| 457 | 457 |
| 458 AdvanceSkipWhitespace(); | 458 AdvanceSkipWhitespace(); |
| 459 if (c0_ != ']') { | 459 if (c0_ != ']') { |
| 460 do { | 460 do { |
| 461 Handle<Object> element = ParseJsonValue(); | 461 Handle<Object> element = ParseJsonValue(); |
| 462 if (element.is_null()) return ReportUnexpectedCharacter(); | 462 if (element.is_null()) return ReportUnexpectedCharacter(); |
| 463 elements.Add(element, zone()); | 463 elements.Add(element, zone()); |
| 464 } while (MatchSkipWhiteSpace(',')); | 464 } while (MatchSkipWhiteSpace(',')); |
| 465 if (c0_ != ']') { | 465 if (c0_ != ']') { |
| 466 return ReportUnexpectedCharacter(); | 466 return ReportUnexpectedCharacter(); |
| 467 } | 467 } |
| 468 } | 468 } |
| 469 AdvanceSkipWhitespace(); | 469 AdvanceSkipWhitespace(); |
| 470 // Allocate a fixed array with all the elements. | 470 // Allocate a fixed array with all the elements. |
| 471 Handle<FixedArray> fast_elements = | 471 Handle<FixedArray> fast_elements = |
| 472 factory()->NewFixedArray(elements.length(), pretenure_); | 472 factory()->NewFixedArray(elements.length(), pretenure_); |
| 473 for (int i = 0, n = elements.length(); i < n; i++) { | 473 for (int i = 0, n = elements.length(); i < n; i++) { |
| 474 fast_elements->set(i, *elements[i]); | 474 fast_elements->set(i, *elements[i]); |
| 475 } | 475 } |
| 476 Handle<Object> json_array = factory()->NewJSArrayWithElements( | 476 Handle<Object> json_array = factory()->NewJSArrayWithElements( |
| 477 fast_elements, FAST_ELEMENTS, pretenure_); | 477 fast_elements, FAST_ELEMENTS, pretenure_); |
| 478 return scope.CloseAndEscape(json_array); | 478 return scope.CloseAndEscape(json_array); |
| 479 } | 479 } |
| 480 | 480 |
| 481 | 481 |
| 482 template <bool seq_ascii> | 482 template <bool seq_one_byte> |
| 483 Handle<Object> JsonParser<seq_ascii>::ParseJsonNumber() { | 483 Handle<Object> JsonParser<seq_one_byte>::ParseJsonNumber() { |
| 484 bool negative = false; | 484 bool negative = false; |
| 485 int beg_pos = position_; | 485 int beg_pos = position_; |
| 486 if (c0_ == '-') { | 486 if (c0_ == '-') { |
| 487 Advance(); | 487 Advance(); |
| 488 negative = true; | 488 negative = true; |
| 489 } | 489 } |
| 490 if (c0_ == '0') { | 490 if (c0_ == '0') { |
| 491 Advance(); | 491 Advance(); |
| 492 // Prefix zero is only allowed if it's the only digit before | 492 // Prefix zero is only allowed if it's the only digit before |
| 493 // a decimal point or exponent. | 493 // a decimal point or exponent. |
| (...skipping 22 matching lines...) Expand all Loading... |
| 516 if (AsciiAlphaToLower(c0_) == 'e') { | 516 if (AsciiAlphaToLower(c0_) == 'e') { |
| 517 Advance(); | 517 Advance(); |
| 518 if (c0_ == '-' || c0_ == '+') Advance(); | 518 if (c0_ == '-' || c0_ == '+') Advance(); |
| 519 if (c0_ < '0' || c0_ > '9') return ReportUnexpectedCharacter(); | 519 if (c0_ < '0' || c0_ > '9') return ReportUnexpectedCharacter(); |
| 520 do { | 520 do { |
| 521 Advance(); | 521 Advance(); |
| 522 } while (c0_ >= '0' && c0_ <= '9'); | 522 } while (c0_ >= '0' && c0_ <= '9'); |
| 523 } | 523 } |
| 524 int length = position_ - beg_pos; | 524 int length = position_ - beg_pos; |
| 525 double number; | 525 double number; |
| 526 if (seq_ascii) { | 526 if (seq_one_byte) { |
| 527 Vector<const uint8_t> chars(seq_source_->GetChars() + beg_pos, length); | 527 Vector<const uint8_t> chars(seq_source_->GetChars() + beg_pos, length); |
| 528 number = StringToDouble(isolate()->unicode_cache(), | 528 number = StringToDouble(isolate()->unicode_cache(), |
| 529 chars, | 529 chars, |
| 530 NO_FLAGS, // Hex, octal or trailing junk. | 530 NO_FLAGS, // Hex, octal or trailing junk. |
| 531 base::OS::nan_value()); | 531 base::OS::nan_value()); |
| 532 } else { | 532 } else { |
| 533 Vector<uint8_t> buffer = Vector<uint8_t>::New(length); | 533 Vector<uint8_t> buffer = Vector<uint8_t>::New(length); |
| 534 String::WriteToFlat(*source_, buffer.start(), beg_pos, position_); | 534 String::WriteToFlat(*source_, buffer.start(), beg_pos, position_); |
| 535 Vector<const uint8_t> result = | 535 Vector<const uint8_t> result = |
| 536 Vector<const uint8_t>(buffer.start(), length); | 536 Vector<const uint8_t>(buffer.start(), length); |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 574 inline Handle<SeqOneByteString> NewRawString(Factory* factory, | 574 inline Handle<SeqOneByteString> NewRawString(Factory* factory, |
| 575 int length, | 575 int length, |
| 576 PretenureFlag pretenure) { | 576 PretenureFlag pretenure) { |
| 577 return factory->NewRawOneByteString(length, pretenure).ToHandleChecked(); | 577 return factory->NewRawOneByteString(length, pretenure).ToHandleChecked(); |
| 578 } | 578 } |
| 579 | 579 |
| 580 | 580 |
| 581 // Scans the rest of a JSON string starting from position_ and writes | 581 // Scans the rest of a JSON string starting from position_ and writes |
| 582 // prefix[start..end] along with the scanned characters into a | 582 // prefix[start..end] along with the scanned characters into a |
| 583 // sequential string of type StringType. | 583 // sequential string of type StringType. |
| 584 template <bool seq_ascii> | 584 template <bool seq_one_byte> |
| 585 template <typename StringType, typename SinkChar> | 585 template <typename StringType, typename SinkChar> |
| 586 Handle<String> JsonParser<seq_ascii>::SlowScanJsonString( | 586 Handle<String> JsonParser<seq_one_byte>::SlowScanJsonString( |
| 587 Handle<String> prefix, int start, int end) { | 587 Handle<String> prefix, int start, int end) { |
| 588 int count = end - start; | 588 int count = end - start; |
| 589 int max_length = count + source_length_ - position_; | 589 int max_length = count + source_length_ - position_; |
| 590 int length = Min(max_length, Max(kInitialSpecialStringLength, 2 * count)); | 590 int length = Min(max_length, Max(kInitialSpecialStringLength, 2 * count)); |
| 591 Handle<StringType> seq_string = | 591 Handle<StringType> seq_string = |
| 592 NewRawString<StringType>(factory(), length, pretenure_); | 592 NewRawString<StringType>(factory(), length, pretenure_); |
| 593 // Copy prefix into seq_str. | 593 // Copy prefix into seq_str. |
| 594 SinkChar* dest = seq_string->GetChars(); | 594 SinkChar* dest = seq_string->GetChars(); |
| 595 String::WriteToFlat(*prefix, dest, start, end); | 595 String::WriteToFlat(*prefix, dest, start, end); |
| 596 | 596 |
| 597 while (c0_ != '"') { | 597 while (c0_ != '"') { |
| 598 // Check for control character (0x00-0x1f) or unterminated string (<0). | 598 // Check for control character (0x00-0x1f) or unterminated string (<0). |
| 599 if (c0_ < 0x20) return Handle<String>::null(); | 599 if (c0_ < 0x20) return Handle<String>::null(); |
| 600 if (count >= length) { | 600 if (count >= length) { |
| 601 // We need to create a longer sequential string for the result. | 601 // We need to create a longer sequential string for the result. |
| 602 return SlowScanJsonString<StringType, SinkChar>(seq_string, 0, count); | 602 return SlowScanJsonString<StringType, SinkChar>(seq_string, 0, count); |
| 603 } | 603 } |
| 604 if (c0_ != '\\') { | 604 if (c0_ != '\\') { |
| 605 // If the sink can contain UC16 characters, or source_ contains only | 605 // If the sink can contain UC16 characters, or source_ contains only |
| 606 // ASCII characters, there's no need to test whether we can store the | 606 // Latin1 characters, there's no need to test whether we can store the |
| 607 // character. Otherwise check whether the UC16 source character can fit | 607 // character. Otherwise check whether the UC16 source character can fit |
| 608 // in the ASCII sink. | 608 // in the Latin1 sink. |
| 609 if (sizeof(SinkChar) == kUC16Size || | 609 if (sizeof(SinkChar) == kUC16Size || seq_one_byte || |
| 610 seq_ascii || | |
| 611 c0_ <= String::kMaxOneByteCharCode) { | 610 c0_ <= String::kMaxOneByteCharCode) { |
| 612 SeqStringSet(seq_string, count++, c0_); | 611 SeqStringSet(seq_string, count++, c0_); |
| 613 Advance(); | 612 Advance(); |
| 614 } else { | 613 } else { |
| 615 // StringType is SeqOneByteString and we just read a non-ASCII char. | 614 // StringType is SeqOneByteString and we just read a non-Latin1 char. |
| 616 return SlowScanJsonString<SeqTwoByteString, uc16>(seq_string, 0, count); | 615 return SlowScanJsonString<SeqTwoByteString, uc16>(seq_string, 0, count); |
| 617 } | 616 } |
| 618 } else { | 617 } else { |
| 619 Advance(); // Advance past the \. | 618 Advance(); // Advance past the \. |
| 620 switch (c0_) { | 619 switch (c0_) { |
| 621 case '"': | 620 case '"': |
| 622 case '\\': | 621 case '\\': |
| 623 case '/': | 622 case '/': |
| 624 SeqStringSet(seq_string, count++, c0_); | 623 SeqStringSet(seq_string, count++, c0_); |
| 625 break; | 624 break; |
| (...skipping 20 matching lines...) Expand all Loading... |
| 646 if (digit < 0) { | 645 if (digit < 0) { |
| 647 return Handle<String>::null(); | 646 return Handle<String>::null(); |
| 648 } | 647 } |
| 649 value = value * 16 + digit; | 648 value = value * 16 + digit; |
| 650 } | 649 } |
| 651 if (sizeof(SinkChar) == kUC16Size || | 650 if (sizeof(SinkChar) == kUC16Size || |
| 652 value <= String::kMaxOneByteCharCode) { | 651 value <= String::kMaxOneByteCharCode) { |
| 653 SeqStringSet(seq_string, count++, value); | 652 SeqStringSet(seq_string, count++, value); |
| 654 break; | 653 break; |
| 655 } else { | 654 } else { |
| 656 // StringType is SeqOneByteString and we just read a non-ASCII char. | 655 // StringType is SeqOneByteString and we just read a non-Latin1 |
| 656 // char. |
| 657 position_ -= 6; // Rewind position_ to \ in \uxxxx. | 657 position_ -= 6; // Rewind position_ to \ in \uxxxx. |
| 658 Advance(); | 658 Advance(); |
| 659 return SlowScanJsonString<SeqTwoByteString, uc16>(seq_string, | 659 return SlowScanJsonString<SeqTwoByteString, uc16>(seq_string, |
| 660 0, | 660 0, |
| 661 count); | 661 count); |
| 662 } | 662 } |
| 663 } | 663 } |
| 664 default: | 664 default: |
| 665 return Handle<String>::null(); | 665 return Handle<String>::null(); |
| 666 } | 666 } |
| 667 Advance(); | 667 Advance(); |
| 668 } | 668 } |
| 669 } | 669 } |
| 670 | 670 |
| 671 DCHECK_EQ('"', c0_); | 671 DCHECK_EQ('"', c0_); |
| 672 // Advance past the last '"'. | 672 // Advance past the last '"'. |
| 673 AdvanceSkipWhitespace(); | 673 AdvanceSkipWhitespace(); |
| 674 | 674 |
| 675 // Shrink seq_string length to count and return. | 675 // Shrink seq_string length to count and return. |
| 676 return SeqString::Truncate(seq_string, count); | 676 return SeqString::Truncate(seq_string, count); |
| 677 } | 677 } |
| 678 | 678 |
| 679 | 679 |
| 680 template <bool seq_ascii> | 680 template <bool seq_one_byte> |
| 681 template <bool is_internalized> | 681 template <bool is_internalized> |
| 682 Handle<String> JsonParser<seq_ascii>::ScanJsonString() { | 682 Handle<String> JsonParser<seq_one_byte>::ScanJsonString() { |
| 683 DCHECK_EQ('"', c0_); | 683 DCHECK_EQ('"', c0_); |
| 684 Advance(); | 684 Advance(); |
| 685 if (c0_ == '"') { | 685 if (c0_ == '"') { |
| 686 AdvanceSkipWhitespace(); | 686 AdvanceSkipWhitespace(); |
| 687 return factory()->empty_string(); | 687 return factory()->empty_string(); |
| 688 } | 688 } |
| 689 | 689 |
| 690 if (seq_ascii && is_internalized) { | 690 if (seq_one_byte && is_internalized) { |
| 691 // Fast path for existing internalized strings. If the the string being | 691 // Fast path for existing internalized strings. If the the string being |
| 692 // parsed is not a known internalized string, contains backslashes or | 692 // parsed is not a known internalized string, contains backslashes or |
| 693 // unexpectedly reaches the end of string, return with an empty handle. | 693 // unexpectedly reaches the end of string, return with an empty handle. |
| 694 uint32_t running_hash = isolate()->heap()->HashSeed(); | 694 uint32_t running_hash = isolate()->heap()->HashSeed(); |
| 695 int position = position_; | 695 int position = position_; |
| 696 uc32 c0 = c0_; | 696 uc32 c0 = c0_; |
| 697 do { | 697 do { |
| 698 if (c0 == '\\') { | 698 if (c0 == '\\') { |
| 699 c0_ = c0; | 699 c0_ = c0; |
| 700 int beg_pos = position_; | 700 int beg_pos = position_; |
| (...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 751 } | 751 } |
| 752 entry = StringTable::NextProbe(entry, count++, capacity); | 752 entry = StringTable::NextProbe(entry, count++, capacity); |
| 753 } | 753 } |
| 754 position_ = position; | 754 position_ = position; |
| 755 // Advance past the last '"'. | 755 // Advance past the last '"'. |
| 756 AdvanceSkipWhitespace(); | 756 AdvanceSkipWhitespace(); |
| 757 return result; | 757 return result; |
| 758 } | 758 } |
| 759 | 759 |
| 760 int beg_pos = position_; | 760 int beg_pos = position_; |
| 761 // Fast case for ASCII only without escape characters. | 761 // Fast case for Latin1 only without escape characters. |
| 762 do { | 762 do { |
| 763 // Check for control character (0x00-0x1f) or unterminated string (<0). | 763 // Check for control character (0x00-0x1f) or unterminated string (<0). |
| 764 if (c0_ < 0x20) return Handle<String>::null(); | 764 if (c0_ < 0x20) return Handle<String>::null(); |
| 765 if (c0_ != '\\') { | 765 if (c0_ != '\\') { |
| 766 if (seq_ascii || c0_ <= String::kMaxOneByteCharCode) { | 766 if (seq_one_byte || c0_ <= String::kMaxOneByteCharCode) { |
| 767 Advance(); | 767 Advance(); |
| 768 } else { | 768 } else { |
| 769 return SlowScanJsonString<SeqTwoByteString, uc16>(source_, | 769 return SlowScanJsonString<SeqTwoByteString, uc16>(source_, |
| 770 beg_pos, | 770 beg_pos, |
| 771 position_); | 771 position_); |
| 772 } | 772 } |
| 773 } else { | 773 } else { |
| 774 return SlowScanJsonString<SeqOneByteString, uint8_t>(source_, | 774 return SlowScanJsonString<SeqOneByteString, uint8_t>(source_, |
| 775 beg_pos, | 775 beg_pos, |
| 776 position_); | 776 position_); |
| 777 } | 777 } |
| 778 } while (c0_ != '"'); | 778 } while (c0_ != '"'); |
| 779 int length = position_ - beg_pos; | 779 int length = position_ - beg_pos; |
| 780 Handle<String> result = | 780 Handle<String> result = |
| 781 factory()->NewRawOneByteString(length, pretenure_).ToHandleChecked(); | 781 factory()->NewRawOneByteString(length, pretenure_).ToHandleChecked(); |
| 782 uint8_t* dest = SeqOneByteString::cast(*result)->GetChars(); | 782 uint8_t* dest = SeqOneByteString::cast(*result)->GetChars(); |
| 783 String::WriteToFlat(*source_, dest, beg_pos, position_); | 783 String::WriteToFlat(*source_, dest, beg_pos, position_); |
| 784 | 784 |
| 785 DCHECK_EQ('"', c0_); | 785 DCHECK_EQ('"', c0_); |
| 786 // Advance past the last '"'. | 786 // Advance past the last '"'. |
| 787 AdvanceSkipWhitespace(); | 787 AdvanceSkipWhitespace(); |
| 788 return result; | 788 return result; |
| 789 } | 789 } |
| 790 | 790 |
| 791 } } // namespace v8::internal | 791 } } // namespace v8::internal |
| 792 | 792 |
| 793 #endif // V8_JSON_PARSER_H_ | 793 #endif // V8_JSON_PARSER_H_ |
| OLD | NEW |