Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1495)

Unified Diff: test/cctest/test-api.cc

Issue 260017: Implemented really weak handles. (Closed)
Patch Set: Fix typo. Created 11 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« src/global-handles.cc ('K') | « src/global-handles.cc ('k') | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: test/cctest/test-api.cc
diff --git a/test/cctest/test-api.cc b/test/cctest/test-api.cc
index 2282c2d9b9563b7d8a2b1c63548d6cc0824c1e80..848f5135ca643cb1ef5b1343f6a95dd5a7290402 100644
--- a/test/cctest/test-api.cc
+++ b/test/cctest/test-api.cc
@@ -32,8 +32,8 @@
#include "api.h"
#include "compilation-cache.h"
#include "execution.h"
-#include "snapshot.h"
#include "platform.h"
+#include "snapshot.h"
#include "top.h"
#include "cctest.h"
@@ -2915,84 +2915,162 @@ THREADED_TEST(ErrorWithMissingScriptInfo) {
}
-int global_index = 0;
+static void WeakFactoryCallback(v8::Persistent<v8::Value> object, void* data);
-class Snorkel {
+class WeakFactory {
public:
- Snorkel() { index_ = global_index++; }
- int index_;
-};
+ enum Mode {
+ FACTORY_WEAK,
+ FACTORY_REALLY_WEAK
+ };
-class Whammy {
- public:
- Whammy() {
- cursor_ = 0;
+ explicit WeakFactory(Mode mode)
+ : mode_(mode),
+ objects_(8),
+ template_(v8::Persistent<v8::FunctionTemplate>::New(
+ v8::FunctionTemplate::New())),
+ instance_template_(v8::Persistent<v8::ObjectTemplate>::New(
+ template_->InstanceTemplate())) { }
+
+ ~WeakFactory() {
+ for (int i = 0; i < objects_.length(); ++i) {
+ objects_[i].Dispose();
+ }
}
- ~Whammy() {
- script_.Dispose();
+
+ v8::Persistent<v8::Object> CreateObject() {
+ v8::Persistent<v8::Object> object =
+ v8::Persistent<v8::Object>::New(instance_template_->NewInstance());
+ if (mode_ == FACTORY_WEAK) {
+ object.MakeWeak(this, &WeakFactoryCallback);
+ } else if (mode_ == FACTORY_REALLY_WEAK) {
+ object.MakeReallyWeak(this, &WeakFactoryCallback);
+ } else {
+ UNREACHABLE();
+ }
+ objects_.Add(object);
+ return object;
+ }
+
+ void Return(v8::Persistent<v8::Value> object) {
+ for (int i = 0; i < objects_.length(); ++i) {
+ if (objects_[i] == object) {
+ object.Dispose();
+ objects_.Remove(i);
+ return;
+ }
+ }
+ CHECK(false);
Christian Plesner Hansen 2009/10/06 13:47:21 UNREACHABLE()?
}
- v8::Handle<Script> getScript() {
- if (script_.IsEmpty())
- script_ = v8::Persistent<Script>::New(v8_compile("({}).blammo"));
- return Local<Script>(*script_);
+
+ int NumLive() const { return objects_.length(); }
+
+ int NumInHeap() const {
+ int counter = 0;
+ i::HeapIterator iter;
+ while (iter.has_next()) {
+ i::HeapObject* object = iter.next();
+ if (object->IsInstanceOf(*v8::Utils::OpenHandle(*template_))) {
+ ++counter;
+ }
+ }
+ return counter;
}
- public:
- static const int kObjectCount = 256;
- int cursor_;
- v8::Persistent<v8::Object> objects_[kObjectCount];
- v8::Persistent<Script> script_;
+ private:
+ const Mode mode_;
Christian Plesner Hansen 2009/10/06 13:47:21 Why const?
+ i::List<v8::Persistent<v8::Value> > objects_;
+ v8::Persistent<v8::FunctionTemplate> template_;
+ v8::Persistent<v8::ObjectTemplate> instance_template_;
};
-static void HandleWeakReference(v8::Persistent<v8::Value> obj, void* data) {
- Snorkel* snorkel = reinterpret_cast<Snorkel*>(data);
- delete snorkel;
- obj.ClearWeak();
+static void WeakFactoryCallback(v8::Persistent<v8::Value> object, void* data) {
+ WeakFactory* factory = reinterpret_cast<WeakFactory*>(data);
+ factory->Return(object);
}
-v8::Handle<Value> WhammyPropertyGetter(Local<String> name,
- const AccessorInfo& info) {
- Whammy* whammy =
- static_cast<Whammy*>(v8::Handle<v8::External>::Cast(info.Data())->Value());
+static v8::Handle<v8::Value> WeakFactoryCreateObject(
+ const v8::Arguments& args) {
+ WeakFactory* factory =
+ reinterpret_cast<WeakFactory*>(v8::External::Unwrap(args.Data()));
+ return factory->CreateObject();
+}
+
+static const char* const kTestWeakCode =
+ "var last = null;"
+ "(function() {"
+ " for (var i = 0; i < 10000; i++) {"
+ " var obj = createObject();"
+ " obj.next = last;"
+ " last = obj;"
+ " }"
+ "})();";
- v8::Persistent<v8::Object> prev = whammy->objects_[whammy->cursor_];
+THREADED_TEST(WeakReference) {
+ v8::HandleScope handle_scope;
+ WeakFactory* factory = new WeakFactory(WeakFactory::FACTORY_WEAK);
- v8::Handle<v8::Object> obj = v8::Object::New();
- v8::Persistent<v8::Object> global = v8::Persistent<v8::Object>::New(obj);
- if (!prev.IsEmpty()) {
- prev->Set(v8_str("next"), obj);
- prev.MakeWeak(new Snorkel(), &HandleWeakReference);
- whammy->objects_[whammy->cursor_].Clear();
- }
- whammy->objects_[whammy->cursor_] = global;
- whammy->cursor_ = (whammy->cursor_ + 1) % Whammy::kObjectCount;
- return whammy->getScript()->Run();
+ const char* extension_list[] = { "v8/gc" };
+ v8::ExtensionConfiguration extensions(1, extension_list);
+ v8::Persistent<Context> context = Context::New(&extensions);
+ Context::Scope context_scope(context);
+
+ v8::Handle<v8::FunctionTemplate> function_templ = v8::FunctionTemplate::New(
+ &WeakFactoryCreateObject, v8::External::Wrap(factory));
+ context->Global()->Set(v8_str("createObject"), function_templ->GetFunction());
+
+ // Create objects held by a variable.
+ CompileRun(kTestWeakCode);
+ CHECK_EQ(10000, factory->NumLive());
+ CHECK_EQ(10000, factory->NumInHeap());
+
+ // Make sure GC doesn't collect them.
+ CompileRun("gc(); gc();");
+ CHECK_EQ(10000, factory->NumLive());
+ CHECK_EQ(10000, factory->NumInHeap());
+
+ // Make sure GC realizes they are no longer reachable and invokes
+ // weak callbacks after the variable is reset.
+ CompileRun("last = null; gc();");
+ CHECK_EQ(0, factory->NumLive());
+ CHECK_EQ(10000, factory->NumInHeap());
+
+ // Next GC after callbacks should collect the objects.
+ CompileRun("gc();");
+ CHECK_EQ(0, factory->NumLive());
+ CHECK_EQ(0, factory->NumInHeap());
+
+ context.Dispose();
}
-THREADED_TEST(WeakReference) {
+THREADED_TEST(ReallyWeakReference) {
v8::HandleScope handle_scope;
- v8::Handle<v8::ObjectTemplate> templ= v8::ObjectTemplate::New();
- templ->SetNamedPropertyHandler(WhammyPropertyGetter,
- 0, 0, 0, 0,
- v8::External::New(new Whammy()));
+ WeakFactory* factory = new WeakFactory(WeakFactory::FACTORY_REALLY_WEAK);
+
const char* extension_list[] = { "v8/gc" };
v8::ExtensionConfiguration extensions(1, extension_list);
v8::Persistent<Context> context = Context::New(&extensions);
Context::Scope context_scope(context);
- v8::Handle<v8::Object> interceptor = templ->NewInstance();
- context->Global()->Set(v8_str("whammy"), interceptor);
- const char* code =
- "var last;"
- "for (var i = 0; i < 10000; i++) {"
- " var obj = whammy.length;"
- " if (last) last.next = obj;"
- " last = obj;"
- "}"
- "gc();"
- "4";
- v8::Handle<Value> result = CompileRun(code);
- CHECK_EQ(4.0, result->NumberValue());
+ v8::Handle<v8::FunctionTemplate> function_templ = v8::FunctionTemplate::New(
+ &WeakFactoryCreateObject, v8::External::Wrap(factory));
+ context->Global()->Set(v8_str("createObject"), function_templ->GetFunction());
+
+ // See the comments above in WeakReference test.
+
+ CompileRun(kTestWeakCode);
+ CHECK_EQ(10000, factory->NumLive());
+ CHECK_EQ(10000, factory->NumInHeap());
+
+ CompileRun("gc(); gc();");
+ CHECK_EQ(10000, factory->NumLive());
+ CHECK_EQ(10000, factory->NumInHeap());
+
+ // Unlike above objects should be immediately collected when they
+ // are unreachable.
+ CompileRun("last = null; gc();");
+ CHECK_EQ(0, factory->NumLive());
+ CHECK_EQ(0, factory->NumInHeap());
context.Dispose();
}
« src/global-handles.cc ('K') | « src/global-handles.cc ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698