[前][次][番号順一覧][スレッド一覧]

ruby-changes:64147

From: Nobuyoshi <ko1@a...>
Date: Mon, 14 Dec 2020 19:29:52 +0900 (JST)
Subject: [ruby-changes:64147] 3323174727 (master): Support shareable_constant_value: literal

https://git.ruby-lang.org/ruby.git/commit/?id=3323174727

From 332317472779554f991ffa5bad74c1255828cc21 Mon Sep 17 00:00:00 2001
From: Nobuyoshi Nakada <nobu@r...>
Date: Thu, 26 Nov 2020 18:10:42 +0900
Subject: Support shareable_constant_value: literal


diff --git a/parse.y b/parse.y
index 0e1ed59..664df9f 100644
--- a/parse.y
+++ b/parse.y
@@ -10985,31 +10985,149 @@ mark_lvar_used(struct parser_params *p, NODE *rhs) https://github.com/ruby/ruby/blob/trunk/parse.y#L10985
 extern VALUE rb_mRubyVMFrozenCore;
 
 static NODE *
-shareable_literal_constant(struct parser_params *p, NODE *value)
+shareable_literal_node(struct parser_params *p, NODE *value, const YYLTYPE *loc)
 {
+    NODE *fcore = NEW_LIT(rb_mRubyVMFrozenCore, loc);
+    return NEW_CALL(fcore, rb_intern("make_shareable"),
+		    NEW_LIST(value, loc), loc);
+}
+
+static int is_static_content(NODE *node);
+
+static VALUE
+shareable_literal_value(NODE *node)
+{
+    if (!node) return Qnil;
+    enum node_type type = nd_type(node);
+    switch (type) {
+      case NODE_TRUE:
+	return Qtrue;
+      case NODE_FALSE:
+	return Qfalse;
+      case NODE_NIL:
+	return Qnil;
+      case NODE_LIT:
+	return node->nd_lit;
+      default:
+	return Qundef;
+    }
+}
+
+VALUE rb_ractor_make_shareable(VALUE obj);
+
+static NODE *
+shareable_literal_constant(struct parser_params *p, NODE *value, enum shareability shareable, const YYLTYPE *loc)
+{
+    VALUE lit;
+
+    if (!value) return 0;
+    enum node_type type = nd_type(value);
+    switch (type) {
+      case NODE_TRUE:
+      case NODE_FALSE:
+      case NODE_NIL:
+      case NODE_LIT:
+      case NODE_DSTR:
+	break;
+
+      case NODE_STR:
+	lit = rb_fstring(value->nd_lit);
+	nd_set_type(value, NODE_LIT);
+	RB_OBJ_WRITE(p->ast, &value->nd_lit, lit);
+	break;
+
+      case NODE_ZLIST:
+	nd_set_type(value, NODE_LIT);
+	RB_OBJ_WRITE(p->ast, &value->nd_lit, rb_ary_new());
+	break;
+
+      case NODE_LIST:
+	lit = rb_ary_new();
+	for (NODE *n = value; n; n = n->nd_next) {
+	    NODE *elt = n->nd_head;
+	    if (elt && !(elt = shareable_literal_constant(p, elt, shareable, &elt->nd_loc))) {
+		if (lit) {
+		    rb_ary_clear(lit);
+		    lit = Qfalse;
+		}
+		continue;
+	    }
+	    if (lit) {
+		VALUE e = shareable_literal_value(elt);
+		if (e != Qundef) {
+		    rb_ary_push(lit, e);
+		}
+		else {
+		    rb_ary_clear(lit);
+		    lit = Qfalse;
+		}
+	    }
+	}
+	if (!lit) return 0;
+	nd_set_type(value, NODE_LIT);
+	RB_OBJ_WRITE(p->ast, &value->nd_lit, rb_ractor_make_shareable(lit));
+	break;
+
+      case NODE_HASH:
+	if (!value->nd_brace) return 0;
+	lit = rb_hash_new();
+	for (NODE *n = value->nd_head; n; n = n->nd_next->nd_next) {
+	    NODE *key = n->nd_head;
+	    NODE *val = n->nd_next->nd_head;
+	    if ((key && !(key = shareable_literal_constant(p, key, shareable, &key->nd_loc))) ||
+		(val && !(val = shareable_literal_constant(p, val, shareable, &val->nd_loc)))) {
+		if (lit) {
+		    rb_hash_clear(lit);
+		    lit = Qfalse;
+		}
+		continue;
+	    }
+	    if (lit) {
+		VALUE k = shareable_literal_value(key);
+		VALUE v = shareable_literal_value(val);
+		if (k != Qundef && v != Qundef) {
+		    rb_hash_aset(lit, k, v);
+		}
+		else {
+		    rb_hash_clear(lit);
+		    lit = Qfalse;
+		}
+	    }
+	}
+	if (!lit) return 0;
+	nd_set_type(value, NODE_LIT);
+	RB_OBJ_WRITE(p->ast, &value->nd_lit, rb_ractor_make_shareable(lit));
+	break;
+
+      default:
+	if (shareable == shareable_literal)
+	    yyerror1(loc, "unshareable expression");
+	return 0;
+    }
     return value;
 }
 
 static NODE *
 shareable_constant_value(struct parser_params *p, NODE *value, enum shareability shareable, const YYLTYPE *loc)
 {
+    if (!value) return 0;
     switch (shareable) {
       case shareable_none:
 	return value;
 
       case shareable_literal:
-	return shareable_literal_constant(p, value);
-
       case shareable_everything:
+	{
+	    NODE *lit = shareable_literal_constant(p, value, shareable, loc);
+	    if (lit) return lit;
+	}
 	break;
 
       default:
 	UNREACHABLE_RETURN(0);
     }
 
-    NODE *fcore = NEW_LIT(rb_mRubyVMFrozenCore, loc);
-    return NEW_CALL(fcore, rb_intern("make_shareable"),
-		    NEW_LIST(value, loc), loc);
+    return shareable_literal_node(p, value, loc);
 }
 
 static NODE *
diff --git a/test/ruby/test_parse.rb b/test/ruby/test_parse.rb
index 61551a2..80debd7 100644
--- a/test/ruby/test_parse.rb
+++ b/test/ruby/test_parse.rb
@@ -1187,11 +1187,14 @@ x = __ENCODING__ https://github.com/ruby/ruby/blob/trunk/test/ruby/test_parse.rb#L1187
       A = [[1]]
       # shareable_constant_value: none
       B = [[2]]
+      # shareable_constant_value: literal
+      C = [["shareable", "constant#{nil}"]]
 
-      [A, B]
+      [A, B, C]
     end;
     assert_send([Ractor, :shareable?, a])
     assert_not_send([Ractor, :shareable?, b])
+    assert_send([Ractor, :shareable?, c])
     assert_equal([1], a[0])
     assert_send([Ractor, :shareable?, a[0]])
     a, b = Class.new.class_eval("#{<<~"begin;"}\n#{<<~'end;'}")
@@ -1208,6 +1211,12 @@ x = __ENCODING__ https://github.com/ruby/ruby/blob/trunk/test/ruby/test_parse.rb#L1211
     assert_not_send([Ractor, :shareable?, b])
     assert_equal([1], a[0])
     assert_send([Ractor, :shareable?, a[0]])
+
+    assert_syntax_error("#{<<~"begin;"}\n#{<<~'end;'}", /unshareable expression/)
+    begin;
+      # shareable_constant_value: literal
+      C = ["Not " + "shareable"]
+    end;
   end
 
 =begin
diff --git a/vm.c b/vm.c
index bc57caf..c618b79 100644
--- a/vm.c
+++ b/vm.c
@@ -995,6 +995,7 @@ collect_outer_variable_names(ID id, VALUE val, void *ptr) https://github.com/ruby/ruby/blob/trunk/vm.c#L995
 }
 
 VALUE rb_ractor_error_class(void);
+VALUE rb_ractor_make_shareable(VALUE obj);
 
 static const rb_env_t *
 env_copy(const VALUE *src_ep, VALUE read_only_variables)
-- 
cgit v0.10.2


--
ML: ruby-changes@q...
Info: http://www.atdot.net/~ko1/quickml/

[前][次][番号順一覧][スレッド一覧]