@@ -13,7 +13,24 @@ module FeatureLoader
13
13
14
14
DOT_DLEXT = ".#{ Truffle ::Platform ::DLEXT } "
15
15
16
- # FeatureEntry => [*index_inside_$LOADED_FEATURES]
16
+ #
17
+ # The following $LOADED_FEATURES:
18
+ # ["/one/path.rb", "/two/path.so", "three/path" ]
19
+ #
20
+ # would create the @loaded_features_index:
21
+ #
22
+ # {
23
+ # "path" => [
24
+ # #<FeatureEntry @feature="/one/path.rb" @index=0>,
25
+ # #<FeatureEntry @feature="/two/path.so" @index=1>,
26
+ # #<FeatureEntry @feature="/three/path" @index=2>,
27
+ # ]
28
+ # }
29
+ #
30
+ # For the feature "path" or "nested/path", all three feature entries are in the same hash key and `include?`
31
+ # the feature. However, for feature "path.rb", only the first entry with the same extension would be at the same
32
+ # hash key and not `include?` the feature.
33
+ #
17
34
@loaded_features_index = { }
18
35
# A snapshot of $LOADED_FEATURES, to check if the @loaded_features_index cache is up to date.
19
36
@loaded_features_version = -1
@@ -33,43 +50,24 @@ def self.clear_cache
33
50
end
34
51
35
52
class FeatureEntry
36
- attr_reader :feature , :ext , :feature_no_ext
37
- attr_accessor :part_of_index
53
+ attr_accessor :index
54
+ attr_reader :feature , :ext , :feature_no_ext , :base
38
55
39
56
def initialize ( feature )
40
- @part_of_index = false
41
57
@ext = Truffle ::FeatureLoader . extension ( feature )
42
58
@feature = feature
43
59
@feature_no_ext = @ext ? feature [ 0 ...( -@ext . size ) ] : feature
44
60
@base = File . basename ( @feature_no_ext )
61
+ @index = nil
45
62
end
46
63
47
- def ==( other )
48
- # The looked up feature has to be the trailing part of an already-part_of_index entry.
49
- # We always want to check part_of_index_feature.end_with?(lookup_feature).
50
- # We compare extensions only if the lookup_feature has an extension.
51
-
52
- if @part_of_index
53
- stored = self
54
- lookup = other
55
- elsif other . part_of_index
56
- stored = other
57
- lookup = self
58
- else
59
- raise 'Expected that at least one of the FeatureEntry instances is part of the index'
60
- end
61
-
64
+ def include? ( lookup )
62
65
if lookup . ext
63
- stored . feature . end_with? ( lookup . feature )
66
+ feature . end_with? ( lookup . feature )
64
67
else
65
- stored . feature_no_ext . end_with? ( lookup . feature_no_ext )
68
+ feature_no_ext . end_with? ( lookup . feature_no_ext )
66
69
end
67
70
end
68
- alias_method :eql? , :==
69
-
70
- def hash
71
- @base . hash
72
- end
73
71
end
74
72
75
73
def self . find_file ( feature )
@@ -161,30 +159,32 @@ def self.feature_provided?(feature, expanded)
161
159
with_synchronized_features do
162
160
get_loaded_features_index
163
161
feature_entry = FeatureEntry . new ( feature )
164
- if @loaded_features_index . key? ( feature_entry )
165
- @loaded_features_index [ feature_entry ] . each do |i |
166
- loaded_feature = $LOADED_FEATURES[ i ]
162
+ if @loaded_features_index . key? ( feature_entry . base )
163
+ @loaded_features_index [ feature_entry . base ] . each do |fe |
164
+ if fe . include? ( feature_entry )
165
+ loaded_feature = $LOADED_FEATURES[ fe . index ]
167
166
168
- next if loaded_feature . size < feature . size
169
- feature_path = if loaded_feature . start_with? ( feature )
170
- feature
171
- else
172
- if expanded
173
- nil
167
+ next if loaded_feature . size < feature . size
168
+ feature_path = if loaded_feature . start_with? ( feature )
169
+ feature
174
170
else
175
- loaded_feature_path ( loaded_feature , feature , get_expanded_load_path )
171
+ if expanded
172
+ nil
173
+ else
174
+ loaded_feature_path ( loaded_feature , feature , get_expanded_load_path )
175
+ end
176
176
end
177
- end
178
- if feature_path
179
- loaded_feature_ext = extension_symbol ( loaded_feature )
180
- if ! loaded_feature_ext
181
- return :unknown unless feature_ext
182
- else
183
- if ( ! feature_has_rb_ext || ! feature_ext ) && binary_ext? ( loaded_feature_ext )
184
- return :so
185
- end
186
- if ( feature_has_rb_ext || ! feature_ext ) && loaded_feature_ext == :rb
187
- return :rb
177
+ if feature_path
178
+ loaded_feature_ext = extension_symbol ( loaded_feature )
179
+ if ! loaded_feature_ext
180
+ return :unknown unless feature_ext
181
+ else
182
+ if ( ! feature_has_rb_ext || ! feature_ext ) && binary_ext? ( loaded_feature_ext )
183
+ return :so
184
+ end
185
+ if ( feature_has_rb_ext || ! feature_ext ) && loaded_feature_ext == :rb
186
+ return :rb
187
+ end
188
188
end
189
189
end
190
190
end
@@ -225,7 +225,7 @@ def self.relative_feature(expanded_path)
225
225
if !load_path_entries . empty?
226
226
load_path_entry = load_path_entries . max_by ( &:length )
227
227
before_dot_rb = expanded_path . end_with? ( '.rb' ) ? -4 : -1
228
- expanded_path [ load_path_entry . size + 1 ..before_dot_rb ]
228
+ expanded_path [ load_path_entry . size + 1 ..before_dot_rb ]
229
229
else
230
230
nil
231
231
end
@@ -297,13 +297,14 @@ def self.get_loaded_features_index
297
297
298
298
# MRI: features_index_add
299
299
# always called inside #with_synchronized_features
300
+ #
300
301
def self . features_index_add ( feature , offset )
301
302
feature_entry = FeatureEntry . new ( feature )
302
- if @loaded_features_index . key? ( feature_entry )
303
- @loaded_features_index [ feature_entry ] << offset
303
+ feature_entry . index = offset
304
+ if @loaded_features_index . key? ( feature_entry . base )
305
+ @loaded_features_index [ feature_entry . base ] << feature_entry
304
306
else
305
- @loaded_features_index [ feature_entry ] = [ offset ]
306
- feature_entry . part_of_index = true
307
+ @loaded_features_index [ feature_entry . base ] = [ feature_entry ]
307
308
end
308
309
end
309
310
0 commit comments