Skip to content

Commit 8728406

Browse files
authored
ZJIT: Inline Thread.current (ruby#15272)
Add `LoadEC` then it's just two `LoadField`.
1 parent 8090988 commit 8728406

File tree

5 files changed

+42
-3
lines changed

5 files changed

+42
-3
lines changed

zjit/src/codegen.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -457,6 +457,7 @@ fn gen_insn(cb: &mut CodeBlock, jit: &mut JITState, asm: &mut Assembler, functio
457457
&Insn::ArrayExtend { left, right, state } => { no_output!(gen_array_extend(jit, asm, opnd!(left), opnd!(right), &function.frame_state(state))) },
458458
&Insn::GuardShape { val, shape, state } => gen_guard_shape(jit, asm, opnd!(val), shape, &function.frame_state(state)),
459459
Insn::LoadPC => gen_load_pc(asm),
460+
Insn::LoadEC => gen_load_ec(),
460461
Insn::LoadSelf => gen_load_self(),
461462
&Insn::LoadField { recv, id, offset, return_type: _ } => gen_load_field(asm, opnd!(recv), id, offset),
462463
&Insn::StoreField { recv, id, offset, val } => no_output!(gen_store_field(asm, opnd!(recv), id, offset, opnd!(val))),
@@ -1041,6 +1042,10 @@ fn gen_load_pc(asm: &mut Assembler) -> Opnd {
10411042
asm.load(Opnd::mem(64, CFP, RUBY_OFFSET_CFP_PC))
10421043
}
10431044

1045+
fn gen_load_ec() -> Opnd {
1046+
EC
1047+
}
1048+
10441049
fn gen_load_self() -> Opnd {
10451050
Opnd::mem(64, CFP, RUBY_OFFSET_CFP_SELF)
10461051
}

zjit/src/cruby.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1377,6 +1377,8 @@ pub(crate) mod ids {
13771377
name: aref content: b"[]"
13781378
name: len
13791379
name: _as_heap
1380+
name: thread_ptr
1381+
name: self_ content: b"self"
13801382
}
13811383

13821384
/// Get an CRuby `ID` to an interned string, e.g. a particular method name.

zjit/src/cruby_methods.rs

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -158,6 +158,7 @@ pub fn init() -> Annotations {
158158
($module:ident, $method_name:literal, $inline:ident) => {
159159
let mut props = FnProperties::default();
160160
props.inline = $inline;
161+
#[allow(unused_unsafe)]
161162
annotate_c_method(cfuncs, unsafe { $module }, $method_name, props);
162163
};
163164
($module:ident, $method_name:literal, $inline:ident, $return_type:expr $(, $properties:ident)*) => {
@@ -167,6 +168,7 @@ pub fn init() -> Annotations {
167168
$(
168169
props.$properties = true;
169170
)*
171+
#[allow(unused_unsafe)]
170172
annotate_c_method(cfuncs, unsafe { $module }, $method_name, props);
171173
};
172174
($module:ident, $method_name:literal, $return_type:expr $(, $properties:ident)*) => {
@@ -240,7 +242,7 @@ pub fn init() -> Annotations {
240242
annotate!(rb_cInteger, "<=", inline_integer_le);
241243
annotate!(rb_cString, "to_s", inline_string_to_s, types::StringExact);
242244
let thread_singleton = unsafe { rb_singleton_class(rb_cThread) };
243-
annotate!(thread_singleton, "current", types::BasicObject, no_gc, leaf);
245+
annotate!(thread_singleton, "current", inline_thread_current, types::BasicObject, no_gc, leaf);
244246

245247
annotate_builtin!(rb_mKernel, "Float", types::Float);
246248
annotate_builtin!(rb_mKernel, "Integer", types::Integer);
@@ -269,6 +271,26 @@ fn inline_string_to_s(fun: &mut hir::Function, block: hir::BlockId, recv: hir::I
269271
None
270272
}
271273

274+
fn inline_thread_current(fun: &mut hir::Function, block: hir::BlockId, _recv: hir::InsnId, args: &[hir::InsnId], _state: hir::InsnId) -> Option<hir::InsnId> {
275+
let &[] = args else { return None; };
276+
let ec = fun.push_insn(block, hir::Insn::LoadEC);
277+
let thread_ptr = fun.push_insn(block, hir::Insn::LoadField {
278+
recv: ec,
279+
id: ID!(thread_ptr),
280+
offset: RUBY_OFFSET_EC_THREAD_PTR as i32,
281+
return_type: types::CPtr,
282+
});
283+
let thread_self = fun.push_insn(block, hir::Insn::LoadField {
284+
recv: thread_ptr,
285+
id: ID!(self_),
286+
offset: RUBY_OFFSET_THREAD_SELF as i32,
287+
// TODO(max): Add Thread type. But Thread.current is not guaranteed to be an exact Thread.
288+
// You can make subclasses...
289+
return_type: types::BasicObject,
290+
});
291+
Some(thread_self)
292+
}
293+
272294
fn inline_kernel_itself(_fun: &mut hir::Function, _block: hir::BlockId, recv: hir::InsnId, args: &[hir::InsnId], _state: hir::InsnId) -> Option<hir::InsnId> {
273295
if args.is_empty() {
274296
// No need to coerce the receiver; that is done by the SendWithoutBlock rewriting.

zjit/src/hir.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -736,6 +736,8 @@ pub enum Insn {
736736

737737
/// Load cfp->pc
738738
LoadPC,
739+
/// Load EC
740+
LoadEC,
739741
/// Load cfp->self
740742
LoadSelf,
741743
LoadField { recv: InsnId, id: ID, offset: i32, return_type: Type },
@@ -980,6 +982,7 @@ impl Insn {
980982
Insn::GetLocal { .. } => false,
981983
Insn::IsNil { .. } => false,
982984
Insn::LoadPC => false,
985+
Insn::LoadEC => false,
983986
Insn::LoadSelf => false,
984987
Insn::LoadField { .. } => false,
985988
Insn::CCall { elidable, .. } => !elidable,
@@ -1272,6 +1275,7 @@ impl<'a> std::fmt::Display for InsnPrinter<'a> {
12721275
Insn::DefinedIvar { self_val, id, .. } => write!(f, "DefinedIvar {self_val}, :{}", id.contents_lossy()),
12731276
Insn::GetIvar { self_val, id, .. } => write!(f, "GetIvar {self_val}, :{}", id.contents_lossy()),
12741277
Insn::LoadPC => write!(f, "LoadPC"),
1278+
Insn::LoadEC => write!(f, "LoadEC"),
12751279
Insn::LoadSelf => write!(f, "LoadSelf"),
12761280
&Insn::LoadField { recv, id, offset, return_type: _ } => write!(f, "LoadField {recv}, :{}@{:p}", id.contents_lossy(), self.ptr_map.map_offset(offset)),
12771281
&Insn::StoreField { recv, id, offset, val } => write!(f, "StoreField {recv}, :{}@{:p}, {val}", id.contents_lossy(), self.ptr_map.map_offset(offset)),
@@ -1775,6 +1779,7 @@ impl Function {
17751779
| SideExit {..}
17761780
| EntryPoint {..}
17771781
| LoadPC
1782+
| LoadEC
17781783
| LoadSelf
17791784
| IncrCounterPtr {..}
17801785
| IncrCounter(_)) => result.clone(),
@@ -2069,6 +2074,7 @@ impl Function {
20692074
Insn::GetGlobal { .. } => types::BasicObject,
20702075
Insn::GetIvar { .. } => types::BasicObject,
20712076
Insn::LoadPC => types::CPtr,
2077+
Insn::LoadEC => types::CPtr,
20722078
Insn::LoadSelf => types::BasicObject,
20732079
&Insn::LoadField { return_type, .. } => return_type,
20742080
Insn::GetSpecialSymbol { .. } => types::BasicObject,
@@ -3397,6 +3403,7 @@ impl Function {
33973403
| &Insn::Param
33983404
| &Insn::EntryPoint { .. }
33993405
| &Insn::LoadPC
3406+
| &Insn::LoadEC
34003407
| &Insn::LoadSelf
34013408
| &Insn::GetLocal { .. }
34023409
| &Insn::PutSpecialObject { .. }
@@ -4101,6 +4108,7 @@ impl Function {
41014108
| Insn::IsBlockGiven
41024109
| Insn::GetGlobal { .. }
41034110
| Insn::LoadPC
4111+
| Insn::LoadEC
41044112
| Insn::LoadSelf
41054113
| Insn::Snapshot { .. }
41064114
| Insn::Jump { .. }

zjit/src/hir/opt_tests.rs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5965,10 +5965,12 @@ mod hir_opt_tests {
59655965
v20:Class[VALUE(0x1008)] = Const Value(VALUE(0x1008))
59665966
PatchPoint MethodRedefined(Class@0x1010, current@0x1018, cme:0x1020)
59675967
PatchPoint NoSingletonClass(Class@0x1010)
5968+
v24:CPtr = LoadEC
5969+
v25:CPtr = LoadField v24, :thread_ptr@0x1048
5970+
v26:BasicObject = LoadField v25, :self@0x1049
59685971
IncrCounter inline_cfunc_optimized_send_count
5969-
v25:BasicObject = CCall Thread.current@0x1048, v20
59705972
CheckInterrupts
5971-
Return v25
5973+
Return v26
59725974
");
59735975
}
59745976

0 commit comments

Comments
 (0)