Fix JSON.stringifier's slow path wrt external strings.
authoryangguo@chromium.org <yangguo@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Fri, 22 Mar 2013 08:42:38 +0000 (08:42 +0000)
committeryangguo@chromium.org <yangguo@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Fri, 22 Mar 2013 08:42:38 +0000 (08:42 +0000)
R=verwaest@chromium.org
BUG=

Review URL: https://chromiumcodereview.appspot.com/12825016

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

src/json-stringifier.h
test/mjsunit/json2.js

index 418d479..60614f4 100644 (file)
@@ -87,9 +87,9 @@ class BasicJsonStringifier BASE_EMBEDDED {
                           bool deferred_comma,
                           bool deferred_key);
 
-  template <typename StringType>
+  template <typename ResultType, typename Char>
   INLINE(static MaybeObject* StringifyString_(Isolate* isolate,
-                                              Handle<String> string,
+                                              Vector<Char> vector,
                                               Handle<String> result));
 
   // Entry point to serialize the object.
@@ -295,36 +295,38 @@ MaybeObject* BasicJsonStringifier::StringifyString(Isolate* isolate,
     return stringifier.Stringify(object);
   }
 
-  object = FlattenGetString(object);
-  if (object->IsSeqOneByteString()) {
+  FlattenString(object);
+  String::FlatContent flat = object->GetFlatContent();
+  if (flat.IsAscii()) {
     return StringifyString_<SeqOneByteString>(
         isolate,
-        object,
+        flat.ToOneByteVector(),
         isolate->factory()->NewRawOneByteString(worst_case_length));
   } else {
+    ASSERT(flat.IsTwoByte());
     return StringifyString_<SeqTwoByteString>(
         isolate,
-        object,
+        flat.ToUC16Vector(),
         isolate->factory()->NewRawTwoByteString(worst_case_length));
   }
 }
 
 
-template <typename StringType>
+template <typename ResultType, typename Char>
 MaybeObject* BasicJsonStringifier::StringifyString_(Isolate* isolate,
-                                                    Handle<String> string,
+                                                    Vector<Char> vector,
                                                     Handle<String> result) {
   AssertNoAllocation no_allocation;
   int final_size = 0;
-  StringType* dest = StringType::cast(*result);
+  ResultType* dest = ResultType::cast(*result);
   dest->Set(final_size++, '\"');
-  final_size += SerializeStringUnchecked_(StringType::cast(*string)->GetChars(),
+  final_size += SerializeStringUnchecked_(vector.start(),
                                           dest->GetChars() + 1,
-                                          string->length());
+                                          vector.length());
   dest->Set(final_size++, '\"');
   if (isolate->heap()->InNewSpace(*result)) {
     // In new space, simply lower the allocation top to fit the actual size.
-    isolate->heap()->new_space()->ShrinkStringAtAllocationBoundary<StringType>(
+    isolate->heap()->new_space()->ShrinkStringAtAllocationBoundary<ResultType>(
         *result, final_size);
     return *result;
   } else {
index 6a72051..cf20b90 100644 (file)
@@ -25,7 +25,7 @@
 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
-// Flags: --allow-natives-syntax
+// Flags: --allow-natives-syntax --expose-externalize-string
 
 // Test JSON.stringify on the global object.
 var a = 12345;
@@ -172,3 +172,9 @@ non_enum.a = 1;
 Object.defineProperty(non_enum, "b", { value: 2, enumerable: false });
 non_enum.c = 3;
 TestStringify('{"a":1,"c":3}', non_enum);
+
+var str = "external";
+try {
+  externalizeString(str, true);
+} catch (e) { }
+TestStringify("\"external\"", str, null, 0);