Fix panic in p_block when all control-point live values are globals#2167
Fix panic in p_block when all control-point live values are globals#2167Pavel-Durov wants to merge 7 commits into
Conversation
When all live values at a control point are globals, their addresses are baked into the IR and nothing needs passing via registers or stack. This produces a trace block with no Arg instructions, which previously caused an unconditional panic in p_block.
| @@ -0,0 +1,43 @@ | |||
| // Run-time: | |||
There was a problem hiding this comment.
AFAICS this test doesn't prove it's testing what it claims. I think we would need to have IR in here and check that there are no arg instructions.
There was a problem hiding this comment.
This test triggers that panic in a trace https://github.com/ykjit/yk/blob/master/ykrt/src/compile/j2/hir_to_asm.rs#L866
There was a problem hiding this comment.
In the current test all interpreter state (g_pc, g_mt, i) are set as globals, so the control point safepoint records no live locals:
bb0:
%0_0: ptr = alloca {0: i64}, 1, 8
%0_1: ptr = call malloc(1000000i64)
%0_2: ptr = ptr_add %0_1, 16
*@shadowstack_head = %0_1
*@shadowstack_0 = %0_2
%0_5: ptr = ptr_add %0_1, 0
*%0_5 = 0i32
br bb1
...
bb7:
# guard_body_no_args.c:34: yk_mt_control_point(g_mt, &i);
%7_0: ptr = load @g_mt
call llvm.experimental.patchpoint.void(0i64, 13i32, __ykrt_control_point, 3i32, %7_0, @i, 0i64) [safepoint: 0i64, ()]
# guard_body_no_args.c:35: debug_fn();
br bb8
In Contrast, if g_pc is moved from a global to a local declared inside main it assigns it a shadow stack slot and it appears as a live variable:
-long g_pc = 0;
+
YkMT *g_mt = NULL;
YkLocation i;
i = yk_location_new();
+ long g_pc = 0;Produced IR:
bb0:
%0_0: ptr = alloca {0: i64}, 1, 8
%0_1: ptr = call malloc(1000000i64)
%0_2: ptr = ptr_add %0_1, 16
*@shadowstack_head = %0_1
*@shadowstack_0 = %0_2
%0_5: ptr = ptr_add %0_1, 0
%0_6: ptr = ptr_add %0_1, 8 ; shadow stack slot for g_pc
*%0_5 = 0i32
br bb1
...
bb8:
# guard_body_no_args.c:35: yk_mt_control_point(g_mt, &i);
%8_0: ptr = load @g_mt
call llvm.experimental.patchpoint.void(0i64, 13i32, __ykrt_control_point, 3i32, %8_0, @i, 0i64, %0_6) [safepoint: 0i64, (%0_6)]
# guard_body_no_args.c:36: debug_fn();
br bb9
%0_6 is live at the control point and yk emits an Arg instruction.
There was a problem hiding this comment.
What I mean is: the C code might show this but the lang_tester test doesn't prove this. We'd need YKD_LOG_IR=jit and then guarantee that has no args in it.
|
Maybe I'm missing out on something here, but when I look in yksompp at Put another way: I get the problem this PR is fixing, but I don't quite understand how it occurs in practise. |
|
The control point block in yksompp looks like this: It has one live varible - |
…Durov/yk-fork into fix-no-arg-trace-when-all-globals
…-when-all-globals
This is something came up while ykifying the yksompp interpreter - there are a lot of static and global varibles.
When all live values at a control point are globals, their addresses are baked into the IR and nothing needs passing via registers or stack. This produces a trace block with no Arg instructions, which previously caused an unconditional panic in p_block.
This fix make yksompp ~20% faster on
AWFY List 150 4.