@@ -15,11 +15,6 @@ use std::collections::HashMap;
15
15
// assume_single_ractor_mode(jit)
16
16
// assume_stable_global_constant_state(jit);
17
17
18
- struct MethodLookupDependency {
19
- block : BlockRef ,
20
- mid : ID
21
- }
22
-
23
18
/// Used to track all of the various block references that contain assumptions
24
19
/// about the state of the virtual machine.
25
20
pub struct Invariants {
@@ -33,7 +28,13 @@ pub struct Invariants {
33
28
/// Tracks block assumptions about method lookup. Maps a class to a table of
34
29
/// method ID points to a set of blocks. While a block `b` is in the table,
35
30
/// b->callee_cme == rb_callable_method_entry(klass, mid).
36
- method_lookup : HashMap < VALUE , HashMap < ID , Vec < MethodLookupDependency > > >
31
+ method_lookup : HashMap < VALUE , HashMap < ID , Vec < ( BlockRef , ID ) > > > <
10000
span class=pl-kos>,
32
+
33
+ /// Tracks the set of blocks that are assuming the interpreter is running
34
+ /// with only one ractor. This is important for things like accessing
35
+ /// constants which can have different semantics when multiple ractors are
36
+ /// running.
37
+ single_ractor : Vec < BlockRef >
37
38
}
38
39
39
40
/// Private singleton instance of the invariants global struct.
@@ -46,7 +47,8 @@ impl Invariants {
46
47
INVARIANTS = Some ( Invariants {
47
48
basic_operators : HashMap :: new ( ) ,
48
49
cme_validity : HashMap :: new ( ) ,
49
- method_lookup : HashMap :: new ( )
50
+ method_lookup : HashMap :: new ( ) ,
51
+ single_ractor : Vec :: new ( )
50
52
} ) ;
51
53
}
52
54
}
@@ -55,12 +57,6 @@ impl Invariants {
55
57
pub fn get_instance ( ) -> & ' static mut Invariants {
56
58
unsafe { INVARIANTS . as_mut ( ) . unwrap ( ) }
57
59
}
58
-
59
- /// Returns the vector of blocks that are currently assuming the given basic
60
- /// operator on the given class has not been redefined.
61
- pub fn get_bop_assumptions ( klass : RedefinitionFlag , bop : ruby_basic_operators ) -> & ' static mut Vec < BlockRef > {
62
- Invariants :: get_instance ( ) . basic_operators . entry ( ( klass, bop) ) . or_insert ( Vec :: new ( ) )
63
- }
64
60
}
65
61
66
62
/// A public function that can be called from within the code generation
@@ -69,7 +65,15 @@ impl Invariants {
69
65
pub fn assume_bop_not_redefined ( jit : & mut JITState , ocb : & mut OutlinedCb , klass : RedefinitionFlag , bop : ruby_basic_operators ) -> bool {
70
66
if unsafe { BASIC_OP_UNREDEFINED_P ( bop, klass) } {
71
67
jit_ensure_block_entry_exit ( jit, ocb) ;
72
- Invariants :: get_bop_assumptions ( klass, bop) . push ( jit. get_block ( ) ) ;
68
+
69
+ // First, fetch the entry in the list of basic operators that
70
+ // corresponds to this class and basic operator tuple.
71
+ let entry = Invariants :: get_instance ( ) . basic_operators . entry ( ( klass, bop) ) ;
72
+
73
+ // Next, add the current block to the list of blocks that are assuming
74
+ // this basic operator is not redefined.
75
+ entry. or_insert ( Vec :: new ( ) ) . push ( jit. get_block ( ) ) ;
76
+
73
77
return true ;
74
78
} else {
75
79
return false ;
@@ -99,18 +103,41 @@ pub fn assume_method_lookup_stable(jit: &mut JITState, ocb: &mut OutlinedCb, rec
99
103
Invariants :: get_instance ( ) . method_lookup
100
104
. entry ( receiver_klass) . or_insert ( HashMap :: new ( ) )
101
105
. entry ( mid) . or_insert ( Vec :: new ( ) )
102
- . push ( MethodLookupDependency { block : block. clone ( ) , mid } ) ;
106
+ . push ( ( block. clone ( ) , mid) ) ;
107
+ }
108
+
109
+ /// Tracks that a block is assuming it is operating in single-ractor mode.
110
+ pub fn assume_single_ractor_mode ( jit : & mut JITState , ocb : & mut OutlinedCb ) -> bool {
111
+ if unsafe { rb_yjit_multi_ractor_p ( ) } {
112
+ false
113
+ } else {
114
+ jit_ensure_block_entry_exit ( jit, ocb) ;
115
+ Invariants :: get_instance ( ) . single_ractor . push ( jit. get_block ( ) ) ;
116
+ true
117
+ }
103
118
}
104
119
105
120
/// Called when a basic operation is redefined.
106
121
#[ no_mangle]
107
122
pub extern "C" fn rb_yjit_bop_redefined ( klass : RedefinitionFlag , bop : ruby_basic_operators ) {
108
- for block in Invariants :: get_bop_assumptions ( klass, bop) . iter ( ) {
123
+ for block in Invariants :: get_instance ( ) . basic_operators . entry ( ( klass, bop) ) . or_insert ( Vec :: new ( ) ) . iter ( ) {
109
124
invalidate_block_version ( block) ;
110
125
incr_counter ! ( invalidate_bop_redefined) ;
111
126
}
112
127
}
113
128
129
+ /// Callback for when a cme becomes invalid. Invalidate all blocks that depend
130
+ /// on the given cme being valid.
131
+ #[ no_mangle]
132
+ pub extern "C" fn rb_yjit_cme_invalidate ( callee_cme : * const rb_callable_method_entry_t ) {
133
+ Invariants :: get_instance ( ) . cme_validity . remove ( & callee_cme) . map ( |blocks| {
134
+ for block in blocks. iter ( ) {
135
+ invalidate_block_version ( block) ;
136
+ incr_counter ! ( invalidate_method_lookup) ;
137
+ }
138
+ } ) ;
139
+ }
140
+
114
141
/// Callback for when rb_callable_method_entry(klass, mid) is going to change.
115
142
/// Invalidate blocks that assume stable method lookup of `mid` in `klass` when this happens.
116
143
/// This needs to be wrapped on the C side with RB_VM_LOCK_ENTER().
@@ -123,61 +150,28 @@ pub extern "C" fn rb_yjit_method_lookup_change(klass: VALUE, mid: ID) {
123
150
124
151
Invariants :: get_instance ( ) . method_lookup . entry ( klass) . and_modify ( |deps| {
125
152
deps. remove ( & mid) . map ( |deps| {
126
- for dep in deps. iter ( ) {
127
- invalidate_block_version ( & dep . block ) ;
153
+ for ( block , mid ) in deps. iter ( ) {
154
+ invalidate_block_version ( block) ;
128
155
incr_counter ! ( invalidate_method_lookup) ;
129
156
}
130
157
} ) ;
131
158
} ) ;
132
159
}
133
160
134
- #[ cfg( test) ]
135
- mod tests {
136
- use super :: * ;
137
-
138
- #[ test]
139
- fn test_get_bop_assumptions ( ) {
140
- Invariants :: init ( ) ;
141
-
142
- let block = Block :: new ( BLOCKID_NULL , & Context :: default ( ) ) ;
143
- let bops = & mut Invariants :: get_instance ( ) . basic_operators ;
144
-
145
- // Configure the set of assumptions such that one block is assuming
146
- // Integer#+ is not redefined and one block is assuming String#+ is not
147
- // redefined.
148
- bops. insert ( ( INTEGER_REDEFINED_OP_FLAG , BOP_PLUS ) , vec ! [ block. clone( ) ] ) ;
149
- bops. insert ( ( STRING_REDEFINED_OP_FLAG , BOP_PLUS ) , vec ! [ block. clone( ) ] ) ;
150
-
151
- assert_eq ! ( Invariants :: get_bop_assumptions( INTEGER_REDEFINED_OP_FLAG , BOP_PLUS ) . len( ) , 1 ) ;
161
+ /// Callback for then Ruby is about to spawn a ractor. In that case we need to
162
+ /// invalidate every block that is assuming single ractor mode.
163
+ #[ no_mangle]
164
+ pub extern "C" fn rb_yjit_before_ractor_spawn ( ) {
165
+ for block in Invariants :: get_instance ( ) . single_ractor . iter ( ) {
166
+ invalidate_block_version ( block) ;
167
+ incr_counter ! ( invalidate_ractor_spawn) ;
152
168
}
153
169
}
154
170
155
171
156
172
157
173
158
174
159
-
160
- //static st_table *blocks_assuming_single_ractor_mode;
161
-
162
- // Can raise NoMemoryError.
163
- //RBIMPL_ATTR_NODISCARD()
164
- pub fn assume_single_ractor_mode ( jit : & JITState ) -> bool
165
- {
166
- todo ! ( )
167
- /*
168
- if (rb_multi_ractor_p()) return false;
169
-
170
- jit_ensure_block_entry_exit(jit);
171
-
172
- //st_insert(blocks_assuming_single_ractor_mode, (st_data_t)jit->block, 1);
173
- true
174
- */
175
- }
176
-
177
-
178
-
179
-
180
-
181
175
//static st_table *blocks_assuming_stable_global_constant_state;
182
176
183
177
// Assume that the global constant state has not changed since call to this function.
@@ -191,69 +185,10 @@ pub fn assume_stable_global_constant_state(jit: &JITState)
191
185
*/
192
186
}
193
187
194
-
195
-
196
188
/*
197
- // Callback for when a cme becomes invalid.
198
- // Invalidate all blocks that depend on cme being valid.
199
- void
200
- rb_yjit_cme_invalidate(VALUE cme)
201
- {
202
- if (!cme_validity_dependency) return;
203
-
204
- RUBY_ASSERT(IMEMO_TYPE_P(cme, imemo_ment));
205
-
206
- RB_VM_LOCK_ENTER();
207
-
208
- // Delete the block set from the table
209
- st_data_t cme_as_st_data = (st_data_t)cme;
210
- st_data_t blocks;
211
- if (st_delete(cme_validity_dependency, &cme_as_st_data, &blocks)) {
212
- st_table *block_set = (st_table *)blocks;
213
-
214
- #if YJIT_STATS
215
- yjit_runtime_counters.invalidate_method_lookup += block_set->num_entries;
216
- #endif
217
-
218
- // Invalidate each block
219
- st_foreach(block_set, block_set_invalidate_i, 0);
220
-
221
- st_free_table(block_set);
222
- }
223
-
224
- RB_VM_LOCK_LEAVE();
225
- }
226
- */
227
-
228
-
229
- /*
230
- static void
231
- yjit_block_assumptions_free(block_t *block)
232
- {
233
- st_data_t as_st_data = (st_data_t)block;
234
- if (blocks_assuming_stable_global_constant_state) {
235
- st_delete(blocks_assuming_stable_global_constant_state, &as_st_data, NULL);
236
- }
237
-
238
- if (blocks_assuming_single_ractor_mode) {
239
- st_delete(blocks_assuming_single_ractor_mode, &as_st_data, NULL);
240
- }
241
-
242
- if (blocks_assuming_bops) {
243
- st_delete(blocks_assuming_bops, &as_st_data, NULL);
244
- }
245
- }
246
- */
247
-
248
-
249
-
250
-
251
- /*
252
- // When a block is deleted, remove the assumptions associated with it
253
189
static void
254
190
yjit_block_assumptions_free(block_t *block)
255
191
{
256
- /*
257
192
st_data_t as_st_data = (st_data_t)block;
258
193
if (blocks_assuming_stable_global_constant_state) {
259
194
st_delete(blocks_assuming_stable_global_constant_state, &as_st_data, NULL);
@@ -266,13 +201,9 @@ yjit_block_assumptions_free(block_t *block)
266
201
if (blocks_assuming_bops) {
267
202
st_delete(blocks_assuming_bops, &as_st_data, NULL);
268
203
}
269
- */
270
204
}
271
205
*/
272
206
273
-
274
-
275
-
276
207
/*
277
208
// Free the yjit resources associated with an iseq
278
209
void
@@ -371,18 +302,6 @@ rb_yjit_constant_ic_update(const rb_iseq_t *const iseq, IC ic)
371
302
}
372
303
RB_VM_LOCK_LEAVE();
373
304
}
374
-
375
- void
376
- rb_yjit_before_ractor_spawn(void)
377
- {
378
- if (blocks_assuming_single_ractor_mode) {
379
- #if YJIT_STATS
380
- yjit_runtime_counters.invalidate_ractor_spawn += blocks_assuming_single_ractor_mode->num_entries;
381
- #endif
382
-
383
- st_foreach(blocks_assuming_single_ractor_mode, block_set_invalidate_i, 0);
384
- }
385
- }
386
305
*/
387
306
388
307
// Invalidate all generated code and patch C method return code to contain
0 commit comments