Avoid infinite loops in type-scanners more efficiently
commitebfdb7137e608888dc958d3fd32b78944a973588
authorRick Lavoie <rlavoie@fb.com>
Fri, 8 Jul 2016 05:44:37 +0000 (7 22:44 -0700)
committerHhvm Bot <hhvm-bot-bot@fb.com>
Sun, 10 Jul 2016 05:32:32 +0000 (9 22:32 -0700)
tree61d371111379c2a6a2d42ad4a38f10ba79c83182
parent5dca88b3c83650d4faa8a0925d9c137bc3a3f4c0
Avoid infinite loops in type-scanners more efficiently

Summary:
Normally the auto-generated type-scanners do not have to worry about entering
into cycles. This is because they, by default, never follow pointers, and thus
cannot enter into a cycle. However, there are certain constructs, which despite
containing pointers, we want to treat as flat values. Standard library
containers are one such example. Since it is possible to enter into a cycle with
these, a runtime check needs to be done to avoid looping infinitely.

The initial implementation of this check just used a set of visited pointers,
which was consulted before scanning a pointer. The problem with this is that
very large data structures can cause the visited set to grow very large, and
clearing the set after the scan can consume a large amount of time.

The visited set has the nice property that we'll never visit a node more than
once, but this is strictly unnecessary. The only real requirement is that we
don't loop infinitely. It is merely undesirable that work isn't duplicated. For
this reason, replace the visited set with a stack of pointers currently being
visited. Push a pointer onto the stack when scanning it, and pop it off when
done. If a pointer is already on the stack, do not scan it. Since chains of
scanned pointers tends to low, linearly searching the stack is sufficient.

Reviewed By: edwinsmith

Differential Revision: D3521753

fbshipit-source-id: e50abcd8b34a3a73c43c58f08055d3b63c685c13
hphp/util/type-scan.h