author | Jon Coppeard <jcoppeard@mozilla.com> |
Mon, 20 Feb 2017 13:00:15 +0000 | |
changeset 343894 | cd05e24fefffc0e409a30a8a720cb7e05f7a0019 |
parent 343893 | 58594006a6fa3fadf523b3c0faa28a964c788103 |
child 343895 | 55cdebd1726441794acdd5d5f3d40d4d04c6cbaa |
push id | 31391 |
push user | philringnalda@gmail.com |
push date | Tue, 21 Feb 2017 04:29:09 +0000 |
treeherder | mozilla-central@d84beb192e57 [default view] [failures only] |
perfherder | [talos] [build metrics] [platform microbench] (compared to previous push) |
reviewers | sfink |
bugs | 1340604 |
milestone | 54.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
|
js/src/jsapi-tests/testGCGrayMarking.cpp | file | annotate | diff | comparison | revisions | |
js/src/jsweakmap.h | file | annotate | diff | comparison | revisions |
--- a/js/src/jsapi-tests/testGCGrayMarking.cpp +++ b/js/src/jsapi-tests/testGCGrayMarking.cpp @@ -1,39 +1,67 @@ /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- * vim: set ts=8 sts=4 et sw=4 tw=99: */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +#include "jsweakmap.h" + #include "gc/Heap.h" #include "gc/Zone.h" #include "jsapi-tests/tests.h" using namespace js; using namespace js::gc; +namespace JS { + +template <> +struct DeletePolicy<js::ObjectWeakMap> : public js::GCManagedDeletePolicy<js::ObjectWeakMap> +{}; + +template <> +struct MapTypeToRootKind<js::ObjectWeakMap*> { + static const JS::RootKind kind = JS::RootKind::Traceable; +}; + +template <> +struct GCPolicy<js::ObjectWeakMap*> { + static void trace(JSTracer* trc, js::ObjectWeakMap** tp, const char* name) { + (*tp)->trace(trc); + } +}; + +} // namespace JS + + class AutoNoAnalysisForTest { public: AutoNoAnalysisForTest() {} } JS_HAZ_GC_SUPPRESSED; BEGIN_TEST(testGCGrayMarking) { AutoNoAnalysisForTest disableAnalysis; CHECK(InitGlobals()); JSAutoCompartment ac(cx, global1); InitGrayRootTracer(); - bool ok = TestMarking() && TestWeakMaps() && TestWatchpoints() && TestCCWs(); + bool ok = + TestMarking() && + TestWeakMaps() && + TestUnassociatedWeakMaps() && + TestWatchpoints() && + TestCCWs(); global1 = nullptr; global2 = nullptr; RemoveGrayRootTracer(); return ok; } @@ -285,16 +313,117 @@ TestWeakMaps() blackRoot2 = nullptr; grayRoots.grayRoot1 = nullptr; grayRoots.grayRoot2 = nullptr; return true; } bool +TestUnassociatedWeakMaps() +{ + // Make a weakmap that's not associated with a JSObject. + auto weakMap = cx->make_unique<ObjectWeakMap>(cx); + CHECK(weakMap); + CHECK(weakMap->init()); + + // Make sure this gets traced during GC. + Rooted<ObjectWeakMap*> rootMap(cx, weakMap.get()); + + JSObject* key = AllocWeakmapKeyObject(); + CHECK(key); + + JSObject* value = AllocPlainObject(); + CHECK(value); + + CHECK(weakMap->add(cx, key, value)); + + // Test the value of a weakmap entry is marked gray by GC if the + // key is marked gray. + + grayRoots.grayRoot1 = key; + JS_GC(cx); + CHECK(IsMarkedGray(key)); + CHECK(IsMarkedGray(value)); + + // Test the value of a weakmap entry is marked gray by GC if the key is marked gray. + + grayRoots.grayRoot1 = key; + grayRoots.grayRoot2 = nullptr; + JS_GC(cx); + CHECK(IsMarkedGray(key)); + CHECK(IsMarkedGray(value)); + + // Test the value of a weakmap entry is marked black by GC if the key is + // marked black. + + JS::RootedObject blackRoot(cx); + blackRoot = key; + grayRoots.grayRoot1 = nullptr; + grayRoots.grayRoot2 = nullptr; + JS_GC(cx); + CHECK(IsMarkedBlack(key)); + CHECK(IsMarkedBlack(value)); + + // Test that a weakmap key is marked gray if it has a gray delegate. + + JSObject* delegate = AllocDelegateForKey(key); + blackRoot = nullptr; + grayRoots.grayRoot1 = delegate; + grayRoots.grayRoot2 = nullptr; + JS_GC(cx); + CHECK(IsMarkedGray(delegate)); + CHECK(IsMarkedGray(key)); + CHECK(IsMarkedGray(value)); + + // Test that a weakmap key is marked black if it has a black delegate. + + blackRoot = delegate; + grayRoots.grayRoot1 = nullptr; + grayRoots.grayRoot2 = nullptr; + JS_GC(cx); + CHECK(IsMarkedBlack(delegate)); + CHECK(IsMarkedBlack(key)); + CHECK(IsMarkedBlack(value)); + + blackRoot = delegate; + grayRoots.grayRoot1 = key; + grayRoots.grayRoot2 = nullptr; + JS_GC(cx); + CHECK(IsMarkedBlack(delegate)); + CHECK(IsMarkedBlack(key)); + CHECK(IsMarkedBlack(value)); + + // Test what happens if there is a delegate but it is not marked for both + // black and gray cases. + + delegate = nullptr; + blackRoot = key; + grayRoots.grayRoot1 = nullptr; + grayRoots.grayRoot2 = nullptr; + JS_GC(cx); + CHECK(IsMarkedBlack(key)); + CHECK(IsMarkedBlack(value)); + + CHECK(AllocDelegateForKey(key)); + blackRoot = nullptr; + grayRoots.grayRoot1 = key; + grayRoots.grayRoot2 = nullptr; + JS_GC(cx); + CHECK(IsMarkedGray(key)); + CHECK(IsMarkedGray(value)); + + blackRoot = nullptr; + grayRoots.grayRoot1 = nullptr; + grayRoots.grayRoot2 = nullptr; + + return true; +} + +bool TestWatchpoints() { JSObject* watched = AllocPlainObject(); CHECK(watched); JSObject* closure = AllocPlainObject(); CHECK(closure);
--- a/js/src/jsweakmap.h +++ b/js/src/jsweakmap.h @@ -397,16 +397,18 @@ class ObjectValueMap : public WeakMap<He class ObjectWeakMap { ObjectValueMap map; public: explicit ObjectWeakMap(JSContext* cx); bool init(); + JS::Zone* zone() const { return map.zone(); } + JSObject* lookup(const JSObject* obj); bool add(JSContext* cx, JSObject* obj, JSObject* target); void clear(); void trace(JSTracer* trc); size_t sizeOfExcludingThis(mozilla::MallocSizeOf mallocSizeOf); size_t sizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf) { return mallocSizeOf(this) + sizeOfExcludingThis(mallocSizeOf);