Reviewers: Vyacheslav Egorov,

Message:
PTAL.

Description:
Release stack trace data after firing Error.stack accessor.

BUG=v8:2308


Please review this at http://codereview.chromium.org/10886012/

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

Affected files:
  M src/messages.js
  M test/cctest/test-heap.cc


Index: src/messages.js
diff --git a/src/messages.js b/src/messages.js
index 4da38051f9200746250867e23f9cc4228c524178..a947bbfbe05aab380e6a78ca5b264d07f380ce63 100644
--- a/src/messages.js
+++ b/src/messages.js
@@ -766,18 +766,18 @@ function DefineOneShotAccessor(obj, name, fun) {
   // Note that the accessors consistently operate on 'obj', not 'this'.
   // Since the object may occur in someone else's prototype chain we
   // can't rely on 'this' being the same as 'obj'.
-  var hasBeenSet = false;
   var value;
+  var getter_function = fun;
   var getter = function() {
-    if (hasBeenSet) {
+    if (getter_function == null) {
       return value;
     }
-    hasBeenSet = true;
-    value = fun(obj);
+    value = getter_function(obj);
+    getter_function = null;
     return value;
   };
   var setter = function(v) {
-    hasBeenSet = true;
+    getter_function = null;
     value = v;
   };
   %DefineOrRedefineAccessorProperty(obj, name, getter, setter, DONT_ENUM);
Index: test/cctest/test-heap.cc
diff --git a/test/cctest/test-heap.cc b/test/cctest/test-heap.cc
index ec2fb3dd6e0e4ef85a4ceb2e9d0b7b7ab251a389..cf435bfd296590ec33ddabc3b30d23d30ef190e9 100644
--- a/test/cctest/test-heap.cc
+++ b/test/cctest/test-heap.cc
@@ -2183,3 +2183,57 @@ TEST(IncrementalMarkingClearsPolymorhpicIC) {
   Code* ic_after = FindFirstIC(f->shared()->code(), Code::LOAD_IC);
   CHECK(ic_after->ic_state() == UNINITIALIZED);
 }
+
+
+class SourceResource: public v8::String::ExternalAsciiStringResource {
+ public:
+  explicit SourceResource(const char* data, int* counter)
+    : data_(data), length_(strlen(data)), counter_(counter) { }
+
+  virtual void Dispose() {
+    i::DeleteArray(data_);
+    if (counter_ != NULL) ++*counter_;
+  }
+
+  const char* data() const { return data_; }
+
+  size_t length() const { return length_; }
+
+ private:
+  const char* data_;
+  size_t length_;
+  int* counter_;
+};
+
+
+
+TEST(ReleaseStackTraceData) {
+  // Test that the data retained by the Error.stack accessor is released
+  // after the first time the accessor is fired.  We use external string
+  // to check whether the data is being released since the external string
+  // resource's callback is fired when the external string is GC'ed.
+  InitializeVM();
+  v8::HandleScope scope;
+  static const char* source = "var error = 1;       "
+                              "try {                "
+                              "  throw new Error(); "
+                              "} catch (e) {        "
+                              "  error = e;         "
+                              "}                    ";
+  int counter = 0;
+ SourceResource* resource = new SourceResource(i::StrDup(source), &counter);
+  {
+    v8::HandleScope scope;
+ v8::Handle<v8::String> source_string = v8::String::NewExternal(resource);
+    v8::Script::Compile(source_string)->Run();
+    CHECK(counter == 0);
+  }
+  HEAP->CollectAllAvailableGarbage();
+ CHECK(counter == 0); // External source is being retained by the stack trace.
+
+  CompileRun("error.stack;");
+  HEAP->CollectAllAvailableGarbage();
+  CHECK(counter == 1);  // External source has been released.
+
+  delete resource;
+}


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

Reply via email to