提问人:Joseph Garvin 提问时间:4/30/2023 更新时间:4/30/2023 访问量:79
ret后说明,热/冷分裂的副作用和异常?
Instructions after ret, side effect of hot/cold splitting and exceptions?
问:
我想检查 GCC 是否确保在抛出异常时为运行析构函数生成的额外代码放在二进制文件的冷部分,以使这些指令远离“快乐路径”并避免导致指令缓存压力。所以我在下面做了一个例子(Godbolt 链接),其中 GCC 无法判断是否会抛出异常。果然,我在组件中看到了一个单独的标签。但是在它上面有一个奇怪的神器:buzz(int) [clone .cold.0]:
.L9:
mov edi, OFFSET FLAT:.LC0
xor eax, eax
call printf
mov eax, ebx
add rsp, 16
imul eax, ebx
add eax, ebx
pop rbx
ret
mov rbx, rax
jmp .L3
buzz(int) [clone .cold.0]:
.L3:
mov eax, DWORD PTR [rsp+12]
...
请注意,指令后面跟着 a 进入寒冷区域。但是之后的指令不是跳转目标(无标签)永远不应该运行。我想这可能是出于指令对齐的目的,但随后跳入冷部分似乎太奇怪了。这是怎么回事?为什么这里有这些说明?也许与解开工作原理的协议有关,它需要在那里,而异常展开表使它成为跳转目标,但它只是未标记?但如果是这样的话,为什么不直接跳到冷部分呢?ret
jmp
ret
C++ 代码:
#include <stdio.h>
extern int global;
struct Foo
{
Foo(int x)
: x(x)
{}
~Foo() {
if(x % global == 0) {
printf("Wow.");
}
}
int x;
};
void bar(Foo& f); // compiler can't see impl, has to assume could throw
// Type your code here, or load an example.
int buzz(int num) {
{
Foo foo(3);
bar(foo);
}
return num * num + num;
}
答: 暂无答案
评论
.L5
.gcc_except_table
.p2align
mov rbx, rax
.gcc_except_table
.L3
mov
jmp
ret