Skip to content

Commit

Permalink
[ruby/prism] Fix hash deopt based on contents
Browse files Browse the repository at this point in the history
The previous implementation of hash deopt was based on clearing the static literal flag on a hash node if the element that was being added was an array, hash or range node, or if the element was not a static literal in the first place.

However, this is not correct. First of all, the elements added to a hash node will primarily be assoc nodes, but never array, hash or range nodes. Secondly, the static literal flag is set on assoc nodes, only if the value in an assoc node is a static literal, so the key is never checked. As a result, the static literal flag on a hash node would never be cleared if the key wasn't a static literal.

This commit fixes this by clearing the static literal flag if:
1. the element is not an assoc node,
2. the element is an assoc node, but the key is not a static literal, or
3. the element is an assoc node, the key is a static literal, but assoc node (and thus the value in assoc node) is not a static literal.

ruby/prism@7f67109b36
  • Loading branch information
paracycle authored and matzbot committed Dec 13, 2023
1 parent 2350c79 commit e96f612
Showing 1 changed file with 9 additions and 3 deletions.
12 changes: 9 additions & 3 deletions prism/prism.c
Expand Up @@ -3348,9 +3348,15 @@ static inline void
pm_hash_node_elements_append(pm_hash_node_t *hash, pm_node_t *element) {
pm_node_list_append(&hash->elements, element);

// If the element is not a static literal, then the hash is not a static
// literal. Turn that flag off.
if (PM_NODE_TYPE_P(element, PM_ARRAY_NODE) || PM_NODE_TYPE_P(element, PM_HASH_NODE) || PM_NODE_TYPE_P(element, PM_RANGE_NODE) || !PM_NODE_FLAG_P(element, PM_NODE_FLAG_STATIC_LITERAL)) {
bool static_literal = PM_NODE_TYPE_P(element, PM_ASSOC_NODE);
if (static_literal) {
pm_assoc_node_t *assoc = (pm_assoc_node_t *) element;
static_literal = !PM_NODE_TYPE_P(assoc->key, PM_ARRAY_NODE) && !PM_NODE_TYPE_P(assoc->key, PM_HASH_NODE) && !PM_NODE_TYPE_P(assoc->key, PM_RANGE_NODE);
static_literal = static_literal && PM_NODE_FLAG_P(assoc->key, PM_NODE_FLAG_STATIC_LITERAL);
static_literal = static_literal && PM_NODE_FLAG_P(assoc, PM_NODE_FLAG_STATIC_LITERAL);
}

if (!static_literal) {
pm_node_flag_unset((pm_node_t *)hash, PM_NODE_FLAG_STATIC_LITERAL);
}
}
Expand Down

0 comments on commit e96f612

Please sign in to comment.