V8 Project
json-parser.h
Go to the documentation of this file.
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
3 // found in the LICENSE file.
4 
5 #ifndef V8_JSON_PARSER_H_
6 #define V8_JSON_PARSER_H_
7 
8 #include "src/v8.h"
9 
11 #include "src/conversions.h"
12 #include "src/heap/spaces-inl.h"
13 #include "src/messages.h"
14 #include "src/token.h"
15 
16 namespace v8 {
17 namespace internal {
18 
19 // A simple json parser.
20 template <bool seq_one_byte>
21 class JsonParser BASE_EMBEDDED {
22  public:
24  return JsonParser(source).ParseJson();
25  }
26 
27  static const int kEndOfString = -1;
28 
29  private:
30  explicit JsonParser(Handle<String> source)
31  : source_(source),
32  source_length_(source->length()),
33  isolate_(source->map()->GetHeap()->isolate()),
34  factory_(isolate_->factory()),
35  zone_(isolate_),
36  object_constructor_(isolate_->native_context()->object_function(),
37  isolate_),
38  position_(-1) {
39  source_ = String::Flatten(source_);
40  pretenure_ = (source_length_ >= kPretenureTreshold) ? TENURED : NOT_TENURED;
41 
42  // Optimized fast case where we only have Latin1 characters.
43  if (seq_one_byte) {
44  seq_source_ = Handle<SeqOneByteString>::cast(source_);
45  }
46  }
47 
48  // Parse a string containing a single JSON value.
50 
51  inline void Advance() {
52  position_++;
53  if (position_ >= source_length_) {
54  c0_ = kEndOfString;
55  } else if (seq_one_byte) {
56  c0_ = seq_source_->SeqOneByteStringGet(position_);
57  } else {
58  c0_ = source_->Get(position_);
59  }
60  }
61 
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
64  // are tab, carriage-return, newline and space.
65 
66  inline void AdvanceSkipWhitespace() {
67  do {
68  Advance();
69  } while (c0_ == ' ' || c0_ == '\t' || c0_ == '\n' || c0_ == '\r');
70  }
71 
72  inline void SkipWhitespace() {
73  while (c0_ == ' ' || c0_ == '\t' || c0_ == '\n' || c0_ == '\r') {
74  Advance();
75  }
76  }
77 
78  inline uc32 AdvanceGetChar() {
79  Advance();
80  return c0_;
81  }
82 
83  // Checks that current charater is c.
84  // If so, then consume c and skip whitespace.
85  inline bool MatchSkipWhiteSpace(uc32 c) {
86  if (c0_ == c) {
87  AdvanceSkipWhitespace();
88  return true;
89  }
90  return false;
91  }
92 
93  // A JSON string (production JSONString) is subset of valid JavaScript string
94  // literals. The string must only be double-quoted (not single-quoted), and
95  // the only allowed backslash-escapes are ", /, \, b, f, n, r, t and
96  // four-digit hex escapes (uXXXX). Any other use of backslashes is invalid.
98  return ScanJsonString<false>();
99  }
100 
102  int length = expected->length();
103  if (source_->length() - position_ - 1 > length) {
105  String::FlatContent content = expected->GetFlatContent();
106  if (content.IsOneByte()) {
107  DCHECK_EQ('"', c0_);
108  const uint8_t* input_chars = seq_source_->GetChars() + position_ + 1;
109  const uint8_t* expected_chars = content.ToOneByteVector().start();
110  for (int i = 0; i < length; i++) {
111  uint8_t c0 = input_chars[i];
112  if (c0 != expected_chars[i] ||
113  c0 == '"' || c0 < 0x20 || c0 == '\\') {
114  return false;
115  }
116  }
117  if (input_chars[length] == '"') {
118  position_ = position_ + length + 1;
119  AdvanceSkipWhitespace();
120  return true;
121  }
122  }
123  }
124  return false;
125  }
126 
128  return ScanJsonString<true>();
129  }
130 
131  template <bool is_internalized>
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
135  // prefix. Called by ScanJsonString when reaching a '\' or non-Latin1 char.
136  template <typename StringType, typename SinkChar>
137  Handle<String> SlowScanJsonString(Handle<String> prefix, int start, int end);
138 
139  // A JSON number (production JSONNumber) is a subset of the valid JavaScript
140  // decimal number literals.
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
143  // the integer part is zero), and may include an exponent part (e.g., "e-10").
144  // Hexadecimal and octal numbers are not allowed.
146 
147  // Parse a single JSON value from input (grammar production JSONValue).
148  // A JSON value is either a (double-quoted) string literal, a number literal,
149  // one of "true", "false", or "null", or an object or array literal.
151 
152  // Parse a JSON object literal (grammar production JSONObject).
153  // An object literal is a squiggly-braced and comma separated sequence
154  // (possibly empty) of key/value pairs, where the key is a JSON string
155  // literal, the value is a JSON value, and the two are separated by a colon.
156  // A JSON array doesn't allow numbers and identifiers as keys, like a
157  // JavaScript array.
159 
160  // Parses a JSON array literal (grammar production JSONArray). An array
161  // literal is a square-bracketed and comma separated sequence (possibly empty)
162  // of JSON values.
163  // A JSON array doesn't allow leaving out values from the sequence, nor does
164  // it allow a terminal comma, like a JavaScript array does.
166 
167 
168  // Mark that a parsing error has happened at the current token, and
169  // return a null handle. Primarily for readability.
171  return Handle<Object>::null();
172  }
173 
174  inline Isolate* isolate() { return isolate_; }
175  inline Factory* factory() { return factory_; }
176  inline Handle<JSFunction> object_constructor() { return object_constructor_; }
177 
178  static const int kInitialSpecialStringLength = 1024;
179  static const int kPretenureTreshold = 100 * 1024;
180 
181 
182  private:
183  Zone* zone() { return &zone_; }
184 
188 
190  Isolate* isolate_;
191  Factory* factory_;
192  Zone zone_;
196 };
197 
198 template <bool seq_one_byte>
199 MaybeHandle<Object> JsonParser<seq_one_byte>::ParseJson() {
200  // Advance to the first character (possibly EOS)
201  AdvanceSkipWhitespace();
202  Handle<Object> result = ParseJsonValue();
203  if (result.is_null() || c0_ != kEndOfString) {
204  // Some exception (for example stack overflow) is already pending.
205  if (isolate_->has_pending_exception()) return Handle<Object>::null();
206 
207  // Parse failed. Current character is the unexpected token.
208  const char* message;
209  Factory* factory = this->factory();
210  Handle<JSArray> array;
211 
212  switch (c0_) {
213  case kEndOfString:
214  message = "unexpected_eos";
215  array = factory->NewJSArray(0);
216  break;
217  case '-':
218  case '0':
219  case '1':
220  case '2':
221  case '3':
222  case '4':
223  case '5':
224  case '6':
225  case '7':
226  case '8':
227  case '9':
228  message = "unexpected_token_number";
229  array = factory->NewJSArray(0);
230  break;
231  case '"':
232  message = "unexpected_token_string";
233  array = factory->NewJSArray(0);
234  break;
235  default:
236  message = "unexpected_token";
237  Handle<Object> name = factory->LookupSingleCharacterStringFromCode(c0_);
238  Handle<FixedArray> element = factory->NewFixedArray(1);
239  element->set(0, *name);
240  array = factory->NewJSArrayWithElements(element);
241  break;
242  }
243 
244  MessageLocation location(factory->NewScript(source_),
245  position_,
246  position_ + 1);
247  Handle<Object> error;
248  ASSIGN_RETURN_ON_EXCEPTION(isolate(), error,
249  factory->NewSyntaxError(message, array), Object);
250  return isolate()->template Throw<Object>(error, &location);
251  }
252  return result;
253 }
254 
255 
256 // Parse any JSON value.
257 template <bool seq_one_byte>
258 Handle<Object> JsonParser<seq_one_byte>::ParseJsonValue() {
259  StackLimitCheck stack_check(isolate_);
260  if (stack_check.HasOverflowed()) {
261  isolate_->StackOverflow();
262  return Handle<Object>::null();
263  }
264 
265  if (c0_ == '"') return ParseJsonString();
266  if ((c0_ >= '0' && c0_ <= '9') || c0_ == '-') return ParseJsonNumber();
267  if (c0_ == '{') return ParseJsonObject();
268  if (c0_ == '[') return ParseJsonArray();
269  if (c0_ == 'f') {
270  if (AdvanceGetChar() == 'a' && AdvanceGetChar() == 'l' &&
271  AdvanceGetChar() == 's' && AdvanceGetChar() == 'e') {
272  AdvanceSkipWhitespace();
273  return factory()->false_value();
274  }
275  return ReportUnexpectedCharacter();
276  }
277  if (c0_ == 't') {
278  if (AdvanceGetChar() == 'r' && AdvanceGetChar() == 'u' &&
279  AdvanceGetChar() == 'e') {
280  AdvanceSkipWhitespace();
281  return factory()->true_value();
282  }
283  return ReportUnexpectedCharacter();
284  }
285  if (c0_ == 'n') {
286  if (AdvanceGetChar() == 'u' && AdvanceGetChar() == 'l' &&
287  AdvanceGetChar() == 'l') {
288  AdvanceSkipWhitespace();
289  return factory()->null_value();
290  }
291  return ReportUnexpectedCharacter();
292  }
293  return ReportUnexpectedCharacter();
294 }
295 
296 
297 // Parse a JSON object. Position must be right at '{'.
298 template <bool seq_one_byte>
299 Handle<Object> JsonParser<seq_one_byte>::ParseJsonObject() {
300  HandleScope scope(isolate());
301  Handle<JSObject> json_object =
302  factory()->NewJSObject(object_constructor(), pretenure_);
303  Handle<Map> map(json_object->map());
304  ZoneList<Handle<Object> > properties(8, zone());
305  DCHECK_EQ(c0_, '{');
306 
307  bool transitioning = true;
308 
309  AdvanceSkipWhitespace();
310  if (c0_ != '}') {
311  do {
312  if (c0_ != '"') return ReportUnexpectedCharacter();
313 
314  int start_position = position_;
315  Advance();
316 
317  uint32_t index = 0;
318  if (c0_ >= '0' && c0_ <= '9') {
319  // Maybe an array index, try to parse it.
320  if (c0_ == '0') {
321  // With a leading zero, the string has to be "0" only to be an index.
322  Advance();
323  } else {
324  do {
325  int d = c0_ - '0';
326  if (index > 429496729U - ((d > 5) ? 1 : 0)) break;
327  index = (index * 10) + d;
328  Advance();
329  } while (c0_ >= '0' && c0_ <= '9');
330  }
331 
332  if (c0_ == '"') {
333  // Successfully parsed index, parse and store element.
334  AdvanceSkipWhitespace();
335 
336  if (c0_ != ':') return ReportUnexpectedCharacter();
337  AdvanceSkipWhitespace();
338  Handle<Object> value = ParseJsonValue();
339  if (value.is_null()) return ReportUnexpectedCharacter();
340 
341  JSObject::SetOwnElement(json_object, index, value, SLOPPY).Assert();
342  continue;
343  }
344  // Not an index, fallback to the slow path.
345  }
346 
347  position_ = start_position;
348 #ifdef DEBUG
349  c0_ = '"';
350 #endif
351 
352  Handle<String> key;
353  Handle<Object> value;
354 
355  // Try to follow existing transitions as long as possible. Once we stop
356  // transitioning, no transition can be found anymore.
357  if (transitioning) {
358  // First check whether there is a single expected transition. If so, try
359  // to parse it first.
360  bool follow_expected = false;
361  Handle<Map> target;
362  if (seq_one_byte) {
364  follow_expected = !key.is_null() && ParseJsonString(key);
365  }
366  // If the expected transition hits, follow it.
367  if (follow_expected) {
369  } else {
370  // If the expected transition failed, parse an internalized string and
371  // try to find a matching transition.
372  key = ParseJsonInternalizedString();
373  if (key.is_null()) return ReportUnexpectedCharacter();
374 
375  target = Map::FindTransitionToField(map, key);
376  // If a transition was found, follow it and continue.
377  transitioning = !target.is_null();
378  }
379  if (c0_ != ':') return ReportUnexpectedCharacter();
380 
381  AdvanceSkipWhitespace();
382  value = ParseJsonValue();
383  if (value.is_null()) return ReportUnexpectedCharacter();
384 
385  if (transitioning) {
386  int descriptor = map->NumberOfOwnDescriptors();
387  PropertyDetails details =
388  target->instance_descriptors()->GetDetails(descriptor);
389  Representation expected_representation = details.representation();
390 
391  if (value->FitsRepresentation(expected_representation)) {
392  if (expected_representation.IsDouble()) {
393  value = Object::NewStorageFor(isolate(), value,
394  expected_representation);
395  } else if (expected_representation.IsHeapObject() &&
396  !target->instance_descriptors()->GetFieldType(
397  descriptor)->NowContains(value)) {
398  Handle<HeapType> value_type(value->OptimalType(
399  isolate(), expected_representation));
400  Map::GeneralizeFieldType(target, descriptor, value_type);
401  }
402  DCHECK(target->instance_descriptors()->GetFieldType(
403  descriptor)->NowContains(value));
404  properties.Add(value, zone());
405  map = target;
406  continue;
407  } else {
408  transitioning = false;
409  }
410  }
411 
412  // Commit the intermediate state to the object and stop transitioning.
413  JSObject::AllocateStorageForMap(json_object, map);
414  int length = properties.length();
415  for (int i = 0; i < length; i++) {
416  Handle<Object> value = properties[i];
417  FieldIndex index = FieldIndex::ForPropertyIndex(*map, i);
418  json_object->FastPropertyAtPut(index, *value);
419  }
420  } else {
421  key = ParseJsonInternalizedString();
422  if (key.is_null() || c0_ != ':') return ReportUnexpectedCharacter();
423 
424  AdvanceSkipWhitespace();
425  value = ParseJsonValue();
426  if (value.is_null()) return ReportUnexpectedCharacter();
427  }
428 
429  Runtime::DefineObjectProperty(json_object, key, value, NONE).Check();
430  } while (MatchSkipWhiteSpace(','));
431  if (c0_ != '}') {
432  return ReportUnexpectedCharacter();
433  }
434 
435  // If we transitioned until the very end, transition the map now.
436  if (transitioning) {
437  JSObject::AllocateStorageForMap(json_object, map);
438  int length = properties.length();
439  for (int i = 0; i < length; i++) {
440  Handle<Object> value = properties[i];
441  FieldIndex index = FieldIndex::ForPropertyIndex(*map, i);
442  json_object->FastPropertyAtPut(index, *value);
443  }
444  }
445  }
446  AdvanceSkipWhitespace();
447  return scope.CloseAndEscape(json_object);
448 }
449 
450 // Parse a JSON array. Position must be right at '['.
451 template <bool seq_one_byte>
452 Handle<Object> JsonParser<seq_one_byte>::ParseJsonArray() {
453  HandleScope scope(isolate());
454  ZoneList<Handle<Object> > elements(4, zone());
455  DCHECK_EQ(c0_, '[');
456 
457  AdvanceSkipWhitespace();
458  if (c0_ != ']') {
459  do {
460  Handle<Object> element = ParseJsonValue();
461  if (element.is_null()) return ReportUnexpectedCharacter();
462  elements.Add(element, zone());
463  } while (MatchSkipWhiteSpace(','));
464  if (c0_ != ']') {
465  return ReportUnexpectedCharacter();
466  }
467  }
468  AdvanceSkipWhitespace();
469  // Allocate a fixed array with all the elements.
470  Handle<FixedArray> fast_elements =
471  factory()->NewFixedArray(elements.length(), pretenure_);
472  for (int i = 0, n = elements.length(); i < n; i++) {
473  fast_elements->set(i, *elements[i]);
474  }
475  Handle<Object> json_array = factory()->NewJSArrayWithElements(
476  fast_elements, FAST_ELEMENTS, pretenure_);
477  return scope.CloseAndEscape(json_array);
478 }
479 
480 
481 template <bool seq_one_byte>
482 Handle<Object> JsonParser<seq_one_byte>::ParseJsonNumber() {
483  bool negative = false;
484  int beg_pos = position_;
485  if (c0_ == '-') {
486  Advance();
487  negative = true;
488  }
489  if (c0_ == '0') {
490  Advance();
491  // Prefix zero is only allowed if it's the only digit before
492  // a decimal point or exponent.
493  if ('0' <= c0_ && c0_ <= '9') return ReportUnexpectedCharacter();
494  } else {
495  int i = 0;
496  int digits = 0;
497  if (c0_ < '1' || c0_ > '9') return ReportUnexpectedCharacter();
498  do {
499  i = i * 10 + c0_ - '0';
500  digits++;
501  Advance();
502  } while (c0_ >= '0' && c0_ <= '9');
503  if (c0_ != '.' && c0_ != 'e' && c0_ != 'E' && digits < 10) {
504  SkipWhitespace();
505  return Handle<Smi>(Smi::FromInt((negative ? -i : i)), isolate());
506  }
507  }
508  if (c0_ == '.') {
509  Advance();
510  if (c0_ < '0' || c0_ > '9') return ReportUnexpectedCharacter();
511  do {
512  Advance();
513  } while (c0_ >= '0' && c0_ <= '9');
514  }
515  if (AsciiAlphaToLower(c0_) == 'e') {
516  Advance();
517  if (c0_ == '-' || c0_ == '+') Advance();
518  if (c0_ < '0' || c0_ > '9') return ReportUnexpectedCharacter();
519  do {
520  Advance();
521  } while (c0_ >= '0' && c0_ <= '9');
522  }
523  int length = position_ - beg_pos;
524  double number;
525  if (seq_one_byte) {
526  Vector<const uint8_t> chars(seq_source_->GetChars() + beg_pos, length);
527  number = StringToDouble(isolate()->unicode_cache(),
528  chars,
529  NO_FLAGS, // Hex, octal or trailing junk.
531  } else {
532  Vector<uint8_t> buffer = Vector<uint8_t>::New(length);
533  String::WriteToFlat(*source_, buffer.start(), beg_pos, position_);
534  Vector<const uint8_t> result =
535  Vector<const uint8_t>(buffer.start(), length);
536  number = StringToDouble(isolate()->unicode_cache(),
537  result,
538  NO_FLAGS, // Hex, octal or trailing junk.
539  0.0);
540  buffer.Dispose();
541  }
542  SkipWhitespace();
543  return factory()->NewNumber(number, pretenure_);
544 }
545 
546 
547 template <typename StringType>
548 inline void SeqStringSet(Handle<StringType> seq_str, int i, uc32 c);
549 
550 template <>
551 inline void SeqStringSet(Handle<SeqTwoByteString> seq_str, int i, uc32 c) {
552  seq_str->SeqTwoByteStringSet(i, c);
553 }
554 
555 template <>
556 inline void SeqStringSet(Handle<SeqOneByteString> seq_str, int i, uc32 c) {
557  seq_str->SeqOneByteStringSet(i, c);
558 }
559 
560 template <typename StringType>
561 inline Handle<StringType> NewRawString(Factory* factory,
562  int length,
563  PretenureFlag pretenure);
564 
565 template <>
566 inline Handle<SeqTwoByteString> NewRawString(Factory* factory,
567  int length,
568  PretenureFlag pretenure) {
569  return factory->NewRawTwoByteString(length, pretenure).ToHandleChecked();
570 }
571 
572 template <>
573 inline Handle<SeqOneByteString> NewRawString(Factory* factory,
574  int length,
575  PretenureFlag pretenure) {
576  return factory->NewRawOneByteString(length, pretenure).ToHandleChecked();
577 }
578 
579 
580 // Scans the rest of a JSON string starting from position_ and writes
581 // prefix[start..end] along with the scanned characters into a
582 // sequential string of type StringType.
583 template <bool seq_one_byte>
584 template <typename StringType, typename SinkChar>
585 Handle<String> JsonParser<seq_one_byte>::SlowScanJsonString(
586  Handle<String> prefix, int start, int end) {
587  int count = end - start;
588  int max_length = count + source_length_ - position_;
589  int length = Min(max_length, Max(kInitialSpecialStringLength, 2 * count));
590  Handle<StringType> seq_string =
591  NewRawString<StringType>(factory(), length, pretenure_);
592  // Copy prefix into seq_str.
593  SinkChar* dest = seq_string->GetChars();
594  String::WriteToFlat(*prefix, dest, start, end);
595 
596  while (c0_ != '"') {
597  // Check for control character (0x00-0x1f) or unterminated string (<0).
598  if (c0_ < 0x20) return Handle<String>::null();
599  if (count >= length) {
600  // We need to create a longer sequential string for the result.
601  return SlowScanJsonString<StringType, SinkChar>(seq_string, 0, count);
602  }
603  if (c0_ != '\\') {
604  // If the sink can contain UC16 characters, or source_ contains only
605  // Latin1 characters, there's no need to test whether we can store the
606  // character. Otherwise check whether the UC16 source character can fit
607  // in the Latin1 sink.
608  if (sizeof(SinkChar) == kUC16Size || seq_one_byte ||
610  SeqStringSet(seq_string, count++, c0_);
611  Advance();
612  } else {
613  // StringType is SeqOneByteString and we just read a non-Latin1 char.
614  return SlowScanJsonString<SeqTwoByteString, uc16>(seq_string, 0, count);
615  }
616  } else {
617  Advance(); // Advance past the \.
618  switch (c0_) {
619  case '"':
620  case '\\':
621  case '/':
622  SeqStringSet(seq_string, count++, c0_);
623  break;
624  case 'b':
625  SeqStringSet(seq_string, count++, '\x08');
626  break;
627  case 'f':
628  SeqStringSet(seq_string, count++, '\x0c');
629  break;
630  case 'n':
631  SeqStringSet(seq_string, count++, '\x0a');
632  break;
633  case 'r':
634  SeqStringSet(seq_string, count++, '\x0d');
635  break;
636  case 't':
637  SeqStringSet(seq_string, count++, '\x09');
638  break;
639  case 'u': {
640  uc32 value = 0;
641  for (int i = 0; i < 4; i++) {
642  Advance();
643  int digit = HexValue(c0_);
644  if (digit < 0) {
645  return Handle<String>::null();
646  }
647  value = value * 16 + digit;
648  }
649  if (sizeof(SinkChar) == kUC16Size ||
650  value <= String::kMaxOneByteCharCode) {
651  SeqStringSet(seq_string, count++, value);
652  break;
653  } else {
654  // StringType is SeqOneByteString and we just read a non-Latin1
655  // char.
656  position_ -= 6; // Rewind position_ to \ in \uxxxx.
657  Advance();
658  return SlowScanJsonString<SeqTwoByteString, uc16>(seq_string,
659  0,
660  count);
661  }
662  }
663  default:
664  return Handle<String>::null();
665  }
666  Advance();
667  }
668  }
669 
670  DCHECK_EQ('"', c0_);
671  // Advance past the last '"'.
672  AdvanceSkipWhitespace();
673 
674  // Shrink seq_string length to count and return.
675  return SeqString::Truncate(seq_string, count);
676 }
677 
678 
679 template <bool seq_one_byte>
680 template <bool is_internalized>
681 Handle<String> JsonParser<seq_one_byte>::ScanJsonString() {
682  DCHECK_EQ('"', c0_);
683  Advance();
684  if (c0_ == '"') {
685  AdvanceSkipWhitespace();
686  return factory()->empty_string();
687  }
688 
689  if (seq_one_byte && is_internalized) {
690  // Fast path for existing internalized strings. If the the string being
691  // parsed is not a known internalized string, contains backslashes or
692  // unexpectedly reaches the end of string, return with an empty handle.
693  uint32_t running_hash = isolate()->heap()->HashSeed();
694  int position = position_;
695  uc32 c0 = c0_;
696  do {
697  if (c0 == '\\') {
698  c0_ = c0;
699  int beg_pos = position_;
700  position_ = position;
701  return SlowScanJsonString<SeqOneByteString, uint8_t>(source_,
702  beg_pos,
703  position_);
704  }
705  if (c0 < 0x20) return Handle<String>::null();
706  if (static_cast<uint32_t>(c0) >
708  running_hash =
709  StringHasher::AddCharacterCore(running_hash,
711  running_hash =
712  StringHasher::AddCharacterCore(running_hash,
714  } else {
715  running_hash = StringHasher::AddCharacterCore(running_hash, c0);
716  }
717  position++;
718  if (position >= source_length_) return Handle<String>::null();
719  c0 = seq_source_->SeqOneByteStringGet(position);
720  } while (c0 != '"');
721  int length = position - position_;
722  uint32_t hash = (length <= String::kMaxHashCalcLength)
723  ? StringHasher::GetHashCore(running_hash)
724  : static_cast<uint32_t>(length);
725  Vector<const uint8_t> string_vector(
726  seq_source_->GetChars() + position_, length);
727  StringTable* string_table = isolate()->heap()->string_table();
728  uint32_t capacity = string_table->Capacity();
729  uint32_t entry = StringTable::FirstProbe(hash, capacity);
730  uint32_t count = 1;
731  Handle<String> result;
732  while (true) {
733  Object* element = string_table->KeyAt(entry);
734  if (element == isolate()->heap()->undefined_value()) {
735  // Lookup failure.
736  result = factory()->InternalizeOneByteString(
737  seq_source_, position_, length);
738  break;
739  }
740  if (element != isolate()->heap()->the_hole_value() &&
741  String::cast(element)->IsOneByteEqualTo(string_vector)) {
742  result = Handle<String>(String::cast(element), isolate());
743 #ifdef DEBUG
744  uint32_t hash_field =
746  DCHECK_EQ(static_cast<int>(result->Hash()),
747  static_cast<int>(hash_field >> String::kHashShift));
748 #endif
749  break;
750  }
751  entry = StringTable::NextProbe(entry, count++, capacity);
752  }
753  position_ = position;
754  // Advance past the last '"'.
755  AdvanceSkipWhitespace();
756  return result;
757  }
758 
759  int beg_pos = position_;
760  // Fast case for Latin1 only without escape characters.
761  do {
762  // Check for control character (0x00-0x1f) or unterminated string (<0).
763  if (c0_ < 0x20) return Handle<String>::null();
764  if (c0_ != '\\') {
765  if (seq_one_byte || c0_ <= String::kMaxOneByteCharCode) {
766  Advance();
767  } else {
768  return SlowScanJsonString<SeqTwoByteString, uc16>(source_,
769  beg_pos,
770  position_);
771  }
772  } else {
773  return SlowScanJsonString<SeqOneByteString, uint8_t>(source_,
774  beg_pos,
775  position_);
776  }
777  } while (c0_ != '"');
778  int length = position_ - beg_pos;
779  Handle<String> result =
780  factory()->NewRawOneByteString(length, pretenure_).ToHandleChecked();
781  uint8_t* dest = SeqOneByteString::cast(*result)->GetChars();
782  String::WriteToFlat(*source_, dest, beg_pos, position_);
783 
784  DCHECK_EQ('"', c0_);
785  // Advance past the last '"'.
786  AdvanceSkipWhitespace();
787  return result;
788 }
789 
790 } } // namespace v8::internal
791 
792 #endif // V8_JSON_PARSER_H_
#define BASE_EMBEDDED
Definition: allocation.h:45
static uint16_t LeadSurrogate(uint32_t char_code)
Definition: unicode.h:108
static const uchar kMaxNonSurrogateCharCode
Definition: unicode.h:98
static uint16_t TrailSurrogate(uint32_t char_code)
Definition: unicode.h:111
An object reference managed by the v8 garbage collector.
Definition: v8.h:198
static double nan_value()
bool ParseJsonString(Handle< String > expected)
Definition: json-parser.h:101
Handle< Object > ParseJsonValue()
MaybeHandle< Object > ParseJson()
Handle< String > ParseJsonString()
Definition: json-parser.h:97
bool MatchSkipWhiteSpace(uc32 c)
Definition: json-parser.h:85
Handle< String > source_
Definition: json-parser.h:185
Handle< Object > ParseJsonNumber()
Handle< SeqOneByteString > seq_source_
Definition: json-parser.h:187
Handle< String > ScanJsonString()
Handle< JSFunction > object_constructor()
Definition: json-parser.h:176
Handle< Object > ReportUnexpectedCharacter()
Definition: json-parser.h:170
Handle< Object > ParseJsonObject()
JsonParser(Handle< String > source)
Definition: json-parser.h:30
Handle< Object > ParseJsonArray()
Handle< String > SlowScanJsonString(Handle< String > prefix, int start, int end)
Handle< JSFunction > object_constructor_
Definition: json-parser.h:193
static MUST_USE_RESULT MaybeHandle< Object > Parse(Handle< String > source)
Definition: json-parser.h:23
Handle< String > ParseJsonInternalizedString()
Definition: json-parser.h:127
static Handle< T > cast(Handle< S > that)
Definition: handles.h:116
bool is_null() const
Definition: handles.h:124
static Handle< T > null()
Definition: handles.h:123
static uint32_t NextProbe(uint32_t last, uint32_t number, uint32_t size)
Definition: objects.h:3341
static uint32_t FirstProbe(uint32_t hash, uint32_t size)
Definition: objects.h:3337
static void AllocateStorageForMap(Handle< JSObject > object, Handle< Map > map)
Definition: objects.cc:3707
static MUST_USE_RESULT MaybeHandle< Object > SetOwnElement(Handle< JSObject > object, uint32_t index, Handle< Object > value, StrictMode strict_mode)
Definition: objects.cc:12327
static MUST_USE_RESULT Handle< HeapType > GeneralizeFieldType(Handle< HeapType > type1, Handle< HeapType > type2, Isolate *isolate)
Definition: objects.cc:2297
static Handle< String > ExpectedTransitionKey(Handle< Map > map)
Definition: objects-inl.h:1847
static Handle< Map > FindTransitionToField(Handle< Map > map, Handle< Name > key)
Definition: objects-inl.h:1869
static Handle< Map > ExpectedTransitionTarget(Handle< Map > map)
Definition: objects-inl.h:1862
static const int kHashShift
Definition: objects.h:8499
static const int kIsNotArrayIndexMask
Definition: objects.h:8495
static Handle< Object > NewStorageFor(Isolate *isolate, Handle< Object > object, Representation representation)
Definition: objects-inl.h:277
static MUST_USE_RESULT MaybeHandle< Object > DefineObjectProperty(Handle< JSObject > object, Handle< Object > key, Handle< Object > value, PropertyAttributes attr)
Definition: runtime.cc:2277
static MUST_USE_RESULT Handle< String > Truncate(Handle< SeqString > string, int new_length)
Definition: objects.cc:8883
static Smi * FromInt(int value)
Definition: objects-inl.h:1321
Vector< const uint8_t > ToOneByteVector()
Definition: objects.h:8639
static void WriteToFlat(String *source, sinkchar *sink, int from, int to)
Definition: objects.cc:8370
static const int32_t kMaxOneByteCharCode
Definition: objects.h:8811
static const int kMaxHashCalcLength
Definition: objects.h:8824
static Handle< String > Flatten(Handle< String > string, PretenureFlag pretenure=NOT_TENURED)
Definition: objects-inl.h:3354
static Vector< T > New(int length)
Definition: vector.h:27
enable harmony numeric enable harmony object literal extensions Optimize object Array DOM strings and string trace pretenuring decisions of HAllocate instructions Enables optimizations which favor memory size over execution speed maximum source size in bytes considered for a single inlining maximum cumulative number of AST nodes considered for inlining trace the tracking of allocation sites deoptimize every n garbage collections perform array bounds checks elimination analyze liveness of environment slots and zap dead values flushes the cache of optimized code for closures on every GC allow uint32 values on optimize frames if they are used only in safe operations track concurrent recompilation artificial compilation delay in ms do not emit check maps for constant values that have a leaf map
enable harmony numeric enable harmony object literal extensions Optimize object Array DOM strings and string trace pretenuring decisions of HAllocate instructions Enables optimizations which favor memory size over execution speed maximum source size in bytes considered for a single inlining maximum cumulative number of AST nodes considered for inlining trace the tracking of allocation sites deoptimize every n garbage collections perform array bounds checks elimination analyze liveness of environment slots and zap dead values flushes the cache of optimized code for closures on every GC allow uint32 values on optimize frames if they are used only in safe operations track concurrent recompilation artificial compilation delay in ms do not emit check maps for constant values that have a leaf deoptimize the optimized code if the layout of the maps changes enable context specialization in TurboFan execution budget before interrupt is triggered max percentage of megamorphic generic ICs to allow optimization enable use of SAHF instruction if enable use of VFP3 instructions if available enable use of NEON instructions if enable use of SDIV and UDIV instructions if enable use of MLS instructions if enable loading bit constant by means of movw movt instruction enable unaligned accesses for enable use of d16 d31 registers on ARM this requires VFP3 force all emitted branches to be in long enable alignment of csp to bytes on platforms which prefer the register to always be expose gc extension under the specified name show built in functions in stack traces use random jit cookie to mask large constants minimum length for automatic enable preparsing CPU profiler sampling interval in microseconds trace out of bounds accesses to external arrays default size of stack region v8 is allowed to maximum length of function source code printed in a stack trace min size of a semi the new space consists of two semi spaces print one trace line following each garbage collection do not print trace line after scavenger collection print cumulative GC statistics in name
#define ASSIGN_RETURN_ON_EXCEPTION(isolate, dst, call, T)
Definition: isolate.h:135
#define DCHECK(condition)
Definition: logging.h:205
#define DCHECK_EQ(v1, v2)
Definition: logging.h:206
#define MUST_USE_RESULT
Definition: macros.h:266
void SeqStringSet(Handle< StringType > seq_str, int i, uc32 c)
Handle< StringType > NewRawString(Factory *factory, int length, PretenureFlag pretenure)
Definition: json-parser.h:566
static LifetimePosition Min(LifetimePosition a, LifetimePosition b)
kSerializedDataOffset Object
Definition: objects-inl.h:5322
const int kUC16Size
Definition: globals.h:187
static LifetimePosition Max(LifetimePosition a, LifetimePosition b)
int AsciiAlphaToLower(uc32 c)
int HexValue(uc32 c)
Definition: scanner.h:31
int32_t uc32
Definition: globals.h:185
double StringToDouble(UnicodeCache *unicode_cache, const char *str, int flags, double empty_string_val)
Definition: conversions.cc:70
Debugger support for the V8 JavaScript engine.
Definition: accessors.cc:20
@ NONE