Skip to content

Commit 391b674

Browse files
committed
Provide Ractor support for **
Fixes [Bug #20916]
1 parent 97f5546 commit 391b674

File tree

2 files changed

+32
-26
lines changed

2 files changed

+32
-26
lines changed

prism_compile.c

Lines changed: 32 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1357,13 +1357,15 @@ pm_compile_call_and_or_write_node(rb_iseq_t *iseq, bool and_node, const pm_node_
13571357
if (lskip && !popped) PUSH_LABEL(ret, lskip);
13581358
}
13591359

1360+
static void pm_compile_shareable_constant_value(rb_iseq_t *iseq, const pm_node_t *node, const pm_node_flags_t shareability, VALUE path, LINK_ANCHOR *const ret, pm_scope_node_t *scope_node, bool top);
1361+
13601362
/**
13611363
* This function compiles a hash onto the stack. It is used to compile hash
13621364
* literals and keyword arguments. It is assumed that if we get here that the
13631365
* contents of the hash are not popped.
13641366
*/
13651367
static void
1366-
pm_compile_hash_elements(rb_iseq_t *iseq, const pm_node_t *node, const pm_node_list_t *elements, bool argument, LINK_ANCHOR *const ret, pm_scope_node_t *scope_node)
1368+
pm_compile_hash_elements(rb_iseq_t *iseq, const pm_node_t *node, const pm_node_list_t *elements, const pm_node_flags_t shareability, VALUE path, bool argument, LINK_ANCHOR *const ret, pm_scope_node_t *scope_node)
13671369
{
13681370
const pm_node_location_t location = PM_NODE_START_LOCATION(scope_node->parser, node);
13691371

@@ -1406,11 +1408,11 @@ pm_compile_hash_elements(rb_iseq_t *iseq, const pm_node_t *node, const pm_node_l
14061408
for (size_t index = 0; index < elements->size; index++) {
14071409
const pm_node_t *element = elements->nodes[index];
14081410

1409-
14101411
switch (PM_NODE_TYPE(element)) {
14111412
case PM_ASSOC_NODE: {
14121413
// Pre-allocation check (this branch can be omitted).
14131414
if (
1415+
(shareability == 0) &&
14141416
PM_NODE_FLAG_P(element, PM_NODE_FLAG_STATIC_LITERAL) && (
14151417
(!static_literal && ((index + min_tmp_hash_length) < elements->size)) ||
14161418
(first_chunk && stack_length == 0)
@@ -1468,7 +1470,15 @@ pm_compile_hash_elements(rb_iseq_t *iseq, const pm_node_t *node, const pm_node_l
14681470

14691471
// If this is a plain assoc node, then we can compile it directly
14701472
// and then add the total number of values on the stack.
1471-
pm_compile_node(iseq, element, anchor, false, scope_node);
1473+
if (shareability == 0) {
1474+
pm_compile_node(iseq, element, anchor, false, scope_node);
1475+
}
1476+
else {
1477+
const pm_assoc_node_t *assoc = (const pm_assoc_node_t *) element;
1478+
pm_compile_shareable_constant_value(iseq, assoc->key, shareability, path, ret, scope_node, false);
1479+
pm_compile_shareable_constant_value(iseq, assoc->value, shareability, path, ret, scope_node, false);
1480+
}
1481+
14721482
if ((stack_length += 2) >= max_stack_length) FLUSH_CHUNK;
14731483
break;
14741484
}
@@ -1511,7 +1521,12 @@ pm_compile_hash_elements(rb_iseq_t *iseq, const pm_node_t *node, const pm_node_l
15111521
// only done for method calls and not for literal hashes,
15121522
// because literal hashes should always result in a new
15131523
// hash.
1514-
PM_COMPILE_NOT_POPPED(element);
1524+
if (shareability == 0) {
1525+
PM_COMPILE_NOT_POPPED(element);
1526+
}
1527+
else {
1528+
pm_compile_shareable_constant_value(iseq, element, shareability, path, ret, scope_node, false);
1529+
}
15151530
}
15161531
else {
15171532
// There is more than one keyword argument, or this is not a
@@ -1527,7 +1542,13 @@ pm_compile_hash_elements(rb_iseq_t *iseq, const pm_node_t *node, const pm_node_l
15271542
PUSH_INSN(ret, location, swap);
15281543
}
15291544

1530-
PM_COMPILE_NOT_POPPED(element);
1545+
if (shareability == 0) {
1546+
PM_COMPILE_NOT_POPPED(element);
1547+
}
1548+
else {
1549+
pm_compile_shareable_constant_value(iseq, element, shareability, path, ret, scope_node, false);
1550+
}
1551+
15311552
PUSH_SEND(ret, location, id_core_hash_merge_kwd, INT2FIX(2));
15321553
}
15331554
}
@@ -1590,17 +1611,17 @@ pm_setup_args_core(const pm_arguments_node_t *arguments_node, const pm_node_t *b
15901611
// in this case, so mark the method as passing mutable
15911612
// keyword splat.
15921613
*flags |= VM_CALL_KW_SPLAT_MUT;
1593-
pm_compile_hash_elements(iseq, argument, elements, true, ret, scope_node);
1614+
pm_compile_hash_elements(iseq, argument, elements, 0, Qundef, true, ret, scope_node);
15941615
}
15951616
else if (*dup_rest & DUP_SINGLE_KW_SPLAT) {
15961617
*flags |= VM_CALL_KW_SPLAT_MUT;
15971618
PUSH_INSN1(ret, location, putspecialobject, INT2FIX(VM_SPECIAL_OBJECT_VMCORE));
15981619
PUSH_INSN1(ret, location, newhash, INT2FIX(0));
1599-
pm_compile_hash_elements(iseq, argument, elements, true, ret, scope_node);
1620+
pm_compile_hash_elements(iseq, argument, elements, 0, Qundef, true, ret, scope_node);
16001621
PUSH_SEND(ret, location, id_core_hash_merge_kwd, INT2FIX(2));
16011622
}
16021623
else {
1603-
pm_compile_hash_elements(iseq, argument, elements, true, ret, scope_node);
1624+
pm_compile_hash_elements(iseq, argument, elements, 0, Qundef, true, ret, scope_node);
16041625
}
16051626
}
16061627
else {
@@ -5289,19 +5310,7 @@ pm_compile_shareable_constant_value(rb_iseq_t *iseq, const pm_node_t *node, cons
52895310
PUSH_INSN1(ret, location, putspecialobject, INT2FIX(VM_SPECIAL_OBJECT_VMCORE));
52905311
}
52915312

5292-
for (size_t index = 0; index < cast->elements.size; index++) {
5293-
const pm_node_t *element = cast->elements.nodes[index];
5294-
5295-
if (!PM_NODE_TYPE_P(element, PM_ASSOC_NODE)) {
5296-
COMPILE_ERROR(iseq, location.line, "Ractor constant writes do not support **");
5297-
}
5298-
5299-
const pm_assoc_node_t *assoc = (const pm_assoc_node_t *) element;
5300-
pm_compile_shareable_constant_value(iseq, assoc->key, shareability, path, ret, scope_node, false);
5301-
pm_compile_shareable_constant_value(iseq, assoc->value, shareability, path, ret, scope_node, false);
5302-
}
5303-
5304-
PUSH_INSN1(ret, location, newhash, INT2FIX(cast->elements.size * 2));
5313+
pm_compile_hash_elements(iseq, (const pm_node_t *) cast, &cast->elements, shareability, path, false, ret, scope_node);
53055314

53065315
if (top) {
53075316
ID method_id = (shareability & PM_SHAREABLE_CONSTANT_NODE_FLAGS_EXPERIMENTAL_COPY) ? rb_intern("make_shareable_copy") : rb_intern("make_shareable");
@@ -6752,7 +6761,7 @@ pm_compile_array_node(rb_iseq_t *iseq, const pm_node_t *node, const pm_node_list
67526761
// ^^^^^
67536762
//
67546763
const pm_keyword_hash_node_t *keyword_hash = (const pm_keyword_hash_node_t *) element;
6755-
pm_compile_hash_elements(iseq, element, &keyword_hash->elements, false, ret, scope_node);
6764+
pm_compile_hash_elements(iseq, element, &keyword_hash->elements, 0, Qundef, false, ret, scope_node);
67566765

67576766
// This boolean controls the manner in which we push the
67586767
// hash onto the array. If it's all keyword splats, then we
@@ -8940,7 +8949,7 @@ pm_compile_node(rb_iseq_t *iseq, const pm_node_t *node, LINK_ANCHOR *const ret,
89408949
}
89418950
}
89428951
else {
8943-
pm_compile_hash_elements(iseq, node, elements, false, ret, scope_node);
8952+
pm_compile_hash_elements(iseq, node, elements, 0, Qundef, false, ret, scope_node);
89448953
}
89458954
}
89468955

test/ruby/test_parse.rb

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1611,9 +1611,6 @@ class X
16111611
end
16121612

16131613
def test_shareable_constant_value_hash_with_keyword_splat
1614-
# Prism compiler does not support keyword splat in Ractor constant [Bug #20916]
1615-
omit if ParserSupport.prism_enabled?
1616-
16171614
a, b = eval_separately("#{<<~"begin;"}\n#{<<~'end;'}")
16181615
begin;
16191616
# shareable_constant_value: experimental_everything

0 commit comments

Comments
 (0)