Specialize JSON parser to only check for SequentialAsciiString once.
authorsandholm@chromium.org <sandholm@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Wed, 8 Jun 2011 08:09:48 +0000 (08:09 +0000)
committersandholm@chromium.org <sandholm@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Wed, 8 Jun 2011 08:09:48 +0000 (08:09 +0000)
Review URL: http://codereview.chromium.org/7134010

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@8214 ce2b1a6d-e550-0410-aec6-3dcde31c8c00

src/SConscript
src/json-parser.cc [deleted file]
src/json-parser.h
src/runtime.cc
tools/gyp/v8.gyp

index 86bf337..5b2f272 100755 (executable)
@@ -85,7 +85,6 @@ SOURCES = {
     inspector.cc
     interpreter-irregexp.cc
     isolate.cc
-    json-parser.cc
     jsregexp.cc
     lithium-allocator.cc
     lithium.cc
diff --git a/src/json-parser.cc b/src/json-parser.cc
deleted file mode 100644 (file)
index 77a22b9..0000000
+++ /dev/null
@@ -1,412 +0,0 @@
-// Copyright 2011 the V8 project authors. All rights reserved.
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-//     * Redistributions of source code must retain the above copyright
-//       notice, this list of conditions and the following disclaimer.
-//     * Redistributions in binary form must reproduce the above
-//       copyright notice, this list of conditions and the following
-//       disclaimer in the documentation and/or other materials provided
-//       with the distribution.
-//     * Neither the name of Google Inc. nor the names of its
-//       contributors may be used to endorse or promote products derived
-//       from this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-#include "v8.h"
-
-#include "char-predicates-inl.h"
-#include "conversions.h"
-#include "json-parser.h"
-#include "messages.h"
-#include "spaces.h"
-
-namespace v8 {
-namespace internal {
-
-
-Handle<Object> JsonParser::ParseJson(Handle<String> source) {
-  isolate_ = source->map()->isolate();
-  source_ = Handle<String>(source->TryFlattenGetString());
-  source_length_ = source_->length() - 1;
-
-  // Optimized fast case where we only have ascii characters.
-  if (source_->IsSeqAsciiString()) {
-      is_sequential_ascii_ = true;
-      seq_source_ = Handle<SeqAsciiString>::cast(source_);
-  } else {
-    is_sequential_ascii_ = false;
-  }
-
-  // Set initial position right before the string.
-  position_ = -1;
-  // Advance to the first character (posibly EOS)
-  AdvanceSkipWhitespace();
-  Handle<Object> result = ParseJsonValue();
-  if (result.is_null() || c0_ != kEndOfString) {
-    // Parse failed. Current character is the unexpected token.
-
-    const char* message;
-    Factory* factory = isolate()->factory();
-    Handle<JSArray> array;
-
-    switch (c0_) {
-      case kEndOfString:
-        message = "unexpected_eos";
-        array = factory->NewJSArray(0);
-        break;
-      case '-':
-      case '0':
-      case '1':
-      case '2':
-      case '3':
-      case '4':
-      case '5':
-      case '6':
-      case '7':
-      case '8':
-      case '9':
-        message = "unexpected_token_number";
-        array = factory->NewJSArray(0);
-        break;
-      case '"':
-        message = "unexpected_token_string";
-        array = factory->NewJSArray(0);
-        break;
-      default:
-        message = "unexpected_token";
-        Handle<Object> name = LookupSingleCharacterStringFromCode(c0_);
-        Handle<FixedArray> element = factory->NewFixedArray(1);
-        element->set(0, *name);
-        array = factory->NewJSArrayWithElements(element);
-        break;
-    }
-
-    MessageLocation location(factory->NewScript(source),
-                             position_,
-                             position_ + 1);
-    Handle<Object> result = factory->NewSyntaxError(message, array);
-    isolate()->Throw(*result, &location);
-    return Handle<Object>::null();
-  }
-  return result;
-}
-
-
-// Parse any JSON value.
-Handle<Object> JsonParser::ParseJsonValue() {
-  switch (c0_) {
-    case '"':
-      return ParseJsonString();
-    case '-':
-    case '0':
-    case '1':
-    case '2':
-    case '3':
-    case '4':
-    case '5':
-    case '6':
-    case '7':
-    case '8':
-    case '9':
-      return ParseJsonNumber();
-    case 'f':
-      if (AdvanceGetChar() == 'a' && AdvanceGetChar() == 'l' &&
-          AdvanceGetChar() == 's' && AdvanceGetChar() == 'e') {
-        AdvanceSkipWhitespace();
-        return isolate()->factory()->false_value();
-      } else {
-        return ReportUnexpectedCharacter();
-      }
-    case 't':
-      if (AdvanceGetChar() == 'r' && AdvanceGetChar() == 'u' &&
-          AdvanceGetChar() == 'e') {
-        AdvanceSkipWhitespace();
-        return isolate()->factory()->true_value();
-      } else {
-        return ReportUnexpectedCharacter();
-      }
-    case 'n':
-      if (AdvanceGetChar() == 'u' && AdvanceGetChar() == 'l' &&
-          AdvanceGetChar() == 'l') {
-        AdvanceSkipWhitespace();
-        return isolate()->factory()->null_value();
-      } else {
-        return ReportUnexpectedCharacter();
-      }
-    case '{':
-      return ParseJsonObject();
-    case '[':
-      return ParseJsonArray();
-    default:
-      return ReportUnexpectedCharacter();
-  }
-}
-
-
-// Parse a JSON object. Position must be right at '{'.
-Handle<Object> JsonParser::ParseJsonObject() {
-  Handle<JSFunction> object_constructor(
-      isolate()->global_context()->object_function());
-  Handle<JSObject> json_object =
-      isolate()->factory()->NewJSObject(object_constructor);
-  ASSERT_EQ(c0_, '{');
-
-  AdvanceSkipWhitespace();
-  if (c0_ != '}') {
-    do {
-      if (c0_ != '"') return ReportUnexpectedCharacter();
-      Handle<String> key = ParseJsonSymbol();
-      if (key.is_null() || c0_ != ':') return ReportUnexpectedCharacter();
-      AdvanceSkipWhitespace();
-      Handle<Object> value = ParseJsonValue();
-      if (value.is_null()) return ReportUnexpectedCharacter();
-
-      uint32_t index;
-      if (key->AsArrayIndex(&index)) {
-        SetOwnElement(json_object, index, value, kNonStrictMode);
-      } else if (key->Equals(isolate()->heap()->Proto_symbol())) {
-        SetPrototype(json_object, value);
-      } else {
-        SetLocalPropertyIgnoreAttributes(json_object, key, value, NONE);
-      }
-    } while (MatchSkipWhiteSpace(','));
-    if (c0_ != '}') {
-      return ReportUnexpectedCharacter();
-    }
-  }
-  AdvanceSkipWhitespace();
-  return json_object;
-}
-
-// Parse a JSON array. Position must be right at '['.
-Handle<Object> JsonParser::ParseJsonArray() {
-  ZoneScope zone_scope(isolate(), DELETE_ON_EXIT);
-  ZoneList<Handle<Object> > elements(4);
-  ASSERT_EQ(c0_, '[');
-
-  AdvanceSkipWhitespace();
-  if (c0_ != ']') {
-    do {
-      Handle<Object> element = ParseJsonValue();
-      if (element.is_null()) return ReportUnexpectedCharacter();
-      elements.Add(element);
-    } while (MatchSkipWhiteSpace(','));
-    if (c0_ != ']') {
-      return ReportUnexpectedCharacter();
-    }
-  }
-  AdvanceSkipWhitespace();
-  // Allocate a fixed array with all the elements.
-  Handle<FixedArray> fast_elements =
-      isolate()->factory()->NewFixedArray(elements.length());
-  for (int i = 0, n = elements.length(); i < n; i++) {
-    fast_elements->set(i, *elements[i]);
-  }
-  return isolate()->factory()->NewJSArrayWithElements(fast_elements);
-}
-
-
-Handle<Object> JsonParser::ParseJsonNumber() {
-  bool negative = false;
-  beg_pos_ = position_;
-  if (c0_ == '-') {
-    Advance();
-    negative = true;
-  }
-  if (c0_ == '0') {
-    Advance();
-    // Prefix zero is only allowed if it's the only digit before
-    // a decimal point or exponent.
-    if ('0' <= c0_ && c0_ <= '9') return ReportUnexpectedCharacter();
-  } else {
-    int i = 0;
-    int digits = 0;
-    if (c0_ < '1' || c0_ > '9') return ReportUnexpectedCharacter();
-    do {
-      i = i * 10 + c0_ - '0';
-      digits++;
-      Advance();
-    } while (c0_ >= '0' && c0_ <= '9');
-    if (c0_ != '.' && c0_ != 'e' && c0_ != 'E' && digits < 10) {
-      number_ = (negative ? -i : i);
-      SkipWhitespace();
-      return isolate()->factory()->NewNumber(number_);
-    }
-  }
-  if (c0_ == '.') {
-    Advance();
-    if (c0_ < '0' || c0_ > '9') return ReportUnexpectedCharacter();
-    do {
-      Advance();
-    } while (c0_ >= '0' && c0_ <= '9');
-  }
-  if (AsciiAlphaToLower(c0_) == 'e') {
-    Advance();
-    if (c0_ == '-' || c0_ == '+') Advance();
-    if (c0_ < '0' || c0_ > '9') return ReportUnexpectedCharacter();
-    do {
-      Advance();
-    } while (c0_ >= '0' && c0_ <= '9');
-  }
-  int length = position_ - beg_pos_;
-  if (is_sequential_ascii_) {
-    Vector<const char> chars(seq_source_->GetChars() +  beg_pos_, length);
-    number_ = StringToDouble(isolate()->unicode_cache(),
-                             chars,
-                             NO_FLAGS,  // Hex, octal or trailing junk.
-                             OS::nan_value());
-  } else {
-    Vector<char> buffer = Vector<char>::New(length);
-    String::WriteToFlat(*source_, buffer.start(), beg_pos_, position_);
-    Vector<const char> result =
-        Vector<const char>(reinterpret_cast<const char*>(buffer.start()),
-        length);
-    number_ = StringToDouble(isolate()->unicode_cache(),
-                             result,
-                             NO_FLAGS,  // Hex, octal or trailing junk.
-                             0.0);
-    buffer.Dispose();
-  }
-  SkipWhitespace();
-  return isolate()->factory()->NewNumber(number_);
-}
-
-Handle<String> JsonParser::SlowScanJsonString() {
-  // The currently scanned ascii characters.
-  Handle<String> ascii(isolate()->factory()->NewSubString(source_,
-                                                          beg_pos_,
-                                                          position_));
-  Handle<String> two_byte =
-      isolate()->factory()->NewRawTwoByteString(kInitialSpecialStringSize,
-                                                NOT_TENURED);
-  Handle<SeqTwoByteString> seq_two_byte =
-      Handle<SeqTwoByteString>::cast(two_byte);
-
-  int allocation_count = 1;
-  int count = 0;
-
-  while (c0_ != '"') {
-    // Create new seq string
-    if (count >= kInitialSpecialStringSize * allocation_count) {
-      allocation_count = allocation_count * 2;
-      int new_size = allocation_count * kInitialSpecialStringSize;
-      Handle<String> new_two_byte =
-          isolate()->factory()->NewRawTwoByteString(new_size,
-                                                    NOT_TENURED);
-      uc16* char_start =
-          Handle<SeqTwoByteString>::cast(new_two_byte)->GetChars();
-      String::WriteToFlat(*seq_two_byte, char_start, 0, count);
-      seq_two_byte = Handle<SeqTwoByteString>::cast(new_two_byte);
-    }
-
-    // Check for control character (0x00-0x1f) or unterminated string (<0).
-    if (c0_ < 0x20) return Handle<String>::null();
-    if (c0_ != '\\') {
-      seq_two_byte->SeqTwoByteStringSet(count++, c0_);
-      Advance();
-    } else {
-      Advance();
-      switch (c0_) {
-        case '"':
-        case '\\':
-        case '/':
-          seq_two_byte->SeqTwoByteStringSet(count++, c0_);
-          break;
-        case 'b':
-          seq_two_byte->SeqTwoByteStringSet(count++, '\x08');
-          break;
-        case 'f':
-          seq_two_byte->SeqTwoByteStringSet(count++, '\x0c');
-          break;
-        case 'n':
-          seq_two_byte->SeqTwoByteStringSet(count++, '\x0a');
-          break;
-        case 'r':
-          seq_two_byte->SeqTwoByteStringSet(count++, '\x0d');
-          break;
-        case 't':
-          seq_two_byte->SeqTwoByteStringSet(count++, '\x09');
-          break;
-        case 'u': {
-          uc32 value = 0;
-          for (int i = 0; i < 4; i++) {
-            Advance();
-            int digit = HexValue(c0_);
-            if (digit < 0) {
-              return Handle<String>::null();
-            }
-            value = value * 16 + digit;
-          }
-          seq_two_byte->SeqTwoByteStringSet(count++, value);
-          break;
-        }
-        default:
-          return Handle<String>::null();
-      }
-      Advance();
-    }
-  }
-  // Advance past the last '"'.
-  ASSERT_EQ('"', c0_);
-  AdvanceSkipWhitespace();
-
-  // Shrink the the string to our length.
-  if (isolate()->heap()->InNewSpace(*seq_two_byte)) {
-    isolate()->heap()->new_space()->
-          ShrinkStringAtAllocationBoundary<SeqTwoByteString>(*seq_two_byte,
-                                                             count);
-  } else {
-    int string_size = SeqTwoByteString::SizeFor(count);
-    int allocated_string_size =
-        SeqTwoByteString::SizeFor(kInitialSpecialStringSize * allocation_count);
-    int delta = allocated_string_size - string_size;
-    Address start_filler_object = seq_two_byte->address() + string_size;
-    seq_two_byte->set_length(count);
-    isolate()->heap()->CreateFillerObjectAt(start_filler_object, delta);
-  }
-  return isolate()->factory()->NewConsString(ascii, seq_two_byte);
-}
-
-
-template <bool is_symbol>
-Handle<String> JsonParser::ScanJsonString() {
-  ASSERT_EQ('"', c0_);
-  Advance();
-  beg_pos_ = position_;
-  // Fast case for ascii only without escape characters.
-  while (c0_ != '"') {
-    // Check for control character (0x00-0x1f) or unterminated string (<0).
-    if (c0_ < 0x20) return Handle<String>::null();
-    if (c0_ != '\\' && c0_ < kMaxAsciiCharCode) {
-      Advance();
-    } else {
-      return SlowScanJsonString();
-    }
-  }
-  ASSERT_EQ('"', c0_);
-  end_pos_ = position_;
-  // Advance past the last '"'.
-  AdvanceSkipWhitespace();
-  if (is_sequential_ascii_ && is_symbol) {
-    return isolate()->factory()->LookupAsciiSymbol(seq_source_,
-                                                   beg_pos_,
-                                                   end_pos_ - beg_pos_);
-  } else {
-    return isolate()->factory()->NewSubString(source_, beg_pos_, end_pos_);
-  }
-}
-
-} }  // namespace v8::internal
index 2422c92..3be2fe1 100644 (file)
 #ifndef V8_JSON_PARSER_H_
 #define V8_JSON_PARSER_H_
 
+#include "v8.h"
+
+#include "char-predicates-inl.h"
+#include "conversions.h"
+#include "messages.h"
+#include "spaces-inl.h"
 #include "token.h"
 
 namespace v8 {
 namespace internal {
 
 // A simple json parser.
+template <bool seq_ascii>
 class JsonParser BASE_EMBEDDED {
  public:
   static Handle<Object> Parse(Handle<String> source) {
@@ -50,7 +57,7 @@ class JsonParser BASE_EMBEDDED {
     position_++;
     if (position_ > source_length_) {
       c0_ = kEndOfString;
-    } else if (is_sequential_ascii_) {
+    } else if (seq_ascii) {
       c0_ = seq_source_->SeqAsciiStringGet(position_);
     } else {
       c0_ = source_->Get(position_);
@@ -149,7 +156,6 @@ class JsonParser BASE_EMBEDDED {
   int source_length_;
   Handle<SeqAsciiString> seq_source_;
 
-  bool is_sequential_ascii_;
   // begin and end position of scanned string or number
   int beg_pos_;
   int end_pos_;
@@ -161,6 +167,381 @@ class JsonParser BASE_EMBEDDED {
   double number_;
 };
 
+template <bool seq_ascii>
+Handle<Object> JsonParser<seq_ascii>::ParseJson(Handle<String> source) {
+  isolate_ = source->map()->isolate();
+  source_ = Handle<String>(source->TryFlattenGetString());
+  source_length_ = source_->length() - 1;
+
+  // Optimized fast case where we only have ascii characters.
+  if (seq_ascii) {
+    seq_source_ = Handle<SeqAsciiString>::cast(source_);
+  }
+
+  // Set initial position right before the string.
+  position_ = -1;
+  // Advance to the first character (posibly EOS)
+  AdvanceSkipWhitespace();
+  Handle<Object> result = ParseJsonValue();
+  if (result.is_null() || c0_ != kEndOfString) {
+    // Parse failed. Current character is the unexpected token.
+
+    const char* message;
+    Factory* factory = isolate()->factory();
+    Handle<JSArray> array;
+
+    switch (c0_) {
+      case kEndOfString:
+        message = "unexpected_eos";
+        array = factory->NewJSArray(0);
+        break;
+      case '-':
+      case '0':
+      case '1':
+      case '2':
+      case '3':
+      case '4':
+      case '5':
+      case '6':
+      case '7':
+      case '8':
+      case '9':
+        message = "unexpected_token_number";
+        array = factory->NewJSArray(0);
+        break;
+      case '"':
+        message = "unexpected_token_string";
+        array = factory->NewJSArray(0);
+        break;
+      default:
+        message = "unexpected_token";
+        Handle<Object> name = LookupSingleCharacterStringFromCode(c0_);
+        Handle<FixedArray> element = factory->NewFixedArray(1);
+        element->set(0, *name);
+        array = factory->NewJSArrayWithElements(element);
+        break;
+    }
+
+    MessageLocation location(factory->NewScript(source),
+                             position_,
+                             position_ + 1);
+    Handle<Object> result = factory->NewSyntaxError(message, array);
+    isolate()->Throw(*result, &location);
+    return Handle<Object>::null();
+  }
+  return result;
+}
+
+
+// Parse any JSON value.
+template <bool seq_ascii>
+Handle<Object> JsonParser<seq_ascii>::ParseJsonValue() {
+  switch (c0_) {
+    case '"':
+      return ParseJsonString();
+    case '-':
+    case '0':
+    case '1':
+    case '2':
+    case '3':
+    case '4':
+    case '5':
+    case '6':
+    case '7':
+    case '8':
+    case '9':
+      return ParseJsonNumber();
+    case 'f':
+      if (AdvanceGetChar() == 'a' && AdvanceGetChar() == 'l' &&
+          AdvanceGetChar() == 's' && AdvanceGetChar() == 'e') {
+        AdvanceSkipWhitespace();
+        return isolate()->factory()->false_value();
+      } else {
+        return ReportUnexpectedCharacter();
+      }
+    case 't':
+      if (AdvanceGetChar() == 'r' && AdvanceGetChar() == 'u' &&
+          AdvanceGetChar() == 'e') {
+        AdvanceSkipWhitespace();
+        return isolate()->factory()->true_value();
+      } else {
+        return ReportUnexpectedCharacter();
+      }
+    case 'n':
+      if (AdvanceGetChar() == 'u' && AdvanceGetChar() == 'l' &&
+          AdvanceGetChar() == 'l') {
+        AdvanceSkipWhitespace();
+        return isolate()->factory()->null_value();
+      } else {
+        return ReportUnexpectedCharacter();
+      }
+    case '{':
+      return ParseJsonObject();
+    case '[':
+      return ParseJsonArray();
+    default:
+      return ReportUnexpectedCharacter();
+  }
+}
+
+
+// Parse a JSON object. Position must be right at '{'.
+template <bool seq_ascii>
+Handle<Object> JsonParser<seq_ascii>::ParseJsonObject() {
+  Handle<JSFunction> object_constructor(
+      isolate()->global_context()->object_function());
+  Handle<JSObject> json_object =
+      isolate()->factory()->NewJSObject(object_constructor);
+  ASSERT_EQ(c0_, '{');
+
+  AdvanceSkipWhitespace();
+  if (c0_ != '}') {
+    do {
+      if (c0_ != '"') return ReportUnexpectedCharacter();
+      Handle<String> key = ParseJsonSymbol();
+      if (key.is_null() || c0_ != ':') return ReportUnexpectedCharacter();
+      AdvanceSkipWhitespace();
+      Handle<Object> value = ParseJsonValue();
+      if (value.is_null()) return ReportUnexpectedCharacter();
+
+      uint32_t index;
+      if (key->AsArrayIndex(&index)) {
+        SetOwnElement(json_object, index, value, kNonStrictMode);
+      } else if (key->Equals(isolate()->heap()->Proto_symbol())) {
+        SetPrototype(json_object, value);
+      } else {
+        SetLocalPropertyIgnoreAttributes(json_object, key, value, NONE);
+      }
+    } while (MatchSkipWhiteSpace(','));
+    if (c0_ != '}') {
+      return ReportUnexpectedCharacter();
+    }
+  }
+  AdvanceSkipWhitespace();
+  return json_object;
+}
+
+// Parse a JSON array. Position must be right at '['.
+template <bool seq_ascii>
+Handle<Object> JsonParser<seq_ascii>::ParseJsonArray() {
+  ZoneScope zone_scope(isolate(), DELETE_ON_EXIT);
+  ZoneList<Handle<Object> > elements(4);
+  ASSERT_EQ(c0_, '[');
+
+  AdvanceSkipWhitespace();
+  if (c0_ != ']') {
+    do {
+      Handle<Object> element = ParseJsonValue();
+      if (element.is_null()) return ReportUnexpectedCharacter();
+      elements.Add(element);
+    } while (MatchSkipWhiteSpace(','));
+    if (c0_ != ']') {
+      return ReportUnexpectedCharacter();
+    }
+  }
+  AdvanceSkipWhitespace();
+  // Allocate a fixed array with all the elements.
+  Handle<FixedArray> fast_elements =
+      isolate()->factory()->NewFixedArray(elements.length());
+  for (int i = 0, n = elements.length(); i < n; i++) {
+    fast_elements->set(i, *elements[i]);
+  }
+  return isolate()->factory()->NewJSArrayWithElements(fast_elements);
+}
+
+
+template <bool seq_ascii>
+Handle<Object> JsonParser<seq_ascii>::ParseJsonNumber() {
+  bool negative = false;
+  beg_pos_ = position_;
+  if (c0_ == '-') {
+    Advance();
+    negative = true;
+  }
+  if (c0_ == '0') {
+    Advance();
+    // Prefix zero is only allowed if it's the only digit before
+    // a decimal point or exponent.
+    if ('0' <= c0_ && c0_ <= '9') return ReportUnexpectedCharacter();
+  } else {
+    int i = 0;
+    int digits = 0;
+    if (c0_ < '1' || c0_ > '9') return ReportUnexpectedCharacter();
+    do {
+      i = i * 10 + c0_ - '0';
+      digits++;
+      Advance();
+    } while (c0_ >= '0' && c0_ <= '9');
+    if (c0_ != '.' && c0_ != 'e' && c0_ != 'E' && digits < 10) {
+      number_ = (negative ? -i : i);
+      SkipWhitespace();
+      return isolate()->factory()->NewNumber(number_);
+    }
+  }
+  if (c0_ == '.') {
+    Advance();
+    if (c0_ < '0' || c0_ > '9') return ReportUnexpectedCharacter();
+    do {
+      Advance();
+    } while (c0_ >= '0' && c0_ <= '9');
+  }
+  if (AsciiAlphaToLower(c0_) == 'e') {
+    Advance();
+    if (c0_ == '-' || c0_ == '+') Advance();
+    if (c0_ < '0' || c0_ > '9') return ReportUnexpectedCharacter();
+    do {
+      Advance();
+    } while (c0_ >= '0' && c0_ <= '9');
+  }
+  int length = position_ - beg_pos_;
+  if (seq_ascii) {
+    Vector<const char> chars(seq_source_->GetChars() +  beg_pos_, length);
+    number_ = StringToDouble(isolate()->unicode_cache(),
+                             chars,
+                             NO_FLAGS,  // Hex, octal or trailing junk.
+                             OS::nan_value());
+  } else {
+    Vector<char> buffer = Vector<char>::New(length);
+    String::WriteToFlat(*source_, buffer.start(), beg_pos_, position_);
+    Vector<const char> result =
+        Vector<const char>(reinterpret_cast<const char*>(buffer.start()),
+        length);
+    number_ = StringToDouble(isolate()->unicode_cache(),
+                             result,
+                             NO_FLAGS,  // Hex, octal or trailing junk.
+                             0.0);
+    buffer.Dispose();
+  }
+  SkipWhitespace();
+  return isolate()->factory()->NewNumber(number_);
+}
+
+template <bool seq_ascii>
+Handle<String> JsonParser<seq_ascii>::SlowScanJsonString() {
+  // The currently scanned ascii characters.
+  Handle<String> ascii(isolate()->factory()->NewSubString(source_,
+                                                          beg_pos_,
+                                                          position_));
+  Handle<String> two_byte =
+      isolate()->factory()->NewRawTwoByteString(kInitialSpecialStringSize,
+                                                NOT_TENURED);
+  Handle<SeqTwoByteString> seq_two_byte =
+      Handle<SeqTwoByteString>::cast(two_byte);
+
+  int allocation_count = 1;
+  int count = 0;
+
+  while (c0_ != '"') {
+    // Create new seq string
+    if (count >= kInitialSpecialStringSize * allocation_count) {
+      allocation_count = allocation_count * 2;
+      int new_size = allocation_count * kInitialSpecialStringSize;
+      Handle<String> new_two_byte =
+          isolate()->factory()->NewRawTwoByteString(new_size,
+                                                    NOT_TENURED);
+      uc16* char_start =
+          Handle<SeqTwoByteString>::cast(new_two_byte)->GetChars();
+      String::WriteToFlat(*seq_two_byte, char_start, 0, count);
+      seq_two_byte = Handle<SeqTwoByteString>::cast(new_two_byte);
+    }
+
+    // Check for control character (0x00-0x1f) or unterminated string (<0).
+    if (c0_ < 0x20) return Handle<String>::null();
+    if (c0_ != '\\') {
+      seq_two_byte->SeqTwoByteStringSet(count++, c0_);
+      Advance();
+    } else {
+      Advance();
+      switch (c0_) {
+        case '"':
+        case '\\':
+        case '/':
+          seq_two_byte->SeqTwoByteStringSet(count++, c0_);
+          break;
+        case 'b':
+          seq_two_byte->SeqTwoByteStringSet(count++, '\x08');
+          break;
+        case 'f':
+          seq_two_byte->SeqTwoByteStringSet(count++, '\x0c');
+          break;
+        case 'n':
+          seq_two_byte->SeqTwoByteStringSet(count++, '\x0a');
+          break;
+        case 'r':
+          seq_two_byte->SeqTwoByteStringSet(count++, '\x0d');
+          break;
+        case 't':
+          seq_two_byte->SeqTwoByteStringSet(count++, '\x09');
+          break;
+        case 'u': {
+          uc32 value = 0;
+          for (int i = 0; i < 4; i++) {
+            Advance();
+            int digit = HexValue(c0_);
+            if (digit < 0) {
+              return Handle<String>::null();
+            }
+            value = value * 16 + digit;
+          }
+          seq_two_byte->SeqTwoByteStringSet(count++, value);
+          break;
+        }
+        default:
+          return Handle<String>::null();
+      }
+      Advance();
+    }
+  }
+  // Advance past the last '"'.
+  ASSERT_EQ('"', c0_);
+  AdvanceSkipWhitespace();
+
+  // Shrink the the string to our length.
+  if (isolate()->heap()->InNewSpace(*seq_two_byte)) {
+    isolate()->heap()->new_space()->
+        template ShrinkStringAtAllocationBoundary<SeqTwoByteString>(
+            *seq_two_byte, count);
+  } else {
+    int string_size = SeqTwoByteString::SizeFor(count);
+    int allocated_string_size =
+        SeqTwoByteString::SizeFor(kInitialSpecialStringSize * allocation_count);
+    int delta = allocated_string_size - string_size;
+    Address start_filler_object = seq_two_byte->address() + string_size;
+    seq_two_byte->set_length(count);
+    isolate()->heap()->CreateFillerObjectAt(start_filler_object, delta);
+  }
+  return isolate()->factory()->NewConsString(ascii, seq_two_byte);
+}
+
+template <bool seq_ascii>
+template <bool is_symbol>
+Handle<String> JsonParser<seq_ascii>::ScanJsonString() {
+  ASSERT_EQ('"', c0_);
+  Advance();
+  beg_pos_ = position_;
+  // Fast case for ascii only without escape characters.
+  while (c0_ != '"') {
+    // Check for control character (0x00-0x1f) or unterminated string (<0).
+    if (c0_ < 0x20) return Handle<String>::null();
+    if (c0_ != '\\' && (seq_ascii || c0_ < kMaxAsciiCharCode)) {
+      Advance();
+    } else {
+      return this->SlowScanJsonString();
+    }
+  }
+  ASSERT_EQ('"', c0_);
+  end_pos_ = position_;
+  // Advance past the last '"'.
+  AdvanceSkipWhitespace();
+  if (seq_ascii && is_symbol) {
+    return isolate()->factory()->LookupAsciiSymbol(seq_source_,
+                                                   beg_pos_,
+                                                   end_pos_ - beg_pos_);
+  } else {
+    return isolate()->factory()->NewSubString(source_, beg_pos_, end_pos_);
+  }
+}
+
 } }  // namespace v8::internal
 
 #endif  // V8_JSON_PARSER_H_
index 1fffa82..60e39d6 100644 (file)
@@ -8480,7 +8480,14 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_ParseJson) {
   ASSERT_EQ(1, args.length());
   CONVERT_ARG_CHECKED(String, source, 0);
 
-  Handle<Object> result = JsonParser::Parse(source);
+  source = Handle<String>(source->TryFlattenGetString());
+  // Optimized fast case where we only have ascii characters.
+  Handle<Object> result;
+  if (source->IsSeqAsciiString()) {
+    result = JsonParser<true>::Parse(source);
+  } else {
+    result = JsonParser<false>::Parse(source);
+  }
   if (result.is_null()) {
     // Syntax error or stack overflow in scanner.
     ASSERT(isolate->has_pending_exception());
index 03e459c..469d468 100644 (file)
             '../../src/inspector.h',
             '../../src/interpreter-irregexp.cc',
             '../../src/interpreter-irregexp.h',
-            '../../src/json-parser.cc',
             '../../src/json-parser.h',
             '../../src/jsregexp.cc',
             '../../src/jsregexp.h',