Revision: 12403
Author:   [email protected]
Date:     Wed Aug 29 00:51:48 2012
Log:      Release stack trace data after firing Error.stack accessor.

BUG=v8:2308

Review URL: https://chromiumcodereview.appspot.com/10886012
http://code.google.com/p/v8/source/detail?r=12403

Modified:
 /branches/bleeding_edge/src/messages.js
 /branches/bleeding_edge/test/cctest/test-heap.cc

=======================================
--- /branches/bleeding_edge/src/messages.js     Wed Jul 11 04:35:19 2012
+++ /branches/bleeding_edge/src/messages.js     Wed Aug 29 00:51:48 2012
@@ -762,22 +762,21 @@

 // Defines accessors for a property that is calculated the first time
 // the property is read.
-function DefineOneShotAccessor(obj, name, fun) {
+function DefineOneShotAccessor(obj, name, value_factory) {
   // 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() {
-    if (hasBeenSet) {
+    if (value_factory == null) {
       return value;
     }
-    hasBeenSet = true;
-    value = fun(obj);
+    value = value_factory(obj);
+    value_factory = null;
     return value;
   };
   var setter = function(v) {
-    hasBeenSet = true;
+    value_factory = null;
     value = v;
   };
   %DefineOrRedefineAccessorProperty(obj, name, getter, setter, DONT_ENUM);
=======================================
--- /branches/bleeding_edge/test/cctest/test-heap.cc Mon Aug 27 09:08:27 2012 +++ /branches/bleeding_edge/test/cctest/test-heap.cc Wed Aug 29 00:51:48 2012
@@ -2183,3 +2183,58 @@
   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)
+    : data_(data), length_(strlen(data)) { }
+
+  virtual void Dispose() {
+    i::DeleteArray(data_);
+    data_ = NULL;
+  }
+
+  const char* data() const { return data_; }
+
+  size_t length() const { return length_; }
+
+  bool IsDisposed() { return data_ == NULL; }
+
+ private:
+  const char* data_;
+  size_t length_;
+};
+
+
+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;         "
+                              "}                    ";
+  SourceResource* resource = new SourceResource(i::StrDup(source));
+  {
+    v8::HandleScope scope;
+ v8::Handle<v8::String> source_string = v8::String::NewExternal(resource);
+    v8::Script::Compile(source_string)->Run();
+    CHECK(!resource->IsDisposed());
+  }
+  HEAP->CollectAllAvailableGarbage();
+  // External source is being retained by the stack trace.
+  CHECK(!resource->IsDisposed());
+
+  CompileRun("error.stack; error.stack;");
+  HEAP->CollectAllAvailableGarbage();
+  // External source has been released.
+  CHECK(resource->IsDisposed());
+
+  delete resource;
+}

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

Reply via email to