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

ruby-changes:58676

From: Nobuyoshi <ko1@a...>
Date: Sat, 9 Nov 2019 19:40:29 +0900 (JST)
Subject: [ruby-changes:58676] dfaac2b372 (master): Embed builtin ruby scripts in miniprelude.c

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

From dfaac2b37253ff25ec873c2fbd93abfa7f789248 Mon Sep 17 00:00:00 2001
From: Nobuyoshi Nakada <nobu@r...>
Date: Sat, 9 Nov 2019 19:28:45 +0900
Subject: Embed builtin ruby scripts in miniprelude.c

Instead of reading from the files by the full-path at runtime.  As
rbinc files need to be included in distributed tarballs, the
full-paths at the packaging are unavailable at compilation times.

diff --git a/common.mk b/common.mk
index 56eba97..6996ae5 100644
--- a/common.mk
+++ b/common.mk
@@ -1072,7 +1072,7 @@ vm_call_iseq_optimized.inc: $(srcdir)/tool/mk_call_iseq_optimized.rb https://github.com/ruby/ruby/blob/trunk/common.mk#L1072
 $(MINIPRELUDE_C): $(COMPILE_PRELUDE)
 	$(ECHO) generating $@
 	$(Q) $(BASERUBY) $(srcdir)/tool/generic_erb.rb -I$(srcdir) -o $@ \
-		$(srcdir)/template/prelude.c.tmpl
+		$(srcdir)/template/prelude.c.tmpl $(BUILTIN_RB_SRCS)
 
 $(PRELUDE_C): $(COMPILE_PRELUDE) \
 	   $(PRELUDE_SCRIPTS)
diff --git a/mini_builtin.c b/mini_builtin.c
index dc95919..290a4b3 100644
--- a/mini_builtin.c
+++ b/mini_builtin.c
@@ -5,55 +5,21 @@ https://github.com/ruby/ruby/blob/trunk/mini_builtin.c#L5
 
 // include from miniinits.c
 
-static const char *
-read_file(const char *fname, size_t *psize)
-{
-    struct stat st;
-    char *code;
-    FILE *fp;
-
-    if (stat(fname, &st) != 0) {
-        rb_bug("stat fails: %s", fname);
-    }
-
-    size_t fsize = st.st_size;
-    if ((code = malloc(fsize + 1)) == NULL) {
-        rb_bug("can't allocate memory: %s (%d)", fname, (int)fsize);
-    }
-
-    if ((fp = fopen(fname, "rb")) == NULL) {
-        rb_bug("can't open file: %s", fname);
-    }
-
-    size_t read_size = fread(code, 1, fsize, fp);
-    if (read_size != fsize) {
-        rb_bug("can't read file enough: %s (expect %d but was %d)", fname, (int)fsize, (int)read_size);
-    }
-
-    code[fsize] = 0;
-    *psize = fsize;
-    return code;
-}
-
 static struct st_table *loaded_builtin_table;
 
+rb_ast_t *rb_builtin_ast(const char *feature_name, VALUE *name_str);
+
 void
 rb_load_with_builtin_functions(const char *feature_name, const char *fname, const struct rb_builtin_function *table)
 {
-    size_t fsize;
-    const char *code = read_file(fname, &fsize);
-    VALUE code_str = rb_utf8_str_new_static(code, fsize);
-    VALUE name_str = rb_sprintf("<internal:%s>", feature_name);
-    rb_obj_hide(code_str);
-
-    rb_ast_t *ast = rb_parser_compile_string_path(rb_parser_new(), name_str, code_str, 1);
+    VALUE name_str = 0;
+    rb_ast_t *ast = rb_builtin_ast(feature_name, &name_str);
 
     GET_VM()->builtin_function_table = table;
     const rb_iseq_t *iseq = rb_iseq_new(&ast->body, name_str, name_str, Qnil, NULL, ISEQ_TYPE_TOP);
     GET_VM()->builtin_function_table = NULL;
 
     rb_ast_dispose(ast);
-    free((void *)code); // code_str becomes broken.
 
     // register (loaded iseq will not be freed)
     st_insert(loaded_builtin_table, (st_data_t)feature_name, (st_data_t)iseq);
diff --git a/template/prelude.c.tmpl b/template/prelude.c.tmpl
index 4b3a38e..33f6a68 100644
--- a/template/prelude.c.tmpl
+++ b/template/prelude.c.tmpl
@@ -34,8 +34,17 @@ class Prelude https://github.com/ruby/ruby/blob/trunk/template/prelude.c.tmpl#L34
     @output = output
     @have_sublib = false
     @vpath = vpath
+    @prelude_count = 0
+    @builtin_count = 0
     @preludes = {}
-    @mains = preludes.map {|filename| translate(filename)[0]}
+    @mains = preludes.map do |filename|
+      if prelude = filename.end_with?("prelude.rb")
+        @prelude_count += 1
+      else
+        @builtin_count += 1
+      end
+      translate(filename, (filename unless prelude))[0]
+    end
     @preludes.delete_if {|_, (_, _, lines, sub)| sub && lines.empty?}
   end
 
@@ -134,11 +143,47 @@ prelude_prefix_path(VALUE self) https://github.com/ruby/ruby/blob/trunk/template/prelude.c.tmpl#L143
     struct prelude_env *ptr = DATA_PTR(self);
     return ptr->prefix_path;
 }
-% end
 
+% end
 % unless preludes.empty?
 #define PRELUDE_NAME(n) rb_usascii_str_new_static(prelude_name##n, sizeof(prelude_name##n)-1)
 #define PRELUDE_CODE(n) rb_utf8_str_new_static(prelude_code##n.L0, sizeof(prelude_code##n))
+
+static rb_ast_t *
+prelude_ast(VALUE name, VALUE code, int line)
+{
+    rb_ast_t *ast = rb_parser_compile_string_path(rb_parser_new(), name, code, line);
+    if (!ast->body.root) {
+	rb_ast_dispose(ast);
+	rb_exc_raise(rb_errinfo());
+    }
+    return ast;
+}
+
+% end
+% if @builtin_count > 0
+#define PRELUDE_AST(n, name_str) \
+    (((sizeof(prelude_name<%='##'%><%=%>n) - prefix_len - 2) == namelen) && \
+     (strncmp(prelude_name<%='##'%><%=%>n + prefix_len, feature_name, namelen) == 0) ? \
+     prelude_ast((name_str) = PRELUDE_NAME(n), PRELUDE_CODE(n), 1) : 0)
+
+rb_ast_t *
+rb_builtin_ast(const char *feature_name, VALUE *name_str)
+{
+    const size_t prefix_len = rb_strlen_lit("<internal:");
+    size_t namelen = strlen(feature_name);
+    rb_ast_t *ast = 0;
+
+%   @preludes.each_value do |i, prelude, lines, sub|
+%     if sub and sub != true
+    if ((ast = PRELUDE_AST(<%=i%><%=%>, *name_str)) != 0) return ast;
+%     end
+%   end
+    return ast;
+}
+
+% end
+% if @prelude_count > 0
 COMPILER_WARNING_PUSH
 #if GCC_VERSION_SINCE(4, 2, 0)
 COMPILER_WARNING_ERROR(-Wmissing-field-initializers)
@@ -160,18 +205,14 @@ prelude_eval(VALUE code, VALUE name, int line) https://github.com/ruby/ruby/blob/trunk/template/prelude.c.tmpl#L205
 	0, /* int debug_level; */
     };
 
-    rb_ast_t *ast = rb_parser_compile_string_path(rb_parser_new(), name, code, line);
-    if (!ast->body.root) {
-	rb_ast_dispose(ast);
-	rb_exc_raise(rb_errinfo());
-    }
+    rb_ast_t *ast = prelude_ast(name, code, line);
     rb_iseq_eval(rb_iseq_new_with_opt(&ast->body, name, name, Qnil, INT2FIX(line),
 				      NULL, ISEQ_TYPE_TOP, &optimization));
     rb_ast_dispose(ast);
 }
 COMPILER_WARNING_POP
-% end
 
+% end
 % if @have_sublib
 static VALUE
 prelude_require(VALUE self, VALUE nth)
@@ -185,7 +226,7 @@ prelude_require(VALUE self, VALUE nth) https://github.com/ruby/ruby/blob/trunk/template/prelude.c.tmpl#L226
     ptr->loaded[n] = 1;
     switch (n) {
 %   @preludes.each_value do |i, prelude, lines, sub|
-%     if sub
+%     if sub == true
       case <%=i%><%=%>:
 	code = PRELUDE_CODE(<%=i%><%=%>);
 	name = PRELUDE_NAME(<%=i%><%=%>);
@@ -205,7 +246,7 @@ prelude_require(VALUE self, VALUE nth) https://github.com/ruby/ruby/blob/trunk/template/prelude.c.tmpl#L246
 void
 Init_<%=init_name%><%=%>(void)
 {
-%unless @preludes.empty?
+%unless @prelude_count.zero?
 % if @have_sublib
     struct prelude_env memo;
     ID name = rb_intern("TMP_RUBY_PREFIX");
-- 
cgit v0.10.2


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

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