Release stack trace data after firing Error.stack accessor.

BUG=v8:2308

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

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@12403 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
This commit is contained in:
yangguo@chromium.org 2012-08-29 07:51:48 +00:00
parent de3c3c0198
commit 5419ee7ba0
2 changed files with 60 additions and 6 deletions

View File

@ -762,22 +762,21 @@ function GetStackTraceLine(recv, fun, pos, isGlobal) {
// 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);

View File

@ -2183,3 +2183,58 @@ 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)
: 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;
}