Reviewers: ulan,

Description:
Correctly check for stack limit in JSON.stringify.

Changes include:
 - inline functions in a way as not to waste stack space.
 - reset StackReserveSize to the value prior to r12808.
 - check stack overflow dynamically.


[email protected]
BUG=


Please review this at https://chromiumcodereview.appspot.com/11271021/

SVN Base: https://v8.googlecode.com/svn/branches/bleeding_edge

Affected files:
  M build/common.gypi
  M src/json-stringifier.h
  M test/mjsunit/json-recursive.js


Index: build/common.gypi
diff --git a/build/common.gypi b/build/common.gypi
index e0564989e62014dd62072f10b746fee942a02f4e..97f0aae6643802f34858d812baea4ee4df89f178 100644
--- a/build/common.gypi
+++ b/build/common.gypi
@@ -180,11 +180,6 @@
         'defines': [
           'V8_TARGET_ARCH_IA32',
         ],
-        'msvs_settings': {
-          'VCLinkerTool': {
-            'StackReserveSize': '4194304',
-          },
-        },
       }],  # v8_target_arch=="ia32"
       ['v8_target_arch=="mipsel"', {
         'defines': [
@@ -251,7 +246,7 @@
         },
         'msvs_settings': {
           'VCLinkerTool': {
-            'StackReserveSize': '8388608',
+            'StackReserveSize': '2097152',
           },
         },
         'msvs_configuration_platform': 'x64',
Index: src/json-stringifier.h
diff --git a/src/json-stringifier.h b/src/json-stringifier.h
index 3f59ca2f63abf68e05bb53f24f24fbbaf595aa26..070a3ddd538523c1693ec7d43d4ff6b36ecb86d0 100644
--- a/src/json-stringifier.h
+++ b/src/json-stringifier.h
@@ -45,7 +45,6 @@ class BasicJsonStringifier BASE_EMBEDDED {
   static const int kInitialPartLength = 32;
   static const int kMaxPartLength = 16 * 1024;
   static const int kPartLengthGrowthFactor = 2;
-  static const int kStackLimit = 4 * 1024;

   enum Result { UNCHANGED, SUCCESS, BAILOUT, CIRCULAR, STACK_OVERFLOW };

@@ -77,10 +76,10 @@ class BasicJsonStringifier BASE_EMBEDDED {
     }
   }

-  INLINE(Handle<Object> GetProperty(Handle<JSObject> object,
-                                    Handle<String> key));
+  Handle<Object> GetProperty(Handle<JSObject> object,
+                             Handle<String> key);

-  INLINE(bool MayHaveToJsonFunction(Handle<JSObject> object));
+  bool MayHaveToJsonFunction(Handle<JSObject> object);

   INLINE(Result Serialize(Handle<Object> object)) {
     return Serialize_<false>(object);
@@ -98,22 +97,21 @@ class BasicJsonStringifier BASE_EMBEDDED {
                     bool comma = false,
                     Handle<String> key = Handle<String>::null());

-  INLINE(void SerializeDeferredKey(bool deferred_comma,
-                                   Handle<String> deferred_key)) {
+ void SerializeDeferredKey(bool deferred_comma, Handle<String> deferred_key) {
     if (deferred_comma) Append(',');
     SerializeString(deferred_key);
     Append(':');
   }

-  INLINE(Result SerializeSmi(Smi* object));
+  Result SerializeSmi(Smi* object);

-  INLINE(Result SerializeDouble(double number));
+  Result SerializeDouble(double number);
   INLINE(Result SerializeHeapNumber(Handle<HeapNumber> object)) {
     return SerializeDouble(object->value());
   }

-  Result SerializeArray(Handle<JSArray> object);
-  Result SerializeObject(Handle<JSObject> object);
+  INLINE(Result SerializeArray(Handle<JSArray> object));
+  INLINE(Result SerializeObject(Handle<JSObject> object));

   void SerializeString(Handle<String> object);

@@ -132,8 +130,8 @@ class BasicJsonStringifier BASE_EMBEDDED {
   template <typename Char>
   INLINE(Vector<const Char> GetCharVector(Handle<String> string));

-  INLINE(Result StackPush(Handle<Object> object));
-  INLINE(void StackPop());
+  Result StackPush(Handle<Object> object);
+  void StackPop();

   INLINE(Handle<String> accumulator()) {
     return Handle<String>(String::cast(accumulator_store_->value()));
@@ -298,8 +296,10 @@ bool BasicJsonStringifier::MayHaveToJsonFunction(Handle<JSObject> object) {

 BasicJsonStringifier::Result BasicJsonStringifier::StackPush(
     Handle<Object> object) {
+  StackLimitCheck check(isolate_);
+  if (check.HasOverflowed()) return STACK_OVERFLOW;
+
   int length = Smi::cast(stack_->length())->value();
-  if (length > kStackLimit) return STACK_OVERFLOW;
   FixedArray* elements = FixedArray::cast(stack_->elements());
   for (int i = 0; i < length; i++) {
     if (elements->get(i) == *object) {
@@ -473,9 +473,8 @@ BasicJsonStringifier::Result BasicJsonStringifier::SerializeObject(
       GetKeysInFixedArrayFor(object, LOCAL_ONLY, &threw);
   if (threw) return BAILOUT;
   Append('{');
-  int length = contents->length();
   bool comma = false;
-  for (int i = 0; i < length; i++) {
+  for (int i = 0; i < contents->length(); i++) {
     Object* key = contents->get(i);
     Handle<String> key_handle;
     Handle<Object> property;
Index: test/mjsunit/json-recursive.js
diff --git a/test/mjsunit/json-recursive.js b/test/mjsunit/json-recursive.js
index 7c7b1465cca86e7491e0258b08ff0aa6fcdcea03..adfd93bbcd6f693f8ffad2d758eed5009899b591 100644
--- a/test/mjsunit/json-recursive.js
+++ b/test/mjsunit/json-recursive.js
@@ -42,15 +42,17 @@ assertThrows(function() { rec(1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4) },
              RangeError);


+var depth1 = 2048;
+var depth2 = 10000;
 var deepArray = [];
-for (var i = 0; i < 2048; i++) deepArray = [deepArray];
+for (var i = 0; i < depth1; i++) deepArray = [deepArray];
 JSON.stringify(deepArray);
-for (var i = 2048; i < 4097; i++) deepArray = [deepArray];
+for (var i = depth1; i < depth2; i++) deepArray = [deepArray];
 assertThrows(function() { JSON.stringify(deepArray); }, RangeError);


 var deepObject = {};
-for (var i = 0; i < 2048; i++) deepObject = { next: deepObject };
+for (var i = 0; i < depth1; i++) deepObject = { next: deepObject };
 JSON.stringify(deepObject);
-for (var i = 2048; i < 4097; i++) deepObject = { next: deepObject };
+for (var i = depth1; i < depth2; i++) deepObject = { next: deepObject };
 assertThrows(function() { JSON.stringify(deepObject); }, RangeError);


--
v8-dev mailing list
[email protected]
http://groups.google.com/group/v8-dev

Reply via email to