Last week was incredibly productive for exact rooting, even if the counts didn't go down that much. Once the reviews are done, we'll have two new tools to help deal with the two major problems we still have outstanding.
The first new tool is a way to interface to Rooted with non-static interfaces. For several months we have been moving to static methods when we need to exactly root |this|. This is similar to the wrapper we added for |Value| on |RootedBase<Value>|. Unfortunately, for most |Cell| implementations it is trickier since they want to inline |Rooted<T>| usage in the header. Naively, we would need to have the declaration of |RootedBase<Foo>| in front of |class Foo| (so Rooted<Foo> is available) and have the forwarders declared afterward. Obviously, splitting |RootedBase<Foo>| in half like this is a non-starter. Luke pointed out that if we pass Foo as a template parameter it gets resolved lazily -- as a spec matter even and not just as a compiler detail. This lets us have our cake and eat it too. I am going to open bugs this morning to kill off |self| rooting of |this| and moving everything over to use this technique. The second new tool is to deal with this awkward, and extremely common, compilation failure: |RawFoo foo = js::NewFoo(cx);|. Ideally, we'd like to do |.get(nogc);| to unpack the |Return<Foo>| returned by |js::NewFoo(cx);| This is impossible because the scope has to contain the |js::NewFoo(cx)| call, which will GC. Our other option is|js::NewFoo(cx).unsafeGet();|, which is both ugly and confusing. An even worse option is: |Return<Foo> foo = js::NewFoo(cx);|. Uhg. The solution has two parts: first, a lazily-initialized AutoAssertNoGC analogue called |Raw<T>|; secondly, rewriting |Return<T>| as a non-lazily-initialized AutoAssertNoGC guard. We can now do: |RawFoo foo = js::NewFoo(cx);| The static type checking guarantees that we do not try to store the result into an unchecked pointer: it's either Raw or Rooted unless you do extra work. The dynamic always-on-in-debug checking ensures that no GC occurs while the Raw is live. The always-on-TBPL rooting analysis catches misuse of naked pointers, if you have to use them. In this world, naked pointers get typedefed to UnsafeFoo, since the only remaining usage of a naked pointer is explicitly one that is not protected by always-on assertions. There are some additional nice side-effects from these tools. One, any use of |.| to access properties implies that the thing is declared in a safe way: e.g. use of |->| is a clue at the usage site that you need to tread carefully when editing. Two, any function or method that takes a RawFoo as an argument cannot GC: this allows us to get rid of most of the explicit AutoAssertNoGC's, keeping the code cleaner while increasing the assertion coverage. Lastly, any use of a naked pointer is now explicitly marked as Unsafe, which is a much more accurate hint than Raw. -Terrence _______________________________________________ dev-tech-js-engine-internals mailing list dev-tech-js-engine-internals@lists.mozilla.org https://lists.mozilla.org/listinfo/dev-tech-js-engine-internals