Bug 814562 - Implement clear() on WeakMaps
authorSaurabh Anand <saurabhanandiit@gmail.com>
Sun, 09 Dec 2012 04:27:58 +0530
changeset 115397 b5fa6a857c3529d1f4658c0e24551a74c7d7896e
parent 115396 2f18ed6d271708d120b3806fe95c6a53a83ae13c
child 115398 812eb3fb9abee2ac5e1e42c64182e11a24d9e885
push id19333
push usersaurabhanandiit@gmail.com
push dateSat, 08 Dec 2012 22:58:21 +0000
treeherdermozilla-inbound@b5fa6a857c35 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
bugs814562
milestone20.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 814562 - Implement clear() on WeakMaps
js/src/jit-test/tests/collections/WeakMap-clear.js
js/src/jsweakmap.cpp
new file mode 100644
--- /dev/null
+++ b/js/src/jit-test/tests/collections/WeakMap-clear.js
@@ -0,0 +1,42 @@
+var key = {};
+var wm = WeakMap();
+
+assertEq(wm.has(key), false);
+// Clearing an already empty WeakMap
+wm.clear();
+assertEq(wm.has(key), false);
+
+// Clearing a WeakMap with a live key
+wm.set(key, 42);
+assertEq(wm.has(key), true);
+wm.clear();
+assertEq(wm.has(key), false);
+
+// Clearing a WeakMap with keys turned to garbage
+wm.set(key, {});
+for (var i = 0; i < 10; i++)
+    wm.set({}, {});
+assertEq(wm.has(key), true);
+wm.clear();
+assertEq(wm.has(key), false);
+
+// Clearing a WeakMap with keys turned to garbage and after doing a GC
+wm.set(key, {});
+for (var i = 0; i < 10; i++)
+    wm.set({}, {});
+assertEq(wm.has(key), true);
+gc();
+assertEq(wm.has(key), true);
+wm.clear();
+assertEq(wm.has(key), false);
+
+// More testing when the key is no longer live
+wm.set(key, {});
+key = null;
+wm.clear();
+gc();
+var key2 = {};
+wm.set(key2, {});
+key2 = null;
+gc();
+wm.clear();
--- a/js/src/jsweakmap.cpp
+++ b/js/src/jsweakmap.cpp
@@ -167,16 +167,38 @@ WeakMap_has_impl(JSContext *cx, CallArgs
 JSBool
 WeakMap_has(JSContext *cx, unsigned argc, Value *vp)
 {
     CallArgs args = CallArgsFromVp(argc, vp);
     return CallNonGenericMethod<IsWeakMap, WeakMap_has_impl>(cx, args);
 }
 
 JS_ALWAYS_INLINE bool
+WeakMap_clear_impl(JSContext *cx, CallArgs args)
+{
+    JS_ASSERT(IsWeakMap(args.thisv()));
+
+    // We can't js_delete the weakmap because the data gathered during GC
+    // is used by the Cycle Collector
+    if (ObjectValueMap *map = GetObjectMap(&args.thisv().toObject())) {
+        map->clear();
+    }
+
+    args.rval().setUndefined();
+    return true;
+}
+
+JSBool
+WeakMap_clear(JSContext *cx, unsigned argc, Value *vp)
+{
+    CallArgs args = CallArgsFromVp(argc, vp);
+    return CallNonGenericMethod<IsWeakMap, WeakMap_clear_impl>(cx, args);
+}
+
+JS_ALWAYS_INLINE bool
 WeakMap_get_impl(JSContext *cx, CallArgs args)
 {
     JS_ASSERT(IsWeakMap(args.thisv()));
 
     if (args.length() < 1) {
         JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_MORE_ARGS_NEEDED,
                              "WeakMap.get", "0", "s");
         return false;
@@ -369,16 +391,17 @@ Class js::WeakMapClass = {
     WeakMap_mark
 };
 
 static JSFunctionSpec weak_map_methods[] = {
     JS_FN("has",    WeakMap_has, 1, 0),
     JS_FN("get",    WeakMap_get, 2, 0),
     JS_FN("delete", WeakMap_delete, 1, 0),
     JS_FN("set",    WeakMap_set, 2, 0),
+    JS_FN("clear",  WeakMap_clear, 0, 0),
     JS_FS_END
 };
 
 JSObject *
 js_InitWeakMapClass(JSContext *cx, HandleObject obj)
 {
     JS_ASSERT(obj->isNative());