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

ruby-changes:67015

From: nagachika <ko1@a...>
Date: Sun, 1 Aug 2021 18:23:31 +0900 (JST)
Subject: [ruby-changes:67015] 0dbb3c15db (ruby_3_0): merge revision(s) b360588cd3cbac5fb4f004aa53a8fdc715906719: [Backport #15856]

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

From 0dbb3c15dbe9b7693ea362c94ed8939d20cba083 Mon Sep 17 00:00:00 2001
From: nagachika <nagachika@r...>
Date: Sun, 1 Aug 2021 18:05:04 +0900
Subject: merge revision(s) b360588cd3cbac5fb4f004aa53a8fdc715906719: [Backport
 #15856]

	Sort feature index arrays by the priority of file types [Bug #15856]

	When looking for libraries to load with a feature name without
	extension, `.rb` files are given priority. However, since the
	feature index arrays were not in that order of priority, but in
	the order in which they were loaded, a lower priority extension
	library might be returned. In that case, the `.rb` file had to be
	searched for again from the `$LOAD_PATH`, resulting in poor
	performance.
	---
	 load.c | 52 +++++++++++++++++++++++++++++++++++++++++++++-------
	 1 file changed, 45 insertions(+), 7 deletions(-)
---
 load.c    | 52 +++++++++++++++++++++++++++++++++++++++++++++-------
 version.h |  6 +++---
 2 files changed, 48 insertions(+), 10 deletions(-)

diff --git a/load.c b/load.c
index cf3adcb..cb6b1fa 100644
--- a/load.c
+++ b/load.c
@@ -185,8 +185,17 @@ feature_key(const char *str, size_t len) https://github.com/ruby/ruby/blob/trunk/load.c#L185
     return st_hash(str, len, 0xfea7009e);
 }
 
+static bool
+is_rbext_path(VALUE feature_path)
+{
+    long len = RSTRING_LEN(feature_path);
+    long rbext_len = rb_strlen_lit(".rb");
+    if (len <= rbext_len) return false;
+    return IS_RBEXT(RSTRING_PTR(feature_path) + len - rbext_len);
+}
+
 static void
-features_index_add_single(const char* str, size_t len, VALUE offset)
+features_index_add_single(const char* str, size_t len, VALUE offset, bool rb)
 {
     struct st_table *features_index;
     VALUE this_feature_index = Qnil;
@@ -202,17 +211,43 @@ features_index_add_single(const char* str, size_t len, VALUE offset) https://github.com/ruby/ruby/blob/trunk/load.c#L211
 	st_insert(features_index, short_feature_key, (st_data_t)offset);
     }
     else if (RB_TYPE_P(this_feature_index, T_FIXNUM)) {
+	VALUE loaded_features = get_loaded_features();
+	VALUE this_feature_path = RARRAY_AREF(loaded_features, FIX2LONG(this_feature_index));
 	VALUE feature_indexes[2];
-	feature_indexes[0] = this_feature_index;
-	feature_indexes[1] = offset;
+	int top = (rb && !is_rbext_path(this_feature_path)) ? 1 : 0;
+	feature_indexes[top^0] = this_feature_index;
+	feature_indexes[top^1] = offset;
 	this_feature_index = (VALUE)xcalloc(1, sizeof(struct RArray));
 	RBASIC(this_feature_index)->flags = T_ARRAY; /* fake VALUE, do not mark/sweep */
 	rb_ary_cat(this_feature_index, feature_indexes, numberof(feature_indexes));
 	st_insert(features_index, short_feature_key, (st_data_t)this_feature_index);
     }
     else {
+        long pos = -1;
+
 	Check_Type(this_feature_index, T_ARRAY);
+        if (rb) {
+            VALUE loaded_features = get_loaded_features();
+            for (long i = 0; i < RARRAY_LEN(this_feature_index); ++i) {
+                VALUE idx = RARRAY_AREF(this_feature_index, i);
+                VALUE this_feature_path = RARRAY_AREF(loaded_features, FIX2LONG(idx));
+                Check_Type(this_feature_path, T_STRING);
+                if (!is_rbext_path(this_feature_path)) {
+                    /* as this_feature_index is a fake VALUE, `push` (which
+                     * doesn't wb_unprotect like as rb_ary_splice) first,
+                     * then rotate partially. */
+                    pos = i;
+                    break;
+                }
+            }
+        }
 	rb_ary_push(this_feature_index, offset);
+        if (pos >= 0) {
+            VALUE *ptr = (VALUE *)RARRAY_CONST_PTR_TRANSIENT(this_feature_index);
+            long len = RARRAY_LEN(this_feature_index);
+            MEMMOVE(ptr + pos, ptr + pos + 1, VALUE, len - pos - 1);
+            ptr[pos] = offset;
+        }
     }
 }
 
@@ -228,6 +263,7 @@ static void https://github.com/ruby/ruby/blob/trunk/load.c#L263
 features_index_add(VALUE feature, VALUE offset)
 {
     const char *feature_str, *feature_end, *ext, *p;
+    bool rb = false;
 
     feature_str = StringValuePtr(feature);
     feature_end = feature_str + RSTRING_LEN(feature);
@@ -237,6 +273,8 @@ features_index_add(VALUE feature, VALUE offset) https://github.com/ruby/ruby/blob/trunk/load.c#L273
 	    break;
     if (*ext != '.')
 	ext = NULL;
+    else
+        rb = IS_RBEXT(ext);
     /* Now `ext` points to the only string matching %r{^\.[^./]*$} that is
        at the end of `feature`, or is NULL if there is no such string. */
 
@@ -248,14 +286,14 @@ features_index_add(VALUE feature, VALUE offset) https://github.com/ruby/ruby/blob/trunk/load.c#L286
 	if (p < feature_str)
 	    break;
 	/* Now *p == '/'.  We reach this point for every '/' in `feature`. */
-	features_index_add_single(p + 1, feature_end - p - 1, offset);
+	features_index_add_single(p + 1, feature_end - p - 1, offset, false);
 	if (ext) {
-	    features_index_add_single(p + 1, ext - p - 1, offset);
+	    features_index_add_single(p + 1, ext - p - 1, offset, rb);
 	}
     }
-    features_index_add_single(feature_str, feature_end - feature_str, offset);
+    features_index_add_single(feature_str, feature_end - feature_str, offset, false);
     if (ext) {
-	features_index_add_single(feature_str, ext - feature_str, offset);
+	features_index_add_single(feature_str, ext - feature_str, offset, rb);
     }
 }
 
diff --git a/version.h b/version.h
index 861825d..4bdc8b9 100644
--- a/version.h
+++ b/version.h
@@ -12,11 +12,11 @@ https://github.com/ruby/ruby/blob/trunk/version.h#L12
 # define RUBY_VERSION_MINOR RUBY_API_VERSION_MINOR
 #define RUBY_VERSION_TEENY 3
 #define RUBY_RELEASE_DATE RUBY_RELEASE_YEAR_STR"-"RUBY_RELEASE_MONTH_STR"-"RUBY_RELEASE_DAY_STR
-#define RUBY_PATCHLEVEL 117
+#define RUBY_PATCHLEVEL 118
 
 #define RUBY_RELEASE_YEAR 2021
-#define RUBY_RELEASE_MONTH 7
-#define RUBY_RELEASE_DAY 29
+#define RUBY_RELEASE_MONTH 8
+#define RUBY_RELEASE_DAY 1
 
 #include "ruby/version.h"
 
-- 
cgit v1.1


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

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