Skip to content

Commit fdc7eb7

Browse files
committed
Comments
1 parent 416fa87 commit fdc7eb7

File tree

2 files changed

+32
-1
lines changed

2 files changed

+32
-1
lines changed

ext/dom/nodelist.c

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@
3434
static zend_always_inline void objmap_cache_release_cached_obj(dom_nnodemap_object *objmap)
3535
{
3636
if (objmap->cached_obj) {
37+
/* Since the DOM is a tree there can be no cycles. */
3738
if (GC_DELREF(&objmap->cached_obj->std) == 0) {
3839
zend_objects_store_del(&objmap->cached_obj->std);
3940
}
@@ -227,7 +228,11 @@ PHP_METHOD(DOMNodeList, item)
227228
DOM_RET_OBJ(itemnode, &ret, objmap->baseobj);
228229
if (cache_itemnode) {
229230
/* Hold additional reference for the cache, must happen before releasing the cache
230-
* because we might be the last reference holder. */
231+
* because we might be the last reference holder.
232+
* Instead of storing and copying zvals, we store the object pointer directly.
233+
* This saves us some bytes because a pointer is smaller than a zval.
234+
* This also means we have to manually refcount the objects here, and remove the reference count
235+
* in reset_objmap_cache() and the destructor. */
231236
dom_object *cached_obj = Z_DOMOBJ_P(return_value);
232237
GC_ADDREF(&cached_obj->std);
233238
/* If the tag is stale, all cached data is useless. Otherwise only the cached object is useless. */

ext/dom/tests/DOMDocument_getElementsByTagName_liveness.phpt

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,32 @@ $root = $doc->documentElement;
1010

1111
$i = 0;
1212

13+
/* Note that the list is live. The explanation for the output is as follows:
14+
Before the loop we have the following (writing only the attributes):
15+
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
16+
17+
Now the loop starts, the current element is marked with a V. $i == 0:
18+
V
19+
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
20+
1 gets printed. $i == 0, which is even, so 1 gets removed, which results in:
21+
V
22+
2 3 4 5 6 7 8 9 10 11 12 13 14 15
23+
Note that everything shifted to the left.
24+
Because the list is live, the current element pointer still refers to the first index, which now corresponds to element with attribute 2.
25+
Now the foreach body ends, which means we go to the next element, which is now 3 instead of 2.
26+
V
27+
2 3 4 5 6 7 8 9 10 11 12 13 14 15
28+
3 gets printed. $i == 1, which is odd, so nothing happens and we move on to the next element:
29+
V
30+
2 3 4 5 6 7 8 9 10 11 12 13 14 15
31+
4 gets printed. $i == 2, which is even, so 4 gets removed, which results in:
32+
V
33+
2 3 5 6 7 8 9 10 11 12 13 14 15
34+
Note again everything shifted to the left.
35+
Now the foreach body ends, which means we go to the next element, which is now 6 instead of 5.
36+
V
37+
2 3 5 6 7 8 9 10 11 12 13 14 15
38+
6 gets printed, etc... */
1339
foreach ($doc->getElementsByTagName('e') as $node) {
1440
print $node->getAttribute('i') . ' ';
1541
if ($i++ % 2 == 0)

0 commit comments

Comments
 (0)