2009-10-11 20:06:12 +00:00
|
|
|
/* DWARF2 EH unwinding support for AMD x86-64 and x86.
|
2025-01-02 11:59:57 +01:00
|
|
|
Copyright (C) 2009-2025 Free Software Foundation, Inc.
|
2009-10-11 20:06:12 +00:00
|
|
|
|
|
|
|
This file is part of GCC.
|
|
|
|
|
|
|
|
GCC is free software; you can redistribute it and/or modify
|
|
|
|
it under the terms of the GNU General Public License as published by
|
|
|
|
the Free Software Foundation; either version 3, or (at your option)
|
|
|
|
any later version.
|
|
|
|
|
|
|
|
GCC is distributed in the hope that it will be useful,
|
|
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
GNU General Public License for more details.
|
|
|
|
|
|
|
|
Under Section 7 of GPL version 3, you are granted additional
|
|
|
|
permissions described in the GCC Runtime Library Exception, version
|
|
|
|
3.1, as published by the Free Software Foundation.
|
|
|
|
|
|
|
|
You should have received a copy of the GNU General Public License and
|
|
|
|
a copy of the GCC Runtime Library Exception along with this program;
|
|
|
|
see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
|
|
|
|
<http://www.gnu.org/licenses/>. */
|
|
|
|
|
|
|
|
/* Do code reading to identify a signal frame, and set the frame
|
|
|
|
state data appropriately. See unwind-dw2.c for the structs. */
|
|
|
|
|
|
|
|
#include <ucontext.h>
|
2010-07-13 09:10:09 +00:00
|
|
|
#include <sys/frame.h>
|
2009-10-11 20:06:12 +00:00
|
|
|
|
|
|
|
#ifdef __x86_64__
|
|
|
|
|
|
|
|
#define MD_FALLBACK_FRAME_STATE_FOR x86_64_fallback_frame_state
|
|
|
|
|
|
|
|
static _Unwind_Reason_Code
|
|
|
|
x86_64_fallback_frame_state (struct _Unwind_Context *context,
|
|
|
|
_Unwind_FrameState *fs)
|
|
|
|
{
|
|
|
|
unsigned char *pc = context->ra;
|
|
|
|
mcontext_t *mctx;
|
|
|
|
long new_cfa;
|
|
|
|
|
2010-07-13 09:10:09 +00:00
|
|
|
if (/* Solaris 10+
|
2009-10-11 20:06:12 +00:00
|
|
|
------------
|
|
|
|
<__sighndlr+0>: push %rbp
|
|
|
|
<__sighndlr+1>: mov %rsp,%rbp
|
|
|
|
<__sighndlr+4>: callq *%rcx
|
|
|
|
<__sighndlr+6>: leaveq <--- PC
|
|
|
|
<__sighndlr+7>: retq */
|
|
|
|
*(unsigned long *)(pc - 6) == 0xc3c9d1ffe5894855)
|
2010-07-13 09:10:09 +00:00
|
|
|
|
|
|
|
/* We need to move up three frames:
|
|
|
|
|
|
|
|
<signal handler> <-- context->cfa
|
|
|
|
__sighndlr
|
|
|
|
call_user_handler
|
|
|
|
sigacthandler
|
|
|
|
<kernel>
|
|
|
|
|
|
|
|
context->cfa points into the frame after the saved frame pointer and
|
|
|
|
saved pc (struct frame).
|
|
|
|
|
|
|
|
The ucontext_t structure is in the kernel frame after the signal
|
|
|
|
number and a siginfo_t *. Since the frame sizes vary even within
|
|
|
|
Solaris 10 updates, we need to walk the stack to get there. */
|
2009-10-11 20:06:12 +00:00
|
|
|
{
|
2010-07-13 09:10:09 +00:00
|
|
|
struct frame *fp = (struct frame *) context->cfa - 1;
|
|
|
|
struct handler_args {
|
|
|
|
int signo;
|
|
|
|
siginfo_t *sip;
|
|
|
|
ucontext_t ucontext;
|
|
|
|
} *handler_args;
|
|
|
|
ucontext_t *ucp;
|
|
|
|
|
|
|
|
/* Next frame: __sighndlr frame pointer. */
|
|
|
|
fp = (struct frame *) fp->fr_savfp;
|
|
|
|
/* call_user_handler frame pointer. */
|
|
|
|
fp = (struct frame *) fp->fr_savfp;
|
|
|
|
/* sigacthandler frame pointer. */
|
|
|
|
fp = (struct frame *) fp->fr_savfp;
|
|
|
|
|
|
|
|
/* The argument area precedes the struct frame. */
|
|
|
|
handler_args = (struct handler_args *) (fp + 1);
|
|
|
|
ucp = &handler_args->ucontext;
|
|
|
|
mctx = &ucp->uc_mcontext;
|
2009-10-11 20:06:12 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
return _URC_END_OF_STACK;
|
|
|
|
|
|
|
|
new_cfa = mctx->gregs[REG_RSP];
|
|
|
|
|
|
|
|
fs->regs.cfa_how = CFA_REG_OFFSET;
|
|
|
|
fs->regs.cfa_reg = 7;
|
|
|
|
fs->regs.cfa_offset = new_cfa - (long) context->cfa;
|
|
|
|
|
|
|
|
/* The SVR4 register numbering macros aren't usable in libgcc. */
|
libgcc: Decrease size of _Unwind_FrameState and even more size of cleared area in uw_frame_state_for
The following patch implements something that has Florian found as
low hanging fruit in our unwinder and has been discussed in the
https://gcc.gnu.org/wiki/cauldron2022#cauldron2022talks.inprocess_unwinding_bof
talk.
_Unwind_FrameState type seems to be (unlike the pre-GCC 3 frame_state
which has been part of ABI) private to unwind-dw2.c + unwind.inc it
includes, it is always defined on the stack of some entrypoints, initialized
by static uw_frame_state_for and the address of it is also passed to other
static functions or the static inlines handling machine dependent unwinding,
but it isn't fortunately passed to any callbacks or public functions, so I
think we can safely change it any time we want.
Florian mentioned that the structure is large even on x86_64, 384 bytes
there, starts with 328 bytes long element with frame_state_reg_info type
which then starts with an array with __LIBGCC_DWARF_FRAME_REGISTERS__ + 1
elements, each of them is 16 bytes long, on x86_64
__LIBGCC_DWARF_FRAME_REGISTERS__ is just 17 but even that is big, on say
riscv __LIBGCC_DWARF_FRAME_REGISTERS__ is I think 128, on powerpc 111,
on sh 153 etc. And, we memset to zero the whole fs variable with the
_Unwind_FrameState type at the start of the unwinding.
The reason why each element is 16 byte (on 64-bit arches) is that it
contains some pointer or pointer sized integer and then an enum (with just
7 different enumerators) + padding.
The following patch decreases it by moving the enum into a separate
array and using just one byte for each register in that second array.
We could compress it even more, say 4 bits per register, but I don't
want to uglify the code for it too much and make the accesses slower.
Furthermore, the clearing of the object can clear only thos how array
and members after it, because REG_UNSAVED enumerator (0) doesn't actually
need any pointer or pointer sized integer, it is just the other kinds
that need to have there something.
By doing this, on x86_64 the above numbers change to _Unwind_FrameState
type being now 264 bytes long, frame_state_reg_info 208 bytes and we
don't clear the first 144 bytes of the object, so the memset is 120 bytes,
so ~ 31% of the old clearing size. On riscv 64-bit assuming it has same
structure layout rules for the few types used there that would be
~ 2160 bytes of _Unwind_FrameState type before and ~ 1264 bytes after,
with the memset previously ~ 2160 bytes and after ~ 232 bytes after.
We've also talked about possibly adding a number of initially initialized
regs and initializing the rest lazily, but at least for x86_64 with
18 elements in the array that doesn't seem to be worth it anymore,
especially because return address column is 16 there and that is usually the
first thing to be touched. It might theory help with lots of registers if
they are usually untouched, but would uglify and complicate any stores to
how by having to check there for the not initialized yet cases and lazy
initialization, and similarly for all reads of how to do there if below
last initialized one, use how, otherwise imply REG_UNSAVED.
The disadvantage of the patch is that touching reg[x].loc and how[x]
now means 2 cachelines rather than one as before, and I admit beyond
bootstrap/regtest I haven't benchmarked it in any way.
2022-10-06 Jakub Jelinek <jakub@redhat.com>
* unwind-dw2.h (REG_UNSAVED, REG_SAVED_OFFSET, REG_SAVED_REG,
REG_SAVED_EXP, REG_SAVED_VAL_OFFSET, REG_SAVED_VAL_EXP,
REG_UNDEFINED): New anonymous enum, moved from inside of
struct frame_state_reg_info.
(struct frame_state_reg_info): Remove reg[].how element and the
anonymous enum there. Add how element.
* unwind-dw2.c: Include stddef.h.
(uw_frame_state_for): Don't clear first
offsetof (_Unwind_FrameState, regs.how[0]) bytes of *fs.
(execute_cfa_program, __frame_state_for, uw_update_context_1,
uw_update_context): Use fs->regs.how[X] instead of fs->regs.reg[X].how
or fs.regs.how[X] instead of fs.regs.reg[X].how.
* config/sh/linux-unwind.h (sh_fallback_frame_state): Likewise.
* config/bfin/linux-unwind.h (bfin_fallback_frame_state): Likewise.
* config/pa/linux-unwind.h (pa32_fallback_frame_state): Likewise.
* config/pa/hpux-unwind.h (UPDATE_FS_FOR_SAR, UPDATE_FS_FOR_GR,
UPDATE_FS_FOR_FR, UPDATE_FS_FOR_PC, pa_fallback_frame_state):
Likewise.
* config/alpha/vms-unwind.h (alpha_vms_fallback_frame_state):
Likewise.
* config/alpha/linux-unwind.h (alpha_fallback_frame_state): Likewise.
* config/arc/linux-unwind.h (arc_fallback_frame_state,
arc_frob_update_context): Likewise.
* config/riscv/linux-unwind.h (riscv_fallback_frame_state): Likewise.
* config/nios2/linux-unwind.h (NIOS2_REG): Likewise.
* config/nds32/linux-unwind.h (NDS32_PUT_FS_REG): Likewise.
* config/s390/tpf-unwind.h (s390_fallback_frame_state): Likewise.
* config/s390/linux-unwind.h (s390_fallback_frame_state): Likewise.
* config/sparc/sol2-unwind.h (sparc64_frob_update_context,
MD_FALLBACK_FRAME_STATE_FOR): Likewise.
* config/sparc/linux-unwind.h (sparc64_fallback_frame_state,
sparc64_frob_update_context, sparc_fallback_frame_state): Likewise.
* config/i386/sol2-unwind.h (x86_64_fallback_frame_state,
x86_fallback_frame_state): Likewise.
* config/i386/w32-unwind.h (i386_w32_fallback_frame_state): Likewise.
* config/i386/linux-unwind.h (x86_64_fallback_frame_state,
x86_fallback_frame_state): Likewise.
* config/i386/freebsd-unwind.h (x86_64_freebsd_fallback_frame_state):
Likewise.
* config/i386/dragonfly-unwind.h
(x86_64_dragonfly_fallback_frame_state): Likewise.
* config/i386/gnu-unwind.h (x86_gnu_fallback_frame_state): Likewise.
* config/csky/linux-unwind.h (csky_fallback_frame_state): Likewise.
* config/aarch64/linux-unwind.h (aarch64_fallback_frame_state):
Likewise.
* config/aarch64/freebsd-unwind.h
(aarch64_freebsd_fallback_frame_state): Likewise.
* config/aarch64/aarch64-unwind.h (aarch64_frob_update_context):
Likewise.
* config/or1k/linux-unwind.h (or1k_fallback_frame_state): Likewise.
* config/mips/linux-unwind.h (mips_fallback_frame_state): Likewise.
* config/loongarch/linux-unwind.h (loongarch_fallback_frame_state):
Likewise.
* config/m68k/linux-unwind.h (m68k_fallback_frame_state): Likewise.
* config/xtensa/linux-unwind.h (xtensa_fallback_frame_state):
Likewise.
* config/rs6000/darwin-fallback.c (set_offset): Likewise.
* config/rs6000/aix-unwind.h (MD_FROB_UPDATE_CONTEXT): Likewise.
* config/rs6000/linux-unwind.h (ppc_fallback_frame_state): Likewise.
* config/rs6000/freebsd-unwind.h (frob_update_context): Likewise.
2022-10-06 11:04:52 +02:00
|
|
|
fs->regs.how[0] = REG_SAVED_OFFSET;
|
2009-10-11 20:06:12 +00:00
|
|
|
fs->regs.reg[0].loc.offset = (long)&mctx->gregs[REG_RAX] - new_cfa;
|
libgcc: Decrease size of _Unwind_FrameState and even more size of cleared area in uw_frame_state_for
The following patch implements something that has Florian found as
low hanging fruit in our unwinder and has been discussed in the
https://gcc.gnu.org/wiki/cauldron2022#cauldron2022talks.inprocess_unwinding_bof
talk.
_Unwind_FrameState type seems to be (unlike the pre-GCC 3 frame_state
which has been part of ABI) private to unwind-dw2.c + unwind.inc it
includes, it is always defined on the stack of some entrypoints, initialized
by static uw_frame_state_for and the address of it is also passed to other
static functions or the static inlines handling machine dependent unwinding,
but it isn't fortunately passed to any callbacks or public functions, so I
think we can safely change it any time we want.
Florian mentioned that the structure is large even on x86_64, 384 bytes
there, starts with 328 bytes long element with frame_state_reg_info type
which then starts with an array with __LIBGCC_DWARF_FRAME_REGISTERS__ + 1
elements, each of them is 16 bytes long, on x86_64
__LIBGCC_DWARF_FRAME_REGISTERS__ is just 17 but even that is big, on say
riscv __LIBGCC_DWARF_FRAME_REGISTERS__ is I think 128, on powerpc 111,
on sh 153 etc. And, we memset to zero the whole fs variable with the
_Unwind_FrameState type at the start of the unwinding.
The reason why each element is 16 byte (on 64-bit arches) is that it
contains some pointer or pointer sized integer and then an enum (with just
7 different enumerators) + padding.
The following patch decreases it by moving the enum into a separate
array and using just one byte for each register in that second array.
We could compress it even more, say 4 bits per register, but I don't
want to uglify the code for it too much and make the accesses slower.
Furthermore, the clearing of the object can clear only thos how array
and members after it, because REG_UNSAVED enumerator (0) doesn't actually
need any pointer or pointer sized integer, it is just the other kinds
that need to have there something.
By doing this, on x86_64 the above numbers change to _Unwind_FrameState
type being now 264 bytes long, frame_state_reg_info 208 bytes and we
don't clear the first 144 bytes of the object, so the memset is 120 bytes,
so ~ 31% of the old clearing size. On riscv 64-bit assuming it has same
structure layout rules for the few types used there that would be
~ 2160 bytes of _Unwind_FrameState type before and ~ 1264 bytes after,
with the memset previously ~ 2160 bytes and after ~ 232 bytes after.
We've also talked about possibly adding a number of initially initialized
regs and initializing the rest lazily, but at least for x86_64 with
18 elements in the array that doesn't seem to be worth it anymore,
especially because return address column is 16 there and that is usually the
first thing to be touched. It might theory help with lots of registers if
they are usually untouched, but would uglify and complicate any stores to
how by having to check there for the not initialized yet cases and lazy
initialization, and similarly for all reads of how to do there if below
last initialized one, use how, otherwise imply REG_UNSAVED.
The disadvantage of the patch is that touching reg[x].loc and how[x]
now means 2 cachelines rather than one as before, and I admit beyond
bootstrap/regtest I haven't benchmarked it in any way.
2022-10-06 Jakub Jelinek <jakub@redhat.com>
* unwind-dw2.h (REG_UNSAVED, REG_SAVED_OFFSET, REG_SAVED_REG,
REG_SAVED_EXP, REG_SAVED_VAL_OFFSET, REG_SAVED_VAL_EXP,
REG_UNDEFINED): New anonymous enum, moved from inside of
struct frame_state_reg_info.
(struct frame_state_reg_info): Remove reg[].how element and the
anonymous enum there. Add how element.
* unwind-dw2.c: Include stddef.h.
(uw_frame_state_for): Don't clear first
offsetof (_Unwind_FrameState, regs.how[0]) bytes of *fs.
(execute_cfa_program, __frame_state_for, uw_update_context_1,
uw_update_context): Use fs->regs.how[X] instead of fs->regs.reg[X].how
or fs.regs.how[X] instead of fs.regs.reg[X].how.
* config/sh/linux-unwind.h (sh_fallback_frame_state): Likewise.
* config/bfin/linux-unwind.h (bfin_fallback_frame_state): Likewise.
* config/pa/linux-unwind.h (pa32_fallback_frame_state): Likewise.
* config/pa/hpux-unwind.h (UPDATE_FS_FOR_SAR, UPDATE_FS_FOR_GR,
UPDATE_FS_FOR_FR, UPDATE_FS_FOR_PC, pa_fallback_frame_state):
Likewise.
* config/alpha/vms-unwind.h (alpha_vms_fallback_frame_state):
Likewise.
* config/alpha/linux-unwind.h (alpha_fallback_frame_state): Likewise.
* config/arc/linux-unwind.h (arc_fallback_frame_state,
arc_frob_update_context): Likewise.
* config/riscv/linux-unwind.h (riscv_fallback_frame_state): Likewise.
* config/nios2/linux-unwind.h (NIOS2_REG): Likewise.
* config/nds32/linux-unwind.h (NDS32_PUT_FS_REG): Likewise.
* config/s390/tpf-unwind.h (s390_fallback_frame_state): Likewise.
* config/s390/linux-unwind.h (s390_fallback_frame_state): Likewise.
* config/sparc/sol2-unwind.h (sparc64_frob_update_context,
MD_FALLBACK_FRAME_STATE_FOR): Likewise.
* config/sparc/linux-unwind.h (sparc64_fallback_frame_state,
sparc64_frob_update_context, sparc_fallback_frame_state): Likewise.
* config/i386/sol2-unwind.h (x86_64_fallback_frame_state,
x86_fallback_frame_state): Likewise.
* config/i386/w32-unwind.h (i386_w32_fallback_frame_state): Likewise.
* config/i386/linux-unwind.h (x86_64_fallback_frame_state,
x86_fallback_frame_state): Likewise.
* config/i386/freebsd-unwind.h (x86_64_freebsd_fallback_frame_state):
Likewise.
* config/i386/dragonfly-unwind.h
(x86_64_dragonfly_fallback_frame_state): Likewise.
* config/i386/gnu-unwind.h (x86_gnu_fallback_frame_state): Likewise.
* config/csky/linux-unwind.h (csky_fallback_frame_state): Likewise.
* config/aarch64/linux-unwind.h (aarch64_fallback_frame_state):
Likewise.
* config/aarch64/freebsd-unwind.h
(aarch64_freebsd_fallback_frame_state): Likewise.
* config/aarch64/aarch64-unwind.h (aarch64_frob_update_context):
Likewise.
* config/or1k/linux-unwind.h (or1k_fallback_frame_state): Likewise.
* config/mips/linux-unwind.h (mips_fallback_frame_state): Likewise.
* config/loongarch/linux-unwind.h (loongarch_fallback_frame_state):
Likewise.
* config/m68k/linux-unwind.h (m68k_fallback_frame_state): Likewise.
* config/xtensa/linux-unwind.h (xtensa_fallback_frame_state):
Likewise.
* config/rs6000/darwin-fallback.c (set_offset): Likewise.
* config/rs6000/aix-unwind.h (MD_FROB_UPDATE_CONTEXT): Likewise.
* config/rs6000/linux-unwind.h (ppc_fallback_frame_state): Likewise.
* config/rs6000/freebsd-unwind.h (frob_update_context): Likewise.
2022-10-06 11:04:52 +02:00
|
|
|
fs->regs.how[1] = REG_SAVED_OFFSET;
|
2009-10-11 20:06:12 +00:00
|
|
|
fs->regs.reg[1].loc.offset = (long)&mctx->gregs[REG_RDX] - new_cfa;
|
libgcc: Decrease size of _Unwind_FrameState and even more size of cleared area in uw_frame_state_for
The following patch implements something that has Florian found as
low hanging fruit in our unwinder and has been discussed in the
https://gcc.gnu.org/wiki/cauldron2022#cauldron2022talks.inprocess_unwinding_bof
talk.
_Unwind_FrameState type seems to be (unlike the pre-GCC 3 frame_state
which has been part of ABI) private to unwind-dw2.c + unwind.inc it
includes, it is always defined on the stack of some entrypoints, initialized
by static uw_frame_state_for and the address of it is also passed to other
static functions or the static inlines handling machine dependent unwinding,
but it isn't fortunately passed to any callbacks or public functions, so I
think we can safely change it any time we want.
Florian mentioned that the structure is large even on x86_64, 384 bytes
there, starts with 328 bytes long element with frame_state_reg_info type
which then starts with an array with __LIBGCC_DWARF_FRAME_REGISTERS__ + 1
elements, each of them is 16 bytes long, on x86_64
__LIBGCC_DWARF_FRAME_REGISTERS__ is just 17 but even that is big, on say
riscv __LIBGCC_DWARF_FRAME_REGISTERS__ is I think 128, on powerpc 111,
on sh 153 etc. And, we memset to zero the whole fs variable with the
_Unwind_FrameState type at the start of the unwinding.
The reason why each element is 16 byte (on 64-bit arches) is that it
contains some pointer or pointer sized integer and then an enum (with just
7 different enumerators) + padding.
The following patch decreases it by moving the enum into a separate
array and using just one byte for each register in that second array.
We could compress it even more, say 4 bits per register, but I don't
want to uglify the code for it too much and make the accesses slower.
Furthermore, the clearing of the object can clear only thos how array
and members after it, because REG_UNSAVED enumerator (0) doesn't actually
need any pointer or pointer sized integer, it is just the other kinds
that need to have there something.
By doing this, on x86_64 the above numbers change to _Unwind_FrameState
type being now 264 bytes long, frame_state_reg_info 208 bytes and we
don't clear the first 144 bytes of the object, so the memset is 120 bytes,
so ~ 31% of the old clearing size. On riscv 64-bit assuming it has same
structure layout rules for the few types used there that would be
~ 2160 bytes of _Unwind_FrameState type before and ~ 1264 bytes after,
with the memset previously ~ 2160 bytes and after ~ 232 bytes after.
We've also talked about possibly adding a number of initially initialized
regs and initializing the rest lazily, but at least for x86_64 with
18 elements in the array that doesn't seem to be worth it anymore,
especially because return address column is 16 there and that is usually the
first thing to be touched. It might theory help with lots of registers if
they are usually untouched, but would uglify and complicate any stores to
how by having to check there for the not initialized yet cases and lazy
initialization, and similarly for all reads of how to do there if below
last initialized one, use how, otherwise imply REG_UNSAVED.
The disadvantage of the patch is that touching reg[x].loc and how[x]
now means 2 cachelines rather than one as before, and I admit beyond
bootstrap/regtest I haven't benchmarked it in any way.
2022-10-06 Jakub Jelinek <jakub@redhat.com>
* unwind-dw2.h (REG_UNSAVED, REG_SAVED_OFFSET, REG_SAVED_REG,
REG_SAVED_EXP, REG_SAVED_VAL_OFFSET, REG_SAVED_VAL_EXP,
REG_UNDEFINED): New anonymous enum, moved from inside of
struct frame_state_reg_info.
(struct frame_state_reg_info): Remove reg[].how element and the
anonymous enum there. Add how element.
* unwind-dw2.c: Include stddef.h.
(uw_frame_state_for): Don't clear first
offsetof (_Unwind_FrameState, regs.how[0]) bytes of *fs.
(execute_cfa_program, __frame_state_for, uw_update_context_1,
uw_update_context): Use fs->regs.how[X] instead of fs->regs.reg[X].how
or fs.regs.how[X] instead of fs.regs.reg[X].how.
* config/sh/linux-unwind.h (sh_fallback_frame_state): Likewise.
* config/bfin/linux-unwind.h (bfin_fallback_frame_state): Likewise.
* config/pa/linux-unwind.h (pa32_fallback_frame_state): Likewise.
* config/pa/hpux-unwind.h (UPDATE_FS_FOR_SAR, UPDATE_FS_FOR_GR,
UPDATE_FS_FOR_FR, UPDATE_FS_FOR_PC, pa_fallback_frame_state):
Likewise.
* config/alpha/vms-unwind.h (alpha_vms_fallback_frame_state):
Likewise.
* config/alpha/linux-unwind.h (alpha_fallback_frame_state): Likewise.
* config/arc/linux-unwind.h (arc_fallback_frame_state,
arc_frob_update_context): Likewise.
* config/riscv/linux-unwind.h (riscv_fallback_frame_state): Likewise.
* config/nios2/linux-unwind.h (NIOS2_REG): Likewise.
* config/nds32/linux-unwind.h (NDS32_PUT_FS_REG): Likewise.
* config/s390/tpf-unwind.h (s390_fallback_frame_state): Likewise.
* config/s390/linux-unwind.h (s390_fallback_frame_state): Likewise.
* config/sparc/sol2-unwind.h (sparc64_frob_update_context,
MD_FALLBACK_FRAME_STATE_FOR): Likewise.
* config/sparc/linux-unwind.h (sparc64_fallback_frame_state,
sparc64_frob_update_context, sparc_fallback_frame_state): Likewise.
* config/i386/sol2-unwind.h (x86_64_fallback_frame_state,
x86_fallback_frame_state): Likewise.
* config/i386/w32-unwind.h (i386_w32_fallback_frame_state): Likewise.
* config/i386/linux-unwind.h (x86_64_fallback_frame_state,
x86_fallback_frame_state): Likewise.
* config/i386/freebsd-unwind.h (x86_64_freebsd_fallback_frame_state):
Likewise.
* config/i386/dragonfly-unwind.h
(x86_64_dragonfly_fallback_frame_state): Likewise.
* config/i386/gnu-unwind.h (x86_gnu_fallback_frame_state): Likewise.
* config/csky/linux-unwind.h (csky_fallback_frame_state): Likewise.
* config/aarch64/linux-unwind.h (aarch64_fallback_frame_state):
Likewise.
* config/aarch64/freebsd-unwind.h
(aarch64_freebsd_fallback_frame_state): Likewise.
* config/aarch64/aarch64-unwind.h (aarch64_frob_update_context):
Likewise.
* config/or1k/linux-unwind.h (or1k_fallback_frame_state): Likewise.
* config/mips/linux-unwind.h (mips_fallback_frame_state): Likewise.
* config/loongarch/linux-unwind.h (loongarch_fallback_frame_state):
Likewise.
* config/m68k/linux-unwind.h (m68k_fallback_frame_state): Likewise.
* config/xtensa/linux-unwind.h (xtensa_fallback_frame_state):
Likewise.
* config/rs6000/darwin-fallback.c (set_offset): Likewise.
* config/rs6000/aix-unwind.h (MD_FROB_UPDATE_CONTEXT): Likewise.
* config/rs6000/linux-unwind.h (ppc_fallback_frame_state): Likewise.
* config/rs6000/freebsd-unwind.h (frob_update_context): Likewise.
2022-10-06 11:04:52 +02:00
|
|
|
fs->regs.how[2] = REG_SAVED_OFFSET;
|
2009-10-11 20:06:12 +00:00
|
|
|
fs->regs.reg[2].loc.offset = (long)&mctx->gregs[REG_RCX] - new_cfa;
|
libgcc: Decrease size of _Unwind_FrameState and even more size of cleared area in uw_frame_state_for
The following patch implements something that has Florian found as
low hanging fruit in our unwinder and has been discussed in the
https://gcc.gnu.org/wiki/cauldron2022#cauldron2022talks.inprocess_unwinding_bof
talk.
_Unwind_FrameState type seems to be (unlike the pre-GCC 3 frame_state
which has been part of ABI) private to unwind-dw2.c + unwind.inc it
includes, it is always defined on the stack of some entrypoints, initialized
by static uw_frame_state_for and the address of it is also passed to other
static functions or the static inlines handling machine dependent unwinding,
but it isn't fortunately passed to any callbacks or public functions, so I
think we can safely change it any time we want.
Florian mentioned that the structure is large even on x86_64, 384 bytes
there, starts with 328 bytes long element with frame_state_reg_info type
which then starts with an array with __LIBGCC_DWARF_FRAME_REGISTERS__ + 1
elements, each of them is 16 bytes long, on x86_64
__LIBGCC_DWARF_FRAME_REGISTERS__ is just 17 but even that is big, on say
riscv __LIBGCC_DWARF_FRAME_REGISTERS__ is I think 128, on powerpc 111,
on sh 153 etc. And, we memset to zero the whole fs variable with the
_Unwind_FrameState type at the start of the unwinding.
The reason why each element is 16 byte (on 64-bit arches) is that it
contains some pointer or pointer sized integer and then an enum (with just
7 different enumerators) + padding.
The following patch decreases it by moving the enum into a separate
array and using just one byte for each register in that second array.
We could compress it even more, say 4 bits per register, but I don't
want to uglify the code for it too much and make the accesses slower.
Furthermore, the clearing of the object can clear only thos how array
and members after it, because REG_UNSAVED enumerator (0) doesn't actually
need any pointer or pointer sized integer, it is just the other kinds
that need to have there something.
By doing this, on x86_64 the above numbers change to _Unwind_FrameState
type being now 264 bytes long, frame_state_reg_info 208 bytes and we
don't clear the first 144 bytes of the object, so the memset is 120 bytes,
so ~ 31% of the old clearing size. On riscv 64-bit assuming it has same
structure layout rules for the few types used there that would be
~ 2160 bytes of _Unwind_FrameState type before and ~ 1264 bytes after,
with the memset previously ~ 2160 bytes and after ~ 232 bytes after.
We've also talked about possibly adding a number of initially initialized
regs and initializing the rest lazily, but at least for x86_64 with
18 elements in the array that doesn't seem to be worth it anymore,
especially because return address column is 16 there and that is usually the
first thing to be touched. It might theory help with lots of registers if
they are usually untouched, but would uglify and complicate any stores to
how by having to check there for the not initialized yet cases and lazy
initialization, and similarly for all reads of how to do there if below
last initialized one, use how, otherwise imply REG_UNSAVED.
The disadvantage of the patch is that touching reg[x].loc and how[x]
now means 2 cachelines rather than one as before, and I admit beyond
bootstrap/regtest I haven't benchmarked it in any way.
2022-10-06 Jakub Jelinek <jakub@redhat.com>
* unwind-dw2.h (REG_UNSAVED, REG_SAVED_OFFSET, REG_SAVED_REG,
REG_SAVED_EXP, REG_SAVED_VAL_OFFSET, REG_SAVED_VAL_EXP,
REG_UNDEFINED): New anonymous enum, moved from inside of
struct frame_state_reg_info.
(struct frame_state_reg_info): Remove reg[].how element and the
anonymous enum there. Add how element.
* unwind-dw2.c: Include stddef.h.
(uw_frame_state_for): Don't clear first
offsetof (_Unwind_FrameState, regs.how[0]) bytes of *fs.
(execute_cfa_program, __frame_state_for, uw_update_context_1,
uw_update_context): Use fs->regs.how[X] instead of fs->regs.reg[X].how
or fs.regs.how[X] instead of fs.regs.reg[X].how.
* config/sh/linux-unwind.h (sh_fallback_frame_state): Likewise.
* config/bfin/linux-unwind.h (bfin_fallback_frame_state): Likewise.
* config/pa/linux-unwind.h (pa32_fallback_frame_state): Likewise.
* config/pa/hpux-unwind.h (UPDATE_FS_FOR_SAR, UPDATE_FS_FOR_GR,
UPDATE_FS_FOR_FR, UPDATE_FS_FOR_PC, pa_fallback_frame_state):
Likewise.
* config/alpha/vms-unwind.h (alpha_vms_fallback_frame_state):
Likewise.
* config/alpha/linux-unwind.h (alpha_fallback_frame_state): Likewise.
* config/arc/linux-unwind.h (arc_fallback_frame_state,
arc_frob_update_context): Likewise.
* config/riscv/linux-unwind.h (riscv_fallback_frame_state): Likewise.
* config/nios2/linux-unwind.h (NIOS2_REG): Likewise.
* config/nds32/linux-unwind.h (NDS32_PUT_FS_REG): Likewise.
* config/s390/tpf-unwind.h (s390_fallback_frame_state): Likewise.
* config/s390/linux-unwind.h (s390_fallback_frame_state): Likewise.
* config/sparc/sol2-unwind.h (sparc64_frob_update_context,
MD_FALLBACK_FRAME_STATE_FOR): Likewise.
* config/sparc/linux-unwind.h (sparc64_fallback_frame_state,
sparc64_frob_update_context, sparc_fallback_frame_state): Likewise.
* config/i386/sol2-unwind.h (x86_64_fallback_frame_state,
x86_fallback_frame_state): Likewise.
* config/i386/w32-unwind.h (i386_w32_fallback_frame_state): Likewise.
* config/i386/linux-unwind.h (x86_64_fallback_frame_state,
x86_fallback_frame_state): Likewise.
* config/i386/freebsd-unwind.h (x86_64_freebsd_fallback_frame_state):
Likewise.
* config/i386/dragonfly-unwind.h
(x86_64_dragonfly_fallback_frame_state): Likewise.
* config/i386/gnu-unwind.h (x86_gnu_fallback_frame_state): Likewise.
* config/csky/linux-unwind.h (csky_fallback_frame_state): Likewise.
* config/aarch64/linux-unwind.h (aarch64_fallback_frame_state):
Likewise.
* config/aarch64/freebsd-unwind.h
(aarch64_freebsd_fallback_frame_state): Likewise.
* config/aarch64/aarch64-unwind.h (aarch64_frob_update_context):
Likewise.
* config/or1k/linux-unwind.h (or1k_fallback_frame_state): Likewise.
* config/mips/linux-unwind.h (mips_fallback_frame_state): Likewise.
* config/loongarch/linux-unwind.h (loongarch_fallback_frame_state):
Likewise.
* config/m68k/linux-unwind.h (m68k_fallback_frame_state): Likewise.
* config/xtensa/linux-unwind.h (xtensa_fallback_frame_state):
Likewise.
* config/rs6000/darwin-fallback.c (set_offset): Likewise.
* config/rs6000/aix-unwind.h (MD_FROB_UPDATE_CONTEXT): Likewise.
* config/rs6000/linux-unwind.h (ppc_fallback_frame_state): Likewise.
* config/rs6000/freebsd-unwind.h (frob_update_context): Likewise.
2022-10-06 11:04:52 +02:00
|
|
|
fs->regs.how[3] = REG_SAVED_OFFSET;
|
2009-10-11 20:06:12 +00:00
|
|
|
fs->regs.reg[3].loc.offset = (long)&mctx->gregs[REG_RBX] - new_cfa;
|
libgcc: Decrease size of _Unwind_FrameState and even more size of cleared area in uw_frame_state_for
The following patch implements something that has Florian found as
low hanging fruit in our unwinder and has been discussed in the
https://gcc.gnu.org/wiki/cauldron2022#cauldron2022talks.inprocess_unwinding_bof
talk.
_Unwind_FrameState type seems to be (unlike the pre-GCC 3 frame_state
which has been part of ABI) private to unwind-dw2.c + unwind.inc it
includes, it is always defined on the stack of some entrypoints, initialized
by static uw_frame_state_for and the address of it is also passed to other
static functions or the static inlines handling machine dependent unwinding,
but it isn't fortunately passed to any callbacks or public functions, so I
think we can safely change it any time we want.
Florian mentioned that the structure is large even on x86_64, 384 bytes
there, starts with 328 bytes long element with frame_state_reg_info type
which then starts with an array with __LIBGCC_DWARF_FRAME_REGISTERS__ + 1
elements, each of them is 16 bytes long, on x86_64
__LIBGCC_DWARF_FRAME_REGISTERS__ is just 17 but even that is big, on say
riscv __LIBGCC_DWARF_FRAME_REGISTERS__ is I think 128, on powerpc 111,
on sh 153 etc. And, we memset to zero the whole fs variable with the
_Unwind_FrameState type at the start of the unwinding.
The reason why each element is 16 byte (on 64-bit arches) is that it
contains some pointer or pointer sized integer and then an enum (with just
7 different enumerators) + padding.
The following patch decreases it by moving the enum into a separate
array and using just one byte for each register in that second array.
We could compress it even more, say 4 bits per register, but I don't
want to uglify the code for it too much and make the accesses slower.
Furthermore, the clearing of the object can clear only thos how array
and members after it, because REG_UNSAVED enumerator (0) doesn't actually
need any pointer or pointer sized integer, it is just the other kinds
that need to have there something.
By doing this, on x86_64 the above numbers change to _Unwind_FrameState
type being now 264 bytes long, frame_state_reg_info 208 bytes and we
don't clear the first 144 bytes of the object, so the memset is 120 bytes,
so ~ 31% of the old clearing size. On riscv 64-bit assuming it has same
structure layout rules for the few types used there that would be
~ 2160 bytes of _Unwind_FrameState type before and ~ 1264 bytes after,
with the memset previously ~ 2160 bytes and after ~ 232 bytes after.
We've also talked about possibly adding a number of initially initialized
regs and initializing the rest lazily, but at least for x86_64 with
18 elements in the array that doesn't seem to be worth it anymore,
especially because return address column is 16 there and that is usually the
first thing to be touched. It might theory help with lots of registers if
they are usually untouched, but would uglify and complicate any stores to
how by having to check there for the not initialized yet cases and lazy
initialization, and similarly for all reads of how to do there if below
last initialized one, use how, otherwise imply REG_UNSAVED.
The disadvantage of the patch is that touching reg[x].loc and how[x]
now means 2 cachelines rather than one as before, and I admit beyond
bootstrap/regtest I haven't benchmarked it in any way.
2022-10-06 Jakub Jelinek <jakub@redhat.com>
* unwind-dw2.h (REG_UNSAVED, REG_SAVED_OFFSET, REG_SAVED_REG,
REG_SAVED_EXP, REG_SAVED_VAL_OFFSET, REG_SAVED_VAL_EXP,
REG_UNDEFINED): New anonymous enum, moved from inside of
struct frame_state_reg_info.
(struct frame_state_reg_info): Remove reg[].how element and the
anonymous enum there. Add how element.
* unwind-dw2.c: Include stddef.h.
(uw_frame_state_for): Don't clear first
offsetof (_Unwind_FrameState, regs.how[0]) bytes of *fs.
(execute_cfa_program, __frame_state_for, uw_update_context_1,
uw_update_context): Use fs->regs.how[X] instead of fs->regs.reg[X].how
or fs.regs.how[X] instead of fs.regs.reg[X].how.
* config/sh/linux-unwind.h (sh_fallback_frame_state): Likewise.
* config/bfin/linux-unwind.h (bfin_fallback_frame_state): Likewise.
* config/pa/linux-unwind.h (pa32_fallback_frame_state): Likewise.
* config/pa/hpux-unwind.h (UPDATE_FS_FOR_SAR, UPDATE_FS_FOR_GR,
UPDATE_FS_FOR_FR, UPDATE_FS_FOR_PC, pa_fallback_frame_state):
Likewise.
* config/alpha/vms-unwind.h (alpha_vms_fallback_frame_state):
Likewise.
* config/alpha/linux-unwind.h (alpha_fallback_frame_state): Likewise.
* config/arc/linux-unwind.h (arc_fallback_frame_state,
arc_frob_update_context): Likewise.
* config/riscv/linux-unwind.h (riscv_fallback_frame_state): Likewise.
* config/nios2/linux-unwind.h (NIOS2_REG): Likewise.
* config/nds32/linux-unwind.h (NDS32_PUT_FS_REG): Likewise.
* config/s390/tpf-unwind.h (s390_fallback_frame_state): Likewise.
* config/s390/linux-unwind.h (s390_fallback_frame_state): Likewise.
* config/sparc/sol2-unwind.h (sparc64_frob_update_context,
MD_FALLBACK_FRAME_STATE_FOR): Likewise.
* config/sparc/linux-unwind.h (sparc64_fallback_frame_state,
sparc64_frob_update_context, sparc_fallback_frame_state): Likewise.
* config/i386/sol2-unwind.h (x86_64_fallback_frame_state,
x86_fallback_frame_state): Likewise.
* config/i386/w32-unwind.h (i386_w32_fallback_frame_state): Likewise.
* config/i386/linux-unwind.h (x86_64_fallback_frame_state,
x86_fallback_frame_state): Likewise.
* config/i386/freebsd-unwind.h (x86_64_freebsd_fallback_frame_state):
Likewise.
* config/i386/dragonfly-unwind.h
(x86_64_dragonfly_fallback_frame_state): Likewise.
* config/i386/gnu-unwind.h (x86_gnu_fallback_frame_state): Likewise.
* config/csky/linux-unwind.h (csky_fallback_frame_state): Likewise.
* config/aarch64/linux-unwind.h (aarch64_fallback_frame_state):
Likewise.
* config/aarch64/freebsd-unwind.h
(aarch64_freebsd_fallback_frame_state): Likewise.
* config/aarch64/aarch64-unwind.h (aarch64_frob_update_context):
Likewise.
* config/or1k/linux-unwind.h (or1k_fallback_frame_state): Likewise.
* config/mips/linux-unwind.h (mips_fallback_frame_state): Likewise.
* config/loongarch/linux-unwind.h (loongarch_fallback_frame_state):
Likewise.
* config/m68k/linux-unwind.h (m68k_fallback_frame_state): Likewise.
* config/xtensa/linux-unwind.h (xtensa_fallback_frame_state):
Likewise.
* config/rs6000/darwin-fallback.c (set_offset): Likewise.
* config/rs6000/aix-unwind.h (MD_FROB_UPDATE_CONTEXT): Likewise.
* config/rs6000/linux-unwind.h (ppc_fallback_frame_state): Likewise.
* config/rs6000/freebsd-unwind.h (frob_update_context): Likewise.
2022-10-06 11:04:52 +02:00
|
|
|
fs->regs.how[4] = REG_SAVED_OFFSET;
|
2009-10-11 20:06:12 +00:00
|
|
|
fs->regs.reg[4].loc.offset = (long)&mctx->gregs[REG_RSI] - new_cfa;
|
libgcc: Decrease size of _Unwind_FrameState and even more size of cleared area in uw_frame_state_for
The following patch implements something that has Florian found as
low hanging fruit in our unwinder and has been discussed in the
https://gcc.gnu.org/wiki/cauldron2022#cauldron2022talks.inprocess_unwinding_bof
talk.
_Unwind_FrameState type seems to be (unlike the pre-GCC 3 frame_state
which has been part of ABI) private to unwind-dw2.c + unwind.inc it
includes, it is always defined on the stack of some entrypoints, initialized
by static uw_frame_state_for and the address of it is also passed to other
static functions or the static inlines handling machine dependent unwinding,
but it isn't fortunately passed to any callbacks or public functions, so I
think we can safely change it any time we want.
Florian mentioned that the structure is large even on x86_64, 384 bytes
there, starts with 328 bytes long element with frame_state_reg_info type
which then starts with an array with __LIBGCC_DWARF_FRAME_REGISTERS__ + 1
elements, each of them is 16 bytes long, on x86_64
__LIBGCC_DWARF_FRAME_REGISTERS__ is just 17 but even that is big, on say
riscv __LIBGCC_DWARF_FRAME_REGISTERS__ is I think 128, on powerpc 111,
on sh 153 etc. And, we memset to zero the whole fs variable with the
_Unwind_FrameState type at the start of the unwinding.
The reason why each element is 16 byte (on 64-bit arches) is that it
contains some pointer or pointer sized integer and then an enum (with just
7 different enumerators) + padding.
The following patch decreases it by moving the enum into a separate
array and using just one byte for each register in that second array.
We could compress it even more, say 4 bits per register, but I don't
want to uglify the code for it too much and make the accesses slower.
Furthermore, the clearing of the object can clear only thos how array
and members after it, because REG_UNSAVED enumerator (0) doesn't actually
need any pointer or pointer sized integer, it is just the other kinds
that need to have there something.
By doing this, on x86_64 the above numbers change to _Unwind_FrameState
type being now 264 bytes long, frame_state_reg_info 208 bytes and we
don't clear the first 144 bytes of the object, so the memset is 120 bytes,
so ~ 31% of the old clearing size. On riscv 64-bit assuming it has same
structure layout rules for the few types used there that would be
~ 2160 bytes of _Unwind_FrameState type before and ~ 1264 bytes after,
with the memset previously ~ 2160 bytes and after ~ 232 bytes after.
We've also talked about possibly adding a number of initially initialized
regs and initializing the rest lazily, but at least for x86_64 with
18 elements in the array that doesn't seem to be worth it anymore,
especially because return address column is 16 there and that is usually the
first thing to be touched. It might theory help with lots of registers if
they are usually untouched, but would uglify and complicate any stores to
how by having to check there for the not initialized yet cases and lazy
initialization, and similarly for all reads of how to do there if below
last initialized one, use how, otherwise imply REG_UNSAVED.
The disadvantage of the patch is that touching reg[x].loc and how[x]
now means 2 cachelines rather than one as before, and I admit beyond
bootstrap/regtest I haven't benchmarked it in any way.
2022-10-06 Jakub Jelinek <jakub@redhat.com>
* unwind-dw2.h (REG_UNSAVED, REG_SAVED_OFFSET, REG_SAVED_REG,
REG_SAVED_EXP, REG_SAVED_VAL_OFFSET, REG_SAVED_VAL_EXP,
REG_UNDEFINED): New anonymous enum, moved from inside of
struct frame_state_reg_info.
(struct frame_state_reg_info): Remove reg[].how element and the
anonymous enum there. Add how element.
* unwind-dw2.c: Include stddef.h.
(uw_frame_state_for): Don't clear first
offsetof (_Unwind_FrameState, regs.how[0]) bytes of *fs.
(execute_cfa_program, __frame_state_for, uw_update_context_1,
uw_update_context): Use fs->regs.how[X] instead of fs->regs.reg[X].how
or fs.regs.how[X] instead of fs.regs.reg[X].how.
* config/sh/linux-unwind.h (sh_fallback_frame_state): Likewise.
* config/bfin/linux-unwind.h (bfin_fallback_frame_state): Likewise.
* config/pa/linux-unwind.h (pa32_fallback_frame_state): Likewise.
* config/pa/hpux-unwind.h (UPDATE_FS_FOR_SAR, UPDATE_FS_FOR_GR,
UPDATE_FS_FOR_FR, UPDATE_FS_FOR_PC, pa_fallback_frame_state):
Likewise.
* config/alpha/vms-unwind.h (alpha_vms_fallback_frame_state):
Likewise.
* config/alpha/linux-unwind.h (alpha_fallback_frame_state): Likewise.
* config/arc/linux-unwind.h (arc_fallback_frame_state,
arc_frob_update_context): Likewise.
* config/riscv/linux-unwind.h (riscv_fallback_frame_state): Likewise.
* config/nios2/linux-unwind.h (NIOS2_REG): Likewise.
* config/nds32/linux-unwind.h (NDS32_PUT_FS_REG): Likewise.
* config/s390/tpf-unwind.h (s390_fallback_frame_state): Likewise.
* config/s390/linux-unwind.h (s390_fallback_frame_state): Likewise.
* config/sparc/sol2-unwind.h (sparc64_frob_update_context,
MD_FALLBACK_FRAME_STATE_FOR): Likewise.
* config/sparc/linux-unwind.h (sparc64_fallback_frame_state,
sparc64_frob_update_context, sparc_fallback_frame_state): Likewise.
* config/i386/sol2-unwind.h (x86_64_fallback_frame_state,
x86_fallback_frame_state): Likewise.
* config/i386/w32-unwind.h (i386_w32_fallback_frame_state): Likewise.
* config/i386/linux-unwind.h (x86_64_fallback_frame_state,
x86_fallback_frame_state): Likewise.
* config/i386/freebsd-unwind.h (x86_64_freebsd_fallback_frame_state):
Likewise.
* config/i386/dragonfly-unwind.h
(x86_64_dragonfly_fallback_frame_state): Likewise.
* config/i386/gnu-unwind.h (x86_gnu_fallback_frame_state): Likewise.
* config/csky/linux-unwind.h (csky_fallback_frame_state): Likewise.
* config/aarch64/linux-unwind.h (aarch64_fallback_frame_state):
Likewise.
* config/aarch64/freebsd-unwind.h
(aarch64_freebsd_fallback_frame_state): Likewise.
* config/aarch64/aarch64-unwind.h (aarch64_frob_update_context):
Likewise.
* config/or1k/linux-unwind.h (or1k_fallback_frame_state): Likewise.
* config/mips/linux-unwind.h (mips_fallback_frame_state): Likewise.
* config/loongarch/linux-unwind.h (loongarch_fallback_frame_state):
Likewise.
* config/m68k/linux-unwind.h (m68k_fallback_frame_state): Likewise.
* config/xtensa/linux-unwind.h (xtensa_fallback_frame_state):
Likewise.
* config/rs6000/darwin-fallback.c (set_offset): Likewise.
* config/rs6000/aix-unwind.h (MD_FROB_UPDATE_CONTEXT): Likewise.
* config/rs6000/linux-unwind.h (ppc_fallback_frame_state): Likewise.
* config/rs6000/freebsd-unwind.h (frob_update_context): Likewise.
2022-10-06 11:04:52 +02:00
|
|
|
fs->regs.how[5] = REG_SAVED_OFFSET;
|
2009-10-11 20:06:12 +00:00
|
|
|
fs->regs.reg[5].loc.offset = (long)&mctx->gregs[REG_RDI] - new_cfa;
|
libgcc: Decrease size of _Unwind_FrameState and even more size of cleared area in uw_frame_state_for
The following patch implements something that has Florian found as
low hanging fruit in our unwinder and has been discussed in the
https://gcc.gnu.org/wiki/cauldron2022#cauldron2022talks.inprocess_unwinding_bof
talk.
_Unwind_FrameState type seems to be (unlike the pre-GCC 3 frame_state
which has been part of ABI) private to unwind-dw2.c + unwind.inc it
includes, it is always defined on the stack of some entrypoints, initialized
by static uw_frame_state_for and the address of it is also passed to other
static functions or the static inlines handling machine dependent unwinding,
but it isn't fortunately passed to any callbacks or public functions, so I
think we can safely change it any time we want.
Florian mentioned that the structure is large even on x86_64, 384 bytes
there, starts with 328 bytes long element with frame_state_reg_info type
which then starts with an array with __LIBGCC_DWARF_FRAME_REGISTERS__ + 1
elements, each of them is 16 bytes long, on x86_64
__LIBGCC_DWARF_FRAME_REGISTERS__ is just 17 but even that is big, on say
riscv __LIBGCC_DWARF_FRAME_REGISTERS__ is I think 128, on powerpc 111,
on sh 153 etc. And, we memset to zero the whole fs variable with the
_Unwind_FrameState type at the start of the unwinding.
The reason why each element is 16 byte (on 64-bit arches) is that it
contains some pointer or pointer sized integer and then an enum (with just
7 different enumerators) + padding.
The following patch decreases it by moving the enum into a separate
array and using just one byte for each register in that second array.
We could compress it even more, say 4 bits per register, but I don't
want to uglify the code for it too much and make the accesses slower.
Furthermore, the clearing of the object can clear only thos how array
and members after it, because REG_UNSAVED enumerator (0) doesn't actually
need any pointer or pointer sized integer, it is just the other kinds
that need to have there something.
By doing this, on x86_64 the above numbers change to _Unwind_FrameState
type being now 264 bytes long, frame_state_reg_info 208 bytes and we
don't clear the first 144 bytes of the object, so the memset is 120 bytes,
so ~ 31% of the old clearing size. On riscv 64-bit assuming it has same
structure layout rules for the few types used there that would be
~ 2160 bytes of _Unwind_FrameState type before and ~ 1264 bytes after,
with the memset previously ~ 2160 bytes and after ~ 232 bytes after.
We've also talked about possibly adding a number of initially initialized
regs and initializing the rest lazily, but at least for x86_64 with
18 elements in the array that doesn't seem to be worth it anymore,
especially because return address column is 16 there and that is usually the
first thing to be touched. It might theory help with lots of registers if
they are usually untouched, but would uglify and complicate any stores to
how by having to check there for the not initialized yet cases and lazy
initialization, and similarly for all reads of how to do there if below
last initialized one, use how, otherwise imply REG_UNSAVED.
The disadvantage of the patch is that touching reg[x].loc and how[x]
now means 2 cachelines rather than one as before, and I admit beyond
bootstrap/regtest I haven't benchmarked it in any way.
2022-10-06 Jakub Jelinek <jakub@redhat.com>
* unwind-dw2.h (REG_UNSAVED, REG_SAVED_OFFSET, REG_SAVED_REG,
REG_SAVED_EXP, REG_SAVED_VAL_OFFSET, REG_SAVED_VAL_EXP,
REG_UNDEFINED): New anonymous enum, moved from inside of
struct frame_state_reg_info.
(struct frame_state_reg_info): Remove reg[].how element and the
anonymous enum there. Add how element.
* unwind-dw2.c: Include stddef.h.
(uw_frame_state_for): Don't clear first
offsetof (_Unwind_FrameState, regs.how[0]) bytes of *fs.
(execute_cfa_program, __frame_state_for, uw_update_context_1,
uw_update_context): Use fs->regs.how[X] instead of fs->regs.reg[X].how
or fs.regs.how[X] instead of fs.regs.reg[X].how.
* config/sh/linux-unwind.h (sh_fallback_frame_state): Likewise.
* config/bfin/linux-unwind.h (bfin_fallback_frame_state): Likewise.
* config/pa/linux-unwind.h (pa32_fallback_frame_state): Likewise.
* config/pa/hpux-unwind.h (UPDATE_FS_FOR_SAR, UPDATE_FS_FOR_GR,
UPDATE_FS_FOR_FR, UPDATE_FS_FOR_PC, pa_fallback_frame_state):
Likewise.
* config/alpha/vms-unwind.h (alpha_vms_fallback_frame_state):
Likewise.
* config/alpha/linux-unwind.h (alpha_fallback_frame_state): Likewise.
* config/arc/linux-unwind.h (arc_fallback_frame_state,
arc_frob_update_context): Likewise.
* config/riscv/linux-unwind.h (riscv_fallback_frame_state): Likewise.
* config/nios2/linux-unwind.h (NIOS2_REG): Likewise.
* config/nds32/linux-unwind.h (NDS32_PUT_FS_REG): Likewise.
* config/s390/tpf-unwind.h (s390_fallback_frame_state): Likewise.
* config/s390/linux-unwind.h (s390_fallback_frame_state): Likewise.
* config/sparc/sol2-unwind.h (sparc64_frob_update_context,
MD_FALLBACK_FRAME_STATE_FOR): Likewise.
* config/sparc/linux-unwind.h (sparc64_fallback_frame_state,
sparc64_frob_update_context, sparc_fallback_frame_state): Likewise.
* config/i386/sol2-unwind.h (x86_64_fallback_frame_state,
x86_fallback_frame_state): Likewise.
* config/i386/w32-unwind.h (i386_w32_fallback_frame_state): Likewise.
* config/i386/linux-unwind.h (x86_64_fallback_frame_state,
x86_fallback_frame_state): Likewise.
* config/i386/freebsd-unwind.h (x86_64_freebsd_fallback_frame_state):
Likewise.
* config/i386/dragonfly-unwind.h
(x86_64_dragonfly_fallback_frame_state): Likewise.
* config/i386/gnu-unwind.h (x86_gnu_fallback_frame_state): Likewise.
* config/csky/linux-unwind.h (csky_fallback_frame_state): Likewise.
* config/aarch64/linux-unwind.h (aarch64_fallback_frame_state):
Likewise.
* config/aarch64/freebsd-unwind.h
(aarch64_freebsd_fallback_frame_state): Likewise.
* config/aarch64/aarch64-unwind.h (aarch64_frob_update_context):
Likewise.
* config/or1k/linux-unwind.h (or1k_fallback_frame_state): Likewise.
* config/mips/linux-unwind.h (mips_fallback_frame_state): Likewise.
* config/loongarch/linux-unwind.h (loongarch_fallback_frame_state):
Likewise.
* config/m68k/linux-unwind.h (m68k_fallback_frame_state): Likewise.
* config/xtensa/linux-unwind.h (xtensa_fallback_frame_state):
Likewise.
* config/rs6000/darwin-fallback.c (set_offset): Likewise.
* config/rs6000/aix-unwind.h (MD_FROB_UPDATE_CONTEXT): Likewise.
* config/rs6000/linux-unwind.h (ppc_fallback_frame_state): Likewise.
* config/rs6000/freebsd-unwind.h (frob_update_context): Likewise.
2022-10-06 11:04:52 +02:00
|
|
|
fs->regs.how[6] = REG_SAVED_OFFSET;
|
2009-10-11 20:06:12 +00:00
|
|
|
fs->regs.reg[6].loc.offset = (long)&mctx->gregs[REG_RBP] - new_cfa;
|
libgcc: Decrease size of _Unwind_FrameState and even more size of cleared area in uw_frame_state_for
The following patch implements something that has Florian found as
low hanging fruit in our unwinder and has been discussed in the
https://gcc.gnu.org/wiki/cauldron2022#cauldron2022talks.inprocess_unwinding_bof
talk.
_Unwind_FrameState type seems to be (unlike the pre-GCC 3 frame_state
which has been part of ABI) private to unwind-dw2.c + unwind.inc it
includes, it is always defined on the stack of some entrypoints, initialized
by static uw_frame_state_for and the address of it is also passed to other
static functions or the static inlines handling machine dependent unwinding,
but it isn't fortunately passed to any callbacks or public functions, so I
think we can safely change it any time we want.
Florian mentioned that the structure is large even on x86_64, 384 bytes
there, starts with 328 bytes long element with frame_state_reg_info type
which then starts with an array with __LIBGCC_DWARF_FRAME_REGISTERS__ + 1
elements, each of them is 16 bytes long, on x86_64
__LIBGCC_DWARF_FRAME_REGISTERS__ is just 17 but even that is big, on say
riscv __LIBGCC_DWARF_FRAME_REGISTERS__ is I think 128, on powerpc 111,
on sh 153 etc. And, we memset to zero the whole fs variable with the
_Unwind_FrameState type at the start of the unwinding.
The reason why each element is 16 byte (on 64-bit arches) is that it
contains some pointer or pointer sized integer and then an enum (with just
7 different enumerators) + padding.
The following patch decreases it by moving the enum into a separate
array and using just one byte for each register in that second array.
We could compress it even more, say 4 bits per register, but I don't
want to uglify the code for it too much and make the accesses slower.
Furthermore, the clearing of the object can clear only thos how array
and members after it, because REG_UNSAVED enumerator (0) doesn't actually
need any pointer or pointer sized integer, it is just the other kinds
that need to have there something.
By doing this, on x86_64 the above numbers change to _Unwind_FrameState
type being now 264 bytes long, frame_state_reg_info 208 bytes and we
don't clear the first 144 bytes of the object, so the memset is 120 bytes,
so ~ 31% of the old clearing size. On riscv 64-bit assuming it has same
structure layout rules for the few types used there that would be
~ 2160 bytes of _Unwind_FrameState type before and ~ 1264 bytes after,
with the memset previously ~ 2160 bytes and after ~ 232 bytes after.
We've also talked about possibly adding a number of initially initialized
regs and initializing the rest lazily, but at least for x86_64 with
18 elements in the array that doesn't seem to be worth it anymore,
especially because return address column is 16 there and that is usually the
first thing to be touched. It might theory help with lots of registers if
they are usually untouched, but would uglify and complicate any stores to
how by having to check there for the not initialized yet cases and lazy
initialization, and similarly for all reads of how to do there if below
last initialized one, use how, otherwise imply REG_UNSAVED.
The disadvantage of the patch is that touching reg[x].loc and how[x]
now means 2 cachelines rather than one as before, and I admit beyond
bootstrap/regtest I haven't benchmarked it in any way.
2022-10-06 Jakub Jelinek <jakub@redhat.com>
* unwind-dw2.h (REG_UNSAVED, REG_SAVED_OFFSET, REG_SAVED_REG,
REG_SAVED_EXP, REG_SAVED_VAL_OFFSET, REG_SAVED_VAL_EXP,
REG_UNDEFINED): New anonymous enum, moved from inside of
struct frame_state_reg_info.
(struct frame_state_reg_info): Remove reg[].how element and the
anonymous enum there. Add how element.
* unwind-dw2.c: Include stddef.h.
(uw_frame_state_for): Don't clear first
offsetof (_Unwind_FrameState, regs.how[0]) bytes of *fs.
(execute_cfa_program, __frame_state_for, uw_update_context_1,
uw_update_context): Use fs->regs.how[X] instead of fs->regs.reg[X].how
or fs.regs.how[X] instead of fs.regs.reg[X].how.
* config/sh/linux-unwind.h (sh_fallback_frame_state): Likewise.
* config/bfin/linux-unwind.h (bfin_fallback_frame_state): Likewise.
* config/pa/linux-unwind.h (pa32_fallback_frame_state): Likewise.
* config/pa/hpux-unwind.h (UPDATE_FS_FOR_SAR, UPDATE_FS_FOR_GR,
UPDATE_FS_FOR_FR, UPDATE_FS_FOR_PC, pa_fallback_frame_state):
Likewise.
* config/alpha/vms-unwind.h (alpha_vms_fallback_frame_state):
Likewise.
* config/alpha/linux-unwind.h (alpha_fallback_frame_state): Likewise.
* config/arc/linux-unwind.h (arc_fallback_frame_state,
arc_frob_update_context): Likewise.
* config/riscv/linux-unwind.h (riscv_fallback_frame_state): Likewise.
* config/nios2/linux-unwind.h (NIOS2_REG): Likewise.
* config/nds32/linux-unwind.h (NDS32_PUT_FS_REG): Likewise.
* config/s390/tpf-unwind.h (s390_fallback_frame_state): Likewise.
* config/s390/linux-unwind.h (s390_fallback_frame_state): Likewise.
* config/sparc/sol2-unwind.h (sparc64_frob_update_context,
MD_FALLBACK_FRAME_STATE_FOR): Likewise.
* config/sparc/linux-unwind.h (sparc64_fallback_frame_state,
sparc64_frob_update_context, sparc_fallback_frame_state): Likewise.
* config/i386/sol2-unwind.h (x86_64_fallback_frame_state,
x86_fallback_frame_state): Likewise.
* config/i386/w32-unwind.h (i386_w32_fallback_frame_state): Likewise.
* config/i386/linux-unwind.h (x86_64_fallback_frame_state,
x86_fallback_frame_state): Likewise.
* config/i386/freebsd-unwind.h (x86_64_freebsd_fallback_frame_state):
Likewise.
* config/i386/dragonfly-unwind.h
(x86_64_dragonfly_fallback_frame_state): Likewise.
* config/i386/gnu-unwind.h (x86_gnu_fallback_frame_state): Likewise.
* config/csky/linux-unwind.h (csky_fallback_frame_state): Likewise.
* config/aarch64/linux-unwind.h (aarch64_fallback_frame_state):
Likewise.
* config/aarch64/freebsd-unwind.h
(aarch64_freebsd_fallback_frame_state): Likewise.
* config/aarch64/aarch64-unwind.h (aarch64_frob_update_context):
Likewise.
* config/or1k/linux-unwind.h (or1k_fallback_frame_state): Likewise.
* config/mips/linux-unwind.h (mips_fallback_frame_state): Likewise.
* config/loongarch/linux-unwind.h (loongarch_fallback_frame_state):
Likewise.
* config/m68k/linux-unwind.h (m68k_fallback_frame_state): Likewise.
* config/xtensa/linux-unwind.h (xtensa_fallback_frame_state):
Likewise.
* config/rs6000/darwin-fallback.c (set_offset): Likewise.
* config/rs6000/aix-unwind.h (MD_FROB_UPDATE_CONTEXT): Likewise.
* config/rs6000/linux-unwind.h (ppc_fallback_frame_state): Likewise.
* config/rs6000/freebsd-unwind.h (frob_update_context): Likewise.
2022-10-06 11:04:52 +02:00
|
|
|
fs->regs.how[8] = REG_SAVED_OFFSET;
|
2009-10-11 20:06:12 +00:00
|
|
|
fs->regs.reg[8].loc.offset = (long)&mctx->gregs[REG_R8] - new_cfa;
|
libgcc: Decrease size of _Unwind_FrameState and even more size of cleared area in uw_frame_state_for
The following patch implements something that has Florian found as
low hanging fruit in our unwinder and has been discussed in the
https://gcc.gnu.org/wiki/cauldron2022#cauldron2022talks.inprocess_unwinding_bof
talk.
_Unwind_FrameState type seems to be (unlike the pre-GCC 3 frame_state
which has been part of ABI) private to unwind-dw2.c + unwind.inc it
includes, it is always defined on the stack of some entrypoints, initialized
by static uw_frame_state_for and the address of it is also passed to other
static functions or the static inlines handling machine dependent unwinding,
but it isn't fortunately passed to any callbacks or public functions, so I
think we can safely change it any time we want.
Florian mentioned that the structure is large even on x86_64, 384 bytes
there, starts with 328 bytes long element with frame_state_reg_info type
which then starts with an array with __LIBGCC_DWARF_FRAME_REGISTERS__ + 1
elements, each of them is 16 bytes long, on x86_64
__LIBGCC_DWARF_FRAME_REGISTERS__ is just 17 but even that is big, on say
riscv __LIBGCC_DWARF_FRAME_REGISTERS__ is I think 128, on powerpc 111,
on sh 153 etc. And, we memset to zero the whole fs variable with the
_Unwind_FrameState type at the start of the unwinding.
The reason why each element is 16 byte (on 64-bit arches) is that it
contains some pointer or pointer sized integer and then an enum (with just
7 different enumerators) + padding.
The following patch decreases it by moving the enum into a separate
array and using just one byte for each register in that second array.
We could compress it even more, say 4 bits per register, but I don't
want to uglify the code for it too much and make the accesses slower.
Furthermore, the clearing of the object can clear only thos how array
and members after it, because REG_UNSAVED enumerator (0) doesn't actually
need any pointer or pointer sized integer, it is just the other kinds
that need to have there something.
By doing this, on x86_64 the above numbers change to _Unwind_FrameState
type being now 264 bytes long, frame_state_reg_info 208 bytes and we
don't clear the first 144 bytes of the object, so the memset is 120 bytes,
so ~ 31% of the old clearing size. On riscv 64-bit assuming it has same
structure layout rules for the few types used there that would be
~ 2160 bytes of _Unwind_FrameState type before and ~ 1264 bytes after,
with the memset previously ~ 2160 bytes and after ~ 232 bytes after.
We've also talked about possibly adding a number of initially initialized
regs and initializing the rest lazily, but at least for x86_64 with
18 elements in the array that doesn't seem to be worth it anymore,
especially because return address column is 16 there and that is usually the
first thing to be touched. It might theory help with lots of registers if
they are usually untouched, but would uglify and complicate any stores to
how by having to check there for the not initialized yet cases and lazy
initialization, and similarly for all reads of how to do there if below
last initialized one, use how, otherwise imply REG_UNSAVED.
The disadvantage of the patch is that touching reg[x].loc and how[x]
now means 2 cachelines rather than one as before, and I admit beyond
bootstrap/regtest I haven't benchmarked it in any way.
2022-10-06 Jakub Jelinek <jakub@redhat.com>
* unwind-dw2.h (REG_UNSAVED, REG_SAVED_OFFSET, REG_SAVED_REG,
REG_SAVED_EXP, REG_SAVED_VAL_OFFSET, REG_SAVED_VAL_EXP,
REG_UNDEFINED): New anonymous enum, moved from inside of
struct frame_state_reg_info.
(struct frame_state_reg_info): Remove reg[].how element and the
anonymous enum there. Add how element.
* unwind-dw2.c: Include stddef.h.
(uw_frame_state_for): Don't clear first
offsetof (_Unwind_FrameState, regs.how[0]) bytes of *fs.
(execute_cfa_program, __frame_state_for, uw_update_context_1,
uw_update_context): Use fs->regs.how[X] instead of fs->regs.reg[X].how
or fs.regs.how[X] instead of fs.regs.reg[X].how.
* config/sh/linux-unwind.h (sh_fallback_frame_state): Likewise.
* config/bfin/linux-unwind.h (bfin_fallback_frame_state): Likewise.
* config/pa/linux-unwind.h (pa32_fallback_frame_state): Likewise.
* config/pa/hpux-unwind.h (UPDATE_FS_FOR_SAR, UPDATE_FS_FOR_GR,
UPDATE_FS_FOR_FR, UPDATE_FS_FOR_PC, pa_fallback_frame_state):
Likewise.
* config/alpha/vms-unwind.h (alpha_vms_fallback_frame_state):
Likewise.
* config/alpha/linux-unwind.h (alpha_fallback_frame_state): Likewise.
* config/arc/linux-unwind.h (arc_fallback_frame_state,
arc_frob_update_context): Likewise.
* config/riscv/linux-unwind.h (riscv_fallback_frame_state): Likewise.
* config/nios2/linux-unwind.h (NIOS2_REG): Likewise.
* config/nds32/linux-unwind.h (NDS32_PUT_FS_REG): Likewise.
* config/s390/tpf-unwind.h (s390_fallback_frame_state): Likewise.
* config/s390/linux-unwind.h (s390_fallback_frame_state): Likewise.
* config/sparc/sol2-unwind.h (sparc64_frob_update_context,
MD_FALLBACK_FRAME_STATE_FOR): Likewise.
* config/sparc/linux-unwind.h (sparc64_fallback_frame_state,
sparc64_frob_update_context, sparc_fallback_frame_state): Likewise.
* config/i386/sol2-unwind.h (x86_64_fallback_frame_state,
x86_fallback_frame_state): Likewise.
* config/i386/w32-unwind.h (i386_w32_fallback_frame_state): Likewise.
* config/i386/linux-unwind.h (x86_64_fallback_frame_state,
x86_fallback_frame_state): Likewise.
* config/i386/freebsd-unwind.h (x86_64_freebsd_fallback_frame_state):
Likewise.
* config/i386/dragonfly-unwind.h
(x86_64_dragonfly_fallback_frame_state): Likewise.
* config/i386/gnu-unwind.h (x86_gnu_fallback_frame_state): Likewise.
* config/csky/linux-unwind.h (csky_fallback_frame_state): Likewise.
* config/aarch64/linux-unwind.h (aarch64_fallback_frame_state):
Likewise.
* config/aarch64/freebsd-unwind.h
(aarch64_freebsd_fallback_frame_state): Likewise.
* config/aarch64/aarch64-unwind.h (aarch64_frob_update_context):
Likewise.
* config/or1k/linux-unwind.h (or1k_fallback_frame_state): Likewise.
* config/mips/linux-unwind.h (mips_fallback_frame_state): Likewise.
* config/loongarch/linux-unwind.h (loongarch_fallback_frame_state):
Likewise.
* config/m68k/linux-unwind.h (m68k_fallback_frame_state): Likewise.
* config/xtensa/linux-unwind.h (xtensa_fallback_frame_state):
Likewise.
* config/rs6000/darwin-fallback.c (set_offset): Likewise.
* config/rs6000/aix-unwind.h (MD_FROB_UPDATE_CONTEXT): Likewise.
* config/rs6000/linux-unwind.h (ppc_fallback_frame_state): Likewise.
* config/rs6000/freebsd-unwind.h (frob_update_context): Likewise.
2022-10-06 11:04:52 +02:00
|
|
|
fs->regs.how[9] = REG_SAVED_OFFSET;
|
2009-10-11 20:06:12 +00:00
|
|
|
fs->regs.reg[9].loc.offset = (long)&mctx->gregs[REG_R9] - new_cfa;
|
libgcc: Decrease size of _Unwind_FrameState and even more size of cleared area in uw_frame_state_for
The following patch implements something that has Florian found as
low hanging fruit in our unwinder and has been discussed in the
https://gcc.gnu.org/wiki/cauldron2022#cauldron2022talks.inprocess_unwinding_bof
talk.
_Unwind_FrameState type seems to be (unlike the pre-GCC 3 frame_state
which has been part of ABI) private to unwind-dw2.c + unwind.inc it
includes, it is always defined on the stack of some entrypoints, initialized
by static uw_frame_state_for and the address of it is also passed to other
static functions or the static inlines handling machine dependent unwinding,
but it isn't fortunately passed to any callbacks or public functions, so I
think we can safely change it any time we want.
Florian mentioned that the structure is large even on x86_64, 384 bytes
there, starts with 328 bytes long element with frame_state_reg_info type
which then starts with an array with __LIBGCC_DWARF_FRAME_REGISTERS__ + 1
elements, each of them is 16 bytes long, on x86_64
__LIBGCC_DWARF_FRAME_REGISTERS__ is just 17 but even that is big, on say
riscv __LIBGCC_DWARF_FRAME_REGISTERS__ is I think 128, on powerpc 111,
on sh 153 etc. And, we memset to zero the whole fs variable with the
_Unwind_FrameState type at the start of the unwinding.
The reason why each element is 16 byte (on 64-bit arches) is that it
contains some pointer or pointer sized integer and then an enum (with just
7 different enumerators) + padding.
The following patch decreases it by moving the enum into a separate
array and using just one byte for each register in that second array.
We could compress it even more, say 4 bits per register, but I don't
want to uglify the code for it too much and make the accesses slower.
Furthermore, the clearing of the object can clear only thos how array
and members after it, because REG_UNSAVED enumerator (0) doesn't actually
need any pointer or pointer sized integer, it is just the other kinds
that need to have there something.
By doing this, on x86_64 the above numbers change to _Unwind_FrameState
type being now 264 bytes long, frame_state_reg_info 208 bytes and we
don't clear the first 144 bytes of the object, so the memset is 120 bytes,
so ~ 31% of the old clearing size. On riscv 64-bit assuming it has same
structure layout rules for the few types used there that would be
~ 2160 bytes of _Unwind_FrameState type before and ~ 1264 bytes after,
with the memset previously ~ 2160 bytes and after ~ 232 bytes after.
We've also talked about possibly adding a number of initially initialized
regs and initializing the rest lazily, but at least for x86_64 with
18 elements in the array that doesn't seem to be worth it anymore,
especially because return address column is 16 there and that is usually the
first thing to be touched. It might theory help with lots of registers if
they are usually untouched, but would uglify and complicate any stores to
how by having to check there for the not initialized yet cases and lazy
initialization, and similarly for all reads of how to do there if below
last initialized one, use how, otherwise imply REG_UNSAVED.
The disadvantage of the patch is that touching reg[x].loc and how[x]
now means 2 cachelines rather than one as before, and I admit beyond
bootstrap/regtest I haven't benchmarked it in any way.
2022-10-06 Jakub Jelinek <jakub@redhat.com>
* unwind-dw2.h (REG_UNSAVED, REG_SAVED_OFFSET, REG_SAVED_REG,
REG_SAVED_EXP, REG_SAVED_VAL_OFFSET, REG_SAVED_VAL_EXP,
REG_UNDEFINED): New anonymous enum, moved from inside of
struct frame_state_reg_info.
(struct frame_state_reg_info): Remove reg[].how element and the
anonymous enum there. Add how element.
* unwind-dw2.c: Include stddef.h.
(uw_frame_state_for): Don't clear first
offsetof (_Unwind_FrameState, regs.how[0]) bytes of *fs.
(execute_cfa_program, __frame_state_for, uw_update_context_1,
uw_update_context): Use fs->regs.how[X] instead of fs->regs.reg[X].how
or fs.regs.how[X] instead of fs.regs.reg[X].how.
* config/sh/linux-unwind.h (sh_fallback_frame_state): Likewise.
* config/bfin/linux-unwind.h (bfin_fallback_frame_state): Likewise.
* config/pa/linux-unwind.h (pa32_fallback_frame_state): Likewise.
* config/pa/hpux-unwind.h (UPDATE_FS_FOR_SAR, UPDATE_FS_FOR_GR,
UPDATE_FS_FOR_FR, UPDATE_FS_FOR_PC, pa_fallback_frame_state):
Likewise.
* config/alpha/vms-unwind.h (alpha_vms_fallback_frame_state):
Likewise.
* config/alpha/linux-unwind.h (alpha_fallback_frame_state): Likewise.
* config/arc/linux-unwind.h (arc_fallback_frame_state,
arc_frob_update_context): Likewise.
* config/riscv/linux-unwind.h (riscv_fallback_frame_state): Likewise.
* config/nios2/linux-unwind.h (NIOS2_REG): Likewise.
* config/nds32/linux-unwind.h (NDS32_PUT_FS_REG): Likewise.
* config/s390/tpf-unwind.h (s390_fallback_frame_state): Likewise.
* config/s390/linux-unwind.h (s390_fallback_frame_state): Likewise.
* config/sparc/sol2-unwind.h (sparc64_frob_update_context,
MD_FALLBACK_FRAME_STATE_FOR): Likewise.
* config/sparc/linux-unwind.h (sparc64_fallback_frame_state,
sparc64_frob_update_context, sparc_fallback_frame_state): Likewise.
* config/i386/sol2-unwind.h (x86_64_fallback_frame_state,
x86_fallback_frame_state): Likewise.
* config/i386/w32-unwind.h (i386_w32_fallback_frame_state): Likewise.
* config/i386/linux-unwind.h (x86_64_fallback_frame_state,
x86_fallback_frame_state): Likewise.
* config/i386/freebsd-unwind.h (x86_64_freebsd_fallback_frame_state):
Likewise.
* config/i386/dragonfly-unwind.h
(x86_64_dragonfly_fallback_frame_state): Likewise.
* config/i386/gnu-unwind.h (x86_gnu_fallback_frame_state): Likewise.
* config/csky/linux-unwind.h (csky_fallback_frame_state): Likewise.
* config/aarch64/linux-unwind.h (aarch64_fallback_frame_state):
Likewise.
* config/aarch64/freebsd-unwind.h
(aarch64_freebsd_fallback_frame_state): Likewise.
* config/aarch64/aarch64-unwind.h (aarch64_frob_update_context):
Likewise.
* config/or1k/linux-unwind.h (or1k_fallback_frame_state): Likewise.
* config/mips/linux-unwind.h (mips_fallback_frame_state): Likewise.
* config/loongarch/linux-unwind.h (loongarch_fallback_frame_state):
Likewise.
* config/m68k/linux-unwind.h (m68k_fallback_frame_state): Likewise.
* config/xtensa/linux-unwind.h (xtensa_fallback_frame_state):
Likewise.
* config/rs6000/darwin-fallback.c (set_offset): Likewise.
* config/rs6000/aix-unwind.h (MD_FROB_UPDATE_CONTEXT): Likewise.
* config/rs6000/linux-unwind.h (ppc_fallback_frame_state): Likewise.
* config/rs6000/freebsd-unwind.h (frob_update_context): Likewise.
2022-10-06 11:04:52 +02:00
|
|
|
fs->regs.how[10] = REG_SAVED_OFFSET;
|
2009-10-11 20:06:12 +00:00
|
|
|
fs->regs.reg[10].loc.offset = (long)&mctx->gregs[REG_R10] - new_cfa;
|
libgcc: Decrease size of _Unwind_FrameState and even more size of cleared area in uw_frame_state_for
The following patch implements something that has Florian found as
low hanging fruit in our unwinder and has been discussed in the
https://gcc.gnu.org/wiki/cauldron2022#cauldron2022talks.inprocess_unwinding_bof
talk.
_Unwind_FrameState type seems to be (unlike the pre-GCC 3 frame_state
which has been part of ABI) private to unwind-dw2.c + unwind.inc it
includes, it is always defined on the stack of some entrypoints, initialized
by static uw_frame_state_for and the address of it is also passed to other
static functions or the static inlines handling machine dependent unwinding,
but it isn't fortunately passed to any callbacks or public functions, so I
think we can safely change it any time we want.
Florian mentioned that the structure is large even on x86_64, 384 bytes
there, starts with 328 bytes long element with frame_state_reg_info type
which then starts with an array with __LIBGCC_DWARF_FRAME_REGISTERS__ + 1
elements, each of them is 16 bytes long, on x86_64
__LIBGCC_DWARF_FRAME_REGISTERS__ is just 17 but even that is big, on say
riscv __LIBGCC_DWARF_FRAME_REGISTERS__ is I think 128, on powerpc 111,
on sh 153 etc. And, we memset to zero the whole fs variable with the
_Unwind_FrameState type at the start of the unwinding.
The reason why each element is 16 byte (on 64-bit arches) is that it
contains some pointer or pointer sized integer and then an enum (with just
7 different enumerators) + padding.
The following patch decreases it by moving the enum into a separate
array and using just one byte for each register in that second array.
We could compress it even more, say 4 bits per register, but I don't
want to uglify the code for it too much and make the accesses slower.
Furthermore, the clearing of the object can clear only thos how array
and members after it, because REG_UNSAVED enumerator (0) doesn't actually
need any pointer or pointer sized integer, it is just the other kinds
that need to have there something.
By doing this, on x86_64 the above numbers change to _Unwind_FrameState
type being now 264 bytes long, frame_state_reg_info 208 bytes and we
don't clear the first 144 bytes of the object, so the memset is 120 bytes,
so ~ 31% of the old clearing size. On riscv 64-bit assuming it has same
structure layout rules for the few types used there that would be
~ 2160 bytes of _Unwind_FrameState type before and ~ 1264 bytes after,
with the memset previously ~ 2160 bytes and after ~ 232 bytes after.
We've also talked about possibly adding a number of initially initialized
regs and initializing the rest lazily, but at least for x86_64 with
18 elements in the array that doesn't seem to be worth it anymore,
especially because return address column is 16 there and that is usually the
first thing to be touched. It might theory help with lots of registers if
they are usually untouched, but would uglify and complicate any stores to
how by having to check there for the not initialized yet cases and lazy
initialization, and similarly for all reads of how to do there if below
last initialized one, use how, otherwise imply REG_UNSAVED.
The disadvantage of the patch is that touching reg[x].loc and how[x]
now means 2 cachelines rather than one as before, and I admit beyond
bootstrap/regtest I haven't benchmarked it in any way.
2022-10-06 Jakub Jelinek <jakub@redhat.com>
* unwind-dw2.h (REG_UNSAVED, REG_SAVED_OFFSET, REG_SAVED_REG,
REG_SAVED_EXP, REG_SAVED_VAL_OFFSET, REG_SAVED_VAL_EXP,
REG_UNDEFINED): New anonymous enum, moved from inside of
struct frame_state_reg_info.
(struct frame_state_reg_info): Remove reg[].how element and the
anonymous enum there. Add how element.
* unwind-dw2.c: Include stddef.h.
(uw_frame_state_for): Don't clear first
offsetof (_Unwind_FrameState, regs.how[0]) bytes of *fs.
(execute_cfa_program, __frame_state_for, uw_update_context_1,
uw_update_context): Use fs->regs.how[X] instead of fs->regs.reg[X].how
or fs.regs.how[X] instead of fs.regs.reg[X].how.
* config/sh/linux-unwind.h (sh_fallback_frame_state): Likewise.
* config/bfin/linux-unwind.h (bfin_fallback_frame_state): Likewise.
* config/pa/linux-unwind.h (pa32_fallback_frame_state): Likewise.
* config/pa/hpux-unwind.h (UPDATE_FS_FOR_SAR, UPDATE_FS_FOR_GR,
UPDATE_FS_FOR_FR, UPDATE_FS_FOR_PC, pa_fallback_frame_state):
Likewise.
* config/alpha/vms-unwind.h (alpha_vms_fallback_frame_state):
Likewise.
* config/alpha/linux-unwind.h (alpha_fallback_frame_state): Likewise.
* config/arc/linux-unwind.h (arc_fallback_frame_state,
arc_frob_update_context): Likewise.
* config/riscv/linux-unwind.h (riscv_fallback_frame_state): Likewise.
* config/nios2/linux-unwind.h (NIOS2_REG): Likewise.
* config/nds32/linux-unwind.h (NDS32_PUT_FS_REG): Likewise.
* config/s390/tpf-unwind.h (s390_fallback_frame_state): Likewise.
* config/s390/linux-unwind.h (s390_fallback_frame_state): Likewise.
* config/sparc/sol2-unwind.h (sparc64_frob_update_context,
MD_FALLBACK_FRAME_STATE_FOR): Likewise.
* config/sparc/linux-unwind.h (sparc64_fallback_frame_state,
sparc64_frob_update_context, sparc_fallback_frame_state): Likewise.
* config/i386/sol2-unwind.h (x86_64_fallback_frame_state,
x86_fallback_frame_state): Likewise.
* config/i386/w32-unwind.h (i386_w32_fallback_frame_state): Likewise.
* config/i386/linux-unwind.h (x86_64_fallback_frame_state,
x86_fallback_frame_state): Likewise.
* config/i386/freebsd-unwind.h (x86_64_freebsd_fallback_frame_state):
Likewise.
* config/i386/dragonfly-unwind.h
(x86_64_dragonfly_fallback_frame_state): Likewise.
* config/i386/gnu-unwind.h (x86_gnu_fallback_frame_state): Likewise.
* config/csky/linux-unwind.h (csky_fallback_frame_state): Likewise.
* config/aarch64/linux-unwind.h (aarch64_fallback_frame_state):
Likewise.
* config/aarch64/freebsd-unwind.h
(aarch64_freebsd_fallback_frame_state): Likewise.
* config/aarch64/aarch64-unwind.h (aarch64_frob_update_context):
Likewise.
* config/or1k/linux-unwind.h (or1k_fallback_frame_state): Likewise.
* config/mips/linux-unwind.h (mips_fallback_frame_state): Likewise.
* config/loongarch/linux-unwind.h (loongarch_fallback_frame_state):
Likewise.
* config/m68k/linux-unwind.h (m68k_fallback_frame_state): Likewise.
* config/xtensa/linux-unwind.h (xtensa_fallback_frame_state):
Likewise.
* config/rs6000/darwin-fallback.c (set_offset): Likewise.
* config/rs6000/aix-unwind.h (MD_FROB_UPDATE_CONTEXT): Likewise.
* config/rs6000/linux-unwind.h (ppc_fallback_frame_state): Likewise.
* config/rs6000/freebsd-unwind.h (frob_update_context): Likewise.
2022-10-06 11:04:52 +02:00
|
|
|
fs->regs.how[11] = REG_SAVED_OFFSET;
|
2009-10-11 20:06:12 +00:00
|
|
|
fs->regs.reg[11].loc.offset = (long)&mctx->gregs[REG_R11] - new_cfa;
|
libgcc: Decrease size of _Unwind_FrameState and even more size of cleared area in uw_frame_state_for
The following patch implements something that has Florian found as
low hanging fruit in our unwinder and has been discussed in the
https://gcc.gnu.org/wiki/cauldron2022#cauldron2022talks.inprocess_unwinding_bof
talk.
_Unwind_FrameState type seems to be (unlike the pre-GCC 3 frame_state
which has been part of ABI) private to unwind-dw2.c + unwind.inc it
includes, it is always defined on the stack of some entrypoints, initialized
by static uw_frame_state_for and the address of it is also passed to other
static functions or the static inlines handling machine dependent unwinding,
but it isn't fortunately passed to any callbacks or public functions, so I
think we can safely change it any time we want.
Florian mentioned that the structure is large even on x86_64, 384 bytes
there, starts with 328 bytes long element with frame_state_reg_info type
which then starts with an array with __LIBGCC_DWARF_FRAME_REGISTERS__ + 1
elements, each of them is 16 bytes long, on x86_64
__LIBGCC_DWARF_FRAME_REGISTERS__ is just 17 but even that is big, on say
riscv __LIBGCC_DWARF_FRAME_REGISTERS__ is I think 128, on powerpc 111,
on sh 153 etc. And, we memset to zero the whole fs variable with the
_Unwind_FrameState type at the start of the unwinding.
The reason why each element is 16 byte (on 64-bit arches) is that it
contains some pointer or pointer sized integer and then an enum (with just
7 different enumerators) + padding.
The following patch decreases it by moving the enum into a separate
array and using just one byte for each register in that second array.
We could compress it even more, say 4 bits per register, but I don't
want to uglify the code for it too much and make the accesses slower.
Furthermore, the clearing of the object can clear only thos how array
and members after it, because REG_UNSAVED enumerator (0) doesn't actually
need any pointer or pointer sized integer, it is just the other kinds
that need to have there something.
By doing this, on x86_64 the above numbers change to _Unwind_FrameState
type being now 264 bytes long, frame_state_reg_info 208 bytes and we
don't clear the first 144 bytes of the object, so the memset is 120 bytes,
so ~ 31% of the old clearing size. On riscv 64-bit assuming it has same
structure layout rules for the few types used there that would be
~ 2160 bytes of _Unwind_FrameState type before and ~ 1264 bytes after,
with the memset previously ~ 2160 bytes and after ~ 232 bytes after.
We've also talked about possibly adding a number of initially initialized
regs and initializing the rest lazily, but at least for x86_64 with
18 elements in the array that doesn't seem to be worth it anymore,
especially because return address column is 16 there and that is usually the
first thing to be touched. It might theory help with lots of registers if
they are usually untouched, but would uglify and complicate any stores to
how by having to check there for the not initialized yet cases and lazy
initialization, and similarly for all reads of how to do there if below
last initialized one, use how, otherwise imply REG_UNSAVED.
The disadvantage of the patch is that touching reg[x].loc and how[x]
now means 2 cachelines rather than one as before, and I admit beyond
bootstrap/regtest I haven't benchmarked it in any way.
2022-10-06 Jakub Jelinek <jakub@redhat.com>
* unwind-dw2.h (REG_UNSAVED, REG_SAVED_OFFSET, REG_SAVED_REG,
REG_SAVED_EXP, REG_SAVED_VAL_OFFSET, REG_SAVED_VAL_EXP,
REG_UNDEFINED): New anonymous enum, moved from inside of
struct frame_state_reg_info.
(struct frame_state_reg_info): Remove reg[].how element and the
anonymous enum there. Add how element.
* unwind-dw2.c: Include stddef.h.
(uw_frame_state_for): Don't clear first
offsetof (_Unwind_FrameState, regs.how[0]) bytes of *fs.
(execute_cfa_program, __frame_state_for, uw_update_context_1,
uw_update_context): Use fs->regs.how[X] instead of fs->regs.reg[X].how
or fs.regs.how[X] instead of fs.regs.reg[X].how.
* config/sh/linux-unwind.h (sh_fallback_frame_state): Likewise.
* config/bfin/linux-unwind.h (bfin_fallback_frame_state): Likewise.
* config/pa/linux-unwind.h (pa32_fallback_frame_state): Likewise.
* config/pa/hpux-unwind.h (UPDATE_FS_FOR_SAR, UPDATE_FS_FOR_GR,
UPDATE_FS_FOR_FR, UPDATE_FS_FOR_PC, pa_fallback_frame_state):
Likewise.
* config/alpha/vms-unwind.h (alpha_vms_fallback_frame_state):
Likewise.
* config/alpha/linux-unwind.h (alpha_fallback_frame_state): Likewise.
* config/arc/linux-unwind.h (arc_fallback_frame_state,
arc_frob_update_context): Likewise.
* config/riscv/linux-unwind.h (riscv_fallback_frame_state): Likewise.
* config/nios2/linux-unwind.h (NIOS2_REG): Likewise.
* config/nds32/linux-unwind.h (NDS32_PUT_FS_REG): Likewise.
* config/s390/tpf-unwind.h (s390_fallback_frame_state): Likewise.
* config/s390/linux-unwind.h (s390_fallback_frame_state): Likewise.
* config/sparc/sol2-unwind.h (sparc64_frob_update_context,
MD_FALLBACK_FRAME_STATE_FOR): Likewise.
* config/sparc/linux-unwind.h (sparc64_fallback_frame_state,
sparc64_frob_update_context, sparc_fallback_frame_state): Likewise.
* config/i386/sol2-unwind.h (x86_64_fallback_frame_state,
x86_fallback_frame_state): Likewise.
* config/i386/w32-unwind.h (i386_w32_fallback_frame_state): Likewise.
* config/i386/linux-unwind.h (x86_64_fallback_frame_state,
x86_fallback_frame_state): Likewise.
* config/i386/freebsd-unwind.h (x86_64_freebsd_fallback_frame_state):
Likewise.
* config/i386/dragonfly-unwind.h
(x86_64_dragonfly_fallback_frame_state): Likewise.
* config/i386/gnu-unwind.h (x86_gnu_fallback_frame_state): Likewise.
* config/csky/linux-unwind.h (csky_fallback_frame_state): Likewise.
* config/aarch64/linux-unwind.h (aarch64_fallback_frame_state):
Likewise.
* config/aarch64/freebsd-unwind.h
(aarch64_freebsd_fallback_frame_state): Likewise.
* config/aarch64/aarch64-unwind.h (aarch64_frob_update_context):
Likewise.
* config/or1k/linux-unwind.h (or1k_fallback_frame_state): Likewise.
* config/mips/linux-unwind.h (mips_fallback_frame_state): Likewise.
* config/loongarch/linux-unwind.h (loongarch_fallback_frame_state):
Likewise.
* config/m68k/linux-unwind.h (m68k_fallback_frame_state): Likewise.
* config/xtensa/linux-unwind.h (xtensa_fallback_frame_state):
Likewise.
* config/rs6000/darwin-fallback.c (set_offset): Likewise.
* config/rs6000/aix-unwind.h (MD_FROB_UPDATE_CONTEXT): Likewise.
* config/rs6000/linux-unwind.h (ppc_fallback_frame_state): Likewise.
* config/rs6000/freebsd-unwind.h (frob_update_context): Likewise.
2022-10-06 11:04:52 +02:00
|
|
|
fs->regs.how[12] = REG_SAVED_OFFSET;
|
2009-10-11 20:06:12 +00:00
|
|
|
fs->regs.reg[12].loc.offset = (long)&mctx->gregs[REG_R12] - new_cfa;
|
libgcc: Decrease size of _Unwind_FrameState and even more size of cleared area in uw_frame_state_for
The following patch implements something that has Florian found as
low hanging fruit in our unwinder and has been discussed in the
https://gcc.gnu.org/wiki/cauldron2022#cauldron2022talks.inprocess_unwinding_bof
talk.
_Unwind_FrameState type seems to be (unlike the pre-GCC 3 frame_state
which has been part of ABI) private to unwind-dw2.c + unwind.inc it
includes, it is always defined on the stack of some entrypoints, initialized
by static uw_frame_state_for and the address of it is also passed to other
static functions or the static inlines handling machine dependent unwinding,
but it isn't fortunately passed to any callbacks or public functions, so I
think we can safely change it any time we want.
Florian mentioned that the structure is large even on x86_64, 384 bytes
there, starts with 328 bytes long element with frame_state_reg_info type
which then starts with an array with __LIBGCC_DWARF_FRAME_REGISTERS__ + 1
elements, each of them is 16 bytes long, on x86_64
__LIBGCC_DWARF_FRAME_REGISTERS__ is just 17 but even that is big, on say
riscv __LIBGCC_DWARF_FRAME_REGISTERS__ is I think 128, on powerpc 111,
on sh 153 etc. And, we memset to zero the whole fs variable with the
_Unwind_FrameState type at the start of the unwinding.
The reason why each element is 16 byte (on 64-bit arches) is that it
contains some pointer or pointer sized integer and then an enum (with just
7 different enumerators) + padding.
The following patch decreases it by moving the enum into a separate
array and using just one byte for each register in that second array.
We could compress it even more, say 4 bits per register, but I don't
want to uglify the code for it too much and make the accesses slower.
Furthermore, the clearing of the object can clear only thos how array
and members after it, because REG_UNSAVED enumerator (0) doesn't actually
need any pointer or pointer sized integer, it is just the other kinds
that need to have there something.
By doing this, on x86_64 the above numbers change to _Unwind_FrameState
type being now 264 bytes long, frame_state_reg_info 208 bytes and we
don't clear the first 144 bytes of the object, so the memset is 120 bytes,
so ~ 31% of the old clearing size. On riscv 64-bit assuming it has same
structure layout rules for the few types used there that would be
~ 2160 bytes of _Unwind_FrameState type before and ~ 1264 bytes after,
with the memset previously ~ 2160 bytes and after ~ 232 bytes after.
We've also talked about possibly adding a number of initially initialized
regs and initializing the rest lazily, but at least for x86_64 with
18 elements in the array that doesn't seem to be worth it anymore,
especially because return address column is 16 there and that is usually the
first thing to be touched. It might theory help with lots of registers if
they are usually untouched, but would uglify and complicate any stores to
how by having to check there for the not initialized yet cases and lazy
initialization, and similarly for all reads of how to do there if below
last initialized one, use how, otherwise imply REG_UNSAVED.
The disadvantage of the patch is that touching reg[x].loc and how[x]
now means 2 cachelines rather than one as before, and I admit beyond
bootstrap/regtest I haven't benchmarked it in any way.
2022-10-06 Jakub Jelinek <jakub@redhat.com>
* unwind-dw2.h (REG_UNSAVED, REG_SAVED_OFFSET, REG_SAVED_REG,
REG_SAVED_EXP, REG_SAVED_VAL_OFFSET, REG_SAVED_VAL_EXP,
REG_UNDEFINED): New anonymous enum, moved from inside of
struct frame_state_reg_info.
(struct frame_state_reg_info): Remove reg[].how element and the
anonymous enum there. Add how element.
* unwind-dw2.c: Include stddef.h.
(uw_frame_state_for): Don't clear first
offsetof (_Unwind_FrameState, regs.how[0]) bytes of *fs.
(execute_cfa_program, __frame_state_for, uw_update_context_1,
uw_update_context): Use fs->regs.how[X] instead of fs->regs.reg[X].how
or fs.regs.how[X] instead of fs.regs.reg[X].how.
* config/sh/linux-unwind.h (sh_fallback_frame_state): Likewise.
* config/bfin/linux-unwind.h (bfin_fallback_frame_state): Likewise.
* config/pa/linux-unwind.h (pa32_fallback_frame_state): Likewise.
* config/pa/hpux-unwind.h (UPDATE_FS_FOR_SAR, UPDATE_FS_FOR_GR,
UPDATE_FS_FOR_FR, UPDATE_FS_FOR_PC, pa_fallback_frame_state):
Likewise.
* config/alpha/vms-unwind.h (alpha_vms_fallback_frame_state):
Likewise.
* config/alpha/linux-unwind.h (alpha_fallback_frame_state): Likewise.
* config/arc/linux-unwind.h (arc_fallback_frame_state,
arc_frob_update_context): Likewise.
* config/riscv/linux-unwind.h (riscv_fallback_frame_state): Likewise.
* config/nios2/linux-unwind.h (NIOS2_REG): Likewise.
* config/nds32/linux-unwind.h (NDS32_PUT_FS_REG): Likewise.
* config/s390/tpf-unwind.h (s390_fallback_frame_state): Likewise.
* config/s390/linux-unwind.h (s390_fallback_frame_state): Likewise.
* config/sparc/sol2-unwind.h (sparc64_frob_update_context,
MD_FALLBACK_FRAME_STATE_FOR): Likewise.
* config/sparc/linux-unwind.h (sparc64_fallback_frame_state,
sparc64_frob_update_context, sparc_fallback_frame_state): Likewise.
* config/i386/sol2-unwind.h (x86_64_fallback_frame_state,
x86_fallback_frame_state): Likewise.
* config/i386/w32-unwind.h (i386_w32_fallback_frame_state): Likewise.
* config/i386/linux-unwind.h (x86_64_fallback_frame_state,
x86_fallback_frame_state): Likewise.
* config/i386/freebsd-unwind.h (x86_64_freebsd_fallback_frame_state):
Likewise.
* config/i386/dragonfly-unwind.h
(x86_64_dragonfly_fallback_frame_state): Likewise.
* config/i386/gnu-unwind.h (x86_gnu_fallback_frame_state): Likewise.
* config/csky/linux-unwind.h (csky_fallback_frame_state): Likewise.
* config/aarch64/linux-unwind.h (aarch64_fallback_frame_state):
Likewise.
* config/aarch64/freebsd-unwind.h
(aarch64_freebsd_fallback_frame_state): Likewise.
* config/aarch64/aarch64-unwind.h (aarch64_frob_update_context):
Likewise.
* config/or1k/linux-unwind.h (or1k_fallback_frame_state): Likewise.
* config/mips/linux-unwind.h (mips_fallback_frame_state): Likewise.
* config/loongarch/linux-unwind.h (loongarch_fallback_frame_state):
Likewise.
* config/m68k/linux-unwind.h (m68k_fallback_frame_state): Likewise.
* config/xtensa/linux-unwind.h (xtensa_fallback_frame_state):
Likewise.
* config/rs6000/darwin-fallback.c (set_offset): Likewise.
* config/rs6000/aix-unwind.h (MD_FROB_UPDATE_CONTEXT): Likewise.
* config/rs6000/linux-unwind.h (ppc_fallback_frame_state): Likewise.
* config/rs6000/freebsd-unwind.h (frob_update_context): Likewise.
2022-10-06 11:04:52 +02:00
|
|
|
fs->regs.how[13] = REG_SAVED_OFFSET;
|
2009-10-11 20:06:12 +00:00
|
|
|
fs->regs.reg[13].loc.offset = (long)&mctx->gregs[REG_R13] - new_cfa;
|
libgcc: Decrease size of _Unwind_FrameState and even more size of cleared area in uw_frame_state_for
The following patch implements something that has Florian found as
low hanging fruit in our unwinder and has been discussed in the
https://gcc.gnu.org/wiki/cauldron2022#cauldron2022talks.inprocess_unwinding_bof
talk.
_Unwind_FrameState type seems to be (unlike the pre-GCC 3 frame_state
which has been part of ABI) private to unwind-dw2.c + unwind.inc it
includes, it is always defined on the stack of some entrypoints, initialized
by static uw_frame_state_for and the address of it is also passed to other
static functions or the static inlines handling machine dependent unwinding,
but it isn't fortunately passed to any callbacks or public functions, so I
think we can safely change it any time we want.
Florian mentioned that the structure is large even on x86_64, 384 bytes
there, starts with 328 bytes long element with frame_state_reg_info type
which then starts with an array with __LIBGCC_DWARF_FRAME_REGISTERS__ + 1
elements, each of them is 16 bytes long, on x86_64
__LIBGCC_DWARF_FRAME_REGISTERS__ is just 17 but even that is big, on say
riscv __LIBGCC_DWARF_FRAME_REGISTERS__ is I think 128, on powerpc 111,
on sh 153 etc. And, we memset to zero the whole fs variable with the
_Unwind_FrameState type at the start of the unwinding.
The reason why each element is 16 byte (on 64-bit arches) is that it
contains some pointer or pointer sized integer and then an enum (with just
7 different enumerators) + padding.
The following patch decreases it by moving the enum into a separate
array and using just one byte for each register in that second array.
We could compress it even more, say 4 bits per register, but I don't
want to uglify the code for it too much and make the accesses slower.
Furthermore, the clearing of the object can clear only thos how array
and members after it, because REG_UNSAVED enumerator (0) doesn't actually
need any pointer or pointer sized integer, it is just the other kinds
that need to have there something.
By doing this, on x86_64 the above numbers change to _Unwind_FrameState
type being now 264 bytes long, frame_state_reg_info 208 bytes and we
don't clear the first 144 bytes of the object, so the memset is 120 bytes,
so ~ 31% of the old clearing size. On riscv 64-bit assuming it has same
structure layout rules for the few types used there that would be
~ 2160 bytes of _Unwind_FrameState type before and ~ 1264 bytes after,
with the memset previously ~ 2160 bytes and after ~ 232 bytes after.
We've also talked about possibly adding a number of initially initialized
regs and initializing the rest lazily, but at least for x86_64 with
18 elements in the array that doesn't seem to be worth it anymore,
especially because return address column is 16 there and that is usually the
first thing to be touched. It might theory help with lots of registers if
they are usually untouched, but would uglify and complicate any stores to
how by having to check there for the not initialized yet cases and lazy
initialization, and similarly for all reads of how to do there if below
last initialized one, use how, otherwise imply REG_UNSAVED.
The disadvantage of the patch is that touching reg[x].loc and how[x]
now means 2 cachelines rather than one as before, and I admit beyond
bootstrap/regtest I haven't benchmarked it in any way.
2022-10-06 Jakub Jelinek <jakub@redhat.com>
* unwind-dw2.h (REG_UNSAVED, REG_SAVED_OFFSET, REG_SAVED_REG,
REG_SAVED_EXP, REG_SAVED_VAL_OFFSET, REG_SAVED_VAL_EXP,
REG_UNDEFINED): New anonymous enum, moved from inside of
struct frame_state_reg_info.
(struct frame_state_reg_info): Remove reg[].how element and the
anonymous enum there. Add how element.
* unwind-dw2.c: Include stddef.h.
(uw_frame_state_for): Don't clear first
offsetof (_Unwind_FrameState, regs.how[0]) bytes of *fs.
(execute_cfa_program, __frame_state_for, uw_update_context_1,
uw_update_context): Use fs->regs.how[X] instead of fs->regs.reg[X].how
or fs.regs.how[X] instead of fs.regs.reg[X].how.
* config/sh/linux-unwind.h (sh_fallback_frame_state): Likewise.
* config/bfin/linux-unwind.h (bfin_fallback_frame_state): Likewise.
* config/pa/linux-unwind.h (pa32_fallback_frame_state): Likewise.
* config/pa/hpux-unwind.h (UPDATE_FS_FOR_SAR, UPDATE_FS_FOR_GR,
UPDATE_FS_FOR_FR, UPDATE_FS_FOR_PC, pa_fallback_frame_state):
Likewise.
* config/alpha/vms-unwind.h (alpha_vms_fallback_frame_state):
Likewise.
* config/alpha/linux-unwind.h (alpha_fallback_frame_state): Likewise.
* config/arc/linux-unwind.h (arc_fallback_frame_state,
arc_frob_update_context): Likewise.
* config/riscv/linux-unwind.h (riscv_fallback_frame_state): Likewise.
* config/nios2/linux-unwind.h (NIOS2_REG): Likewise.
* config/nds32/linux-unwind.h (NDS32_PUT_FS_REG): Likewise.
* config/s390/tpf-unwind.h (s390_fallback_frame_state): Likewise.
* config/s390/linux-unwind.h (s390_fallback_frame_state): Likewise.
* config/sparc/sol2-unwind.h (sparc64_frob_update_context,
MD_FALLBACK_FRAME_STATE_FOR): Likewise.
* config/sparc/linux-unwind.h (sparc64_fallback_frame_state,
sparc64_frob_update_context, sparc_fallback_frame_state): Likewise.
* config/i386/sol2-unwind.h (x86_64_fallback_frame_state,
x86_fallback_frame_state): Likewise.
* config/i386/w32-unwind.h (i386_w32_fallback_frame_state): Likewise.
* config/i386/linux-unwind.h (x86_64_fallback_frame_state,
x86_fallback_frame_state): Likewise.
* config/i386/freebsd-unwind.h (x86_64_freebsd_fallback_frame_state):
Likewise.
* config/i386/dragonfly-unwind.h
(x86_64_dragonfly_fallback_frame_state): Likewise.
* config/i386/gnu-unwind.h (x86_gnu_fallback_frame_state): Likewise.
* config/csky/linux-unwind.h (csky_fallback_frame_state): Likewise.
* config/aarch64/linux-unwind.h (aarch64_fallback_frame_state):
Likewise.
* config/aarch64/freebsd-unwind.h
(aarch64_freebsd_fallback_frame_state): Likewise.
* config/aarch64/aarch64-unwind.h (aarch64_frob_update_context):
Likewise.
* config/or1k/linux-unwind.h (or1k_fallback_frame_state): Likewise.
* config/mips/linux-unwind.h (mips_fallback_frame_state): Likewise.
* config/loongarch/linux-unwind.h (loongarch_fallback_frame_state):
Likewise.
* config/m68k/linux-unwind.h (m68k_fallback_frame_state): Likewise.
* config/xtensa/linux-unwind.h (xtensa_fallback_frame_state):
Likewise.
* config/rs6000/darwin-fallback.c (set_offset): Likewise.
* config/rs6000/aix-unwind.h (MD_FROB_UPDATE_CONTEXT): Likewise.
* config/rs6000/linux-unwind.h (ppc_fallback_frame_state): Likewise.
* config/rs6000/freebsd-unwind.h (frob_update_context): Likewise.
2022-10-06 11:04:52 +02:00
|
|
|
fs->regs.how[14] = REG_SAVED_OFFSET;
|
2009-10-11 20:06:12 +00:00
|
|
|
fs->regs.reg[14].loc.offset = (long)&mctx->gregs[REG_R14] - new_cfa;
|
libgcc: Decrease size of _Unwind_FrameState and even more size of cleared area in uw_frame_state_for
The following patch implements something that has Florian found as
low hanging fruit in our unwinder and has been discussed in the
https://gcc.gnu.org/wiki/cauldron2022#cauldron2022talks.inprocess_unwinding_bof
talk.
_Unwind_FrameState type seems to be (unlike the pre-GCC 3 frame_state
which has been part of ABI) private to unwind-dw2.c + unwind.inc it
includes, it is always defined on the stack of some entrypoints, initialized
by static uw_frame_state_for and the address of it is also passed to other
static functions or the static inlines handling machine dependent unwinding,
but it isn't fortunately passed to any callbacks or public functions, so I
think we can safely change it any time we want.
Florian mentioned that the structure is large even on x86_64, 384 bytes
there, starts with 328 bytes long element with frame_state_reg_info type
which then starts with an array with __LIBGCC_DWARF_FRAME_REGISTERS__ + 1
elements, each of them is 16 bytes long, on x86_64
__LIBGCC_DWARF_FRAME_REGISTERS__ is just 17 but even that is big, on say
riscv __LIBGCC_DWARF_FRAME_REGISTERS__ is I think 128, on powerpc 111,
on sh 153 etc. And, we memset to zero the whole fs variable with the
_Unwind_FrameState type at the start of the unwinding.
The reason why each element is 16 byte (on 64-bit arches) is that it
contains some pointer or pointer sized integer and then an enum (with just
7 different enumerators) + padding.
The following patch decreases it by moving the enum into a separate
array and using just one byte for each register in that second array.
We could compress it even more, say 4 bits per register, but I don't
want to uglify the code for it too much and make the accesses slower.
Furthermore, the clearing of the object can clear only thos how array
and members after it, because REG_UNSAVED enumerator (0) doesn't actually
need any pointer or pointer sized integer, it is just the other kinds
that need to have there something.
By doing this, on x86_64 the above numbers change to _Unwind_FrameState
type being now 264 bytes long, frame_state_reg_info 208 bytes and we
don't clear the first 144 bytes of the object, so the memset is 120 bytes,
so ~ 31% of the old clearing size. On riscv 64-bit assuming it has same
structure layout rules for the few types used there that would be
~ 2160 bytes of _Unwind_FrameState type before and ~ 1264 bytes after,
with the memset previously ~ 2160 bytes and after ~ 232 bytes after.
We've also talked about possibly adding a number of initially initialized
regs and initializing the rest lazily, but at least for x86_64 with
18 elements in the array that doesn't seem to be worth it anymore,
especially because return address column is 16 there and that is usually the
first thing to be touched. It might theory help with lots of registers if
they are usually untouched, but would uglify and complicate any stores to
how by having to check there for the not initialized yet cases and lazy
initialization, and similarly for all reads of how to do there if below
last initialized one, use how, otherwise imply REG_UNSAVED.
The disadvantage of the patch is that touching reg[x].loc and how[x]
now means 2 cachelines rather than one as before, and I admit beyond
bootstrap/regtest I haven't benchmarked it in any way.
2022-10-06 Jakub Jelinek <jakub@redhat.com>
* unwind-dw2.h (REG_UNSAVED, REG_SAVED_OFFSET, REG_SAVED_REG,
REG_SAVED_EXP, REG_SAVED_VAL_OFFSET, REG_SAVED_VAL_EXP,
REG_UNDEFINED): New anonymous enum, moved from inside of
struct frame_state_reg_info.
(struct frame_state_reg_info): Remove reg[].how element and the
anonymous enum there. Add how element.
* unwind-dw2.c: Include stddef.h.
(uw_frame_state_for): Don't clear first
offsetof (_Unwind_FrameState, regs.how[0]) bytes of *fs.
(execute_cfa_program, __frame_state_for, uw_update_context_1,
uw_update_context): Use fs->regs.how[X] instead of fs->regs.reg[X].how
or fs.regs.how[X] instead of fs.regs.reg[X].how.
* config/sh/linux-unwind.h (sh_fallback_frame_state): Likewise.
* config/bfin/linux-unwind.h (bfin_fallback_frame_state): Likewise.
* config/pa/linux-unwind.h (pa32_fallback_frame_state): Likewise.
* config/pa/hpux-unwind.h (UPDATE_FS_FOR_SAR, UPDATE_FS_FOR_GR,
UPDATE_FS_FOR_FR, UPDATE_FS_FOR_PC, pa_fallback_frame_state):
Likewise.
* config/alpha/vms-unwind.h (alpha_vms_fallback_frame_state):
Likewise.
* config/alpha/linux-unwind.h (alpha_fallback_frame_state): Likewise.
* config/arc/linux-unwind.h (arc_fallback_frame_state,
arc_frob_update_context): Likewise.
* config/riscv/linux-unwind.h (riscv_fallback_frame_state): Likewise.
* config/nios2/linux-unwind.h (NIOS2_REG): Likewise.
* config/nds32/linux-unwind.h (NDS32_PUT_FS_REG): Likewise.
* config/s390/tpf-unwind.h (s390_fallback_frame_state): Likewise.
* config/s390/linux-unwind.h (s390_fallback_frame_state): Likewise.
* config/sparc/sol2-unwind.h (sparc64_frob_update_context,
MD_FALLBACK_FRAME_STATE_FOR): Likewise.
* config/sparc/linux-unwind.h (sparc64_fallback_frame_state,
sparc64_frob_update_context, sparc_fallback_frame_state): Likewise.
* config/i386/sol2-unwind.h (x86_64_fallback_frame_state,
x86_fallback_frame_state): Likewise.
* config/i386/w32-unwind.h (i386_w32_fallback_frame_state): Likewise.
* config/i386/linux-unwind.h (x86_64_fallback_frame_state,
x86_fallback_frame_state): Likewise.
* config/i386/freebsd-unwind.h (x86_64_freebsd_fallback_frame_state):
Likewise.
* config/i386/dragonfly-unwind.h
(x86_64_dragonfly_fallback_frame_state): Likewise.
* config/i386/gnu-unwind.h (x86_gnu_fallback_frame_state): Likewise.
* config/csky/linux-unwind.h (csky_fallback_frame_state): Likewise.
* config/aarch64/linux-unwind.h (aarch64_fallback_frame_state):
Likewise.
* config/aarch64/freebsd-unwind.h
(aarch64_freebsd_fallback_frame_state): Likewise.
* config/aarch64/aarch64-unwind.h (aarch64_frob_update_context):
Likewise.
* config/or1k/linux-unwind.h (or1k_fallback_frame_state): Likewise.
* config/mips/linux-unwind.h (mips_fallback_frame_state): Likewise.
* config/loongarch/linux-unwind.h (loongarch_fallback_frame_state):
Likewise.
* config/m68k/linux-unwind.h (m68k_fallback_frame_state): Likewise.
* config/xtensa/linux-unwind.h (xtensa_fallback_frame_state):
Likewise.
* config/rs6000/darwin-fallback.c (set_offset): Likewise.
* config/rs6000/aix-unwind.h (MD_FROB_UPDATE_CONTEXT): Likewise.
* config/rs6000/linux-unwind.h (ppc_fallback_frame_state): Likewise.
* config/rs6000/freebsd-unwind.h (frob_update_context): Likewise.
2022-10-06 11:04:52 +02:00
|
|
|
fs->regs.how[15] = REG_SAVED_OFFSET;
|
2009-10-11 20:06:12 +00:00
|
|
|
fs->regs.reg[15].loc.offset = (long)&mctx->gregs[REG_R15] - new_cfa;
|
libgcc: Decrease size of _Unwind_FrameState and even more size of cleared area in uw_frame_state_for
The following patch implements something that has Florian found as
low hanging fruit in our unwinder and has been discussed in the
https://gcc.gnu.org/wiki/cauldron2022#cauldron2022talks.inprocess_unwinding_bof
talk.
_Unwind_FrameState type seems to be (unlike the pre-GCC 3 frame_state
which has been part of ABI) private to unwind-dw2.c + unwind.inc it
includes, it is always defined on the stack of some entrypoints, initialized
by static uw_frame_state_for and the address of it is also passed to other
static functions or the static inlines handling machine dependent unwinding,
but it isn't fortunately passed to any callbacks or public functions, so I
think we can safely change it any time we want.
Florian mentioned that the structure is large even on x86_64, 384 bytes
there, starts with 328 bytes long element with frame_state_reg_info type
which then starts with an array with __LIBGCC_DWARF_FRAME_REGISTERS__ + 1
elements, each of them is 16 bytes long, on x86_64
__LIBGCC_DWARF_FRAME_REGISTERS__ is just 17 but even that is big, on say
riscv __LIBGCC_DWARF_FRAME_REGISTERS__ is I think 128, on powerpc 111,
on sh 153 etc. And, we memset to zero the whole fs variable with the
_Unwind_FrameState type at the start of the unwinding.
The reason why each element is 16 byte (on 64-bit arches) is that it
contains some pointer or pointer sized integer and then an enum (with just
7 different enumerators) + padding.
The following patch decreases it by moving the enum into a separate
array and using just one byte for each register in that second array.
We could compress it even more, say 4 bits per register, but I don't
want to uglify the code for it too much and make the accesses slower.
Furthermore, the clearing of the object can clear only thos how array
and members after it, because REG_UNSAVED enumerator (0) doesn't actually
need any pointer or pointer sized integer, it is just the other kinds
that need to have there something.
By doing this, on x86_64 the above numbers change to _Unwind_FrameState
type being now 264 bytes long, frame_state_reg_info 208 bytes and we
don't clear the first 144 bytes of the object, so the memset is 120 bytes,
so ~ 31% of the old clearing size. On riscv 64-bit assuming it has same
structure layout rules for the few types used there that would be
~ 2160 bytes of _Unwind_FrameState type before and ~ 1264 bytes after,
with the memset previously ~ 2160 bytes and after ~ 232 bytes after.
We've also talked about possibly adding a number of initially initialized
regs and initializing the rest lazily, but at least for x86_64 with
18 elements in the array that doesn't seem to be worth it anymore,
especially because return address column is 16 there and that is usually the
first thing to be touched. It might theory help with lots of registers if
they are usually untouched, but would uglify and complicate any stores to
how by having to check there for the not initialized yet cases and lazy
initialization, and similarly for all reads of how to do there if below
last initialized one, use how, otherwise imply REG_UNSAVED.
The disadvantage of the patch is that touching reg[x].loc and how[x]
now means 2 cachelines rather than one as before, and I admit beyond
bootstrap/regtest I haven't benchmarked it in any way.
2022-10-06 Jakub Jelinek <jakub@redhat.com>
* unwind-dw2.h (REG_UNSAVED, REG_SAVED_OFFSET, REG_SAVED_REG,
REG_SAVED_EXP, REG_SAVED_VAL_OFFSET, REG_SAVED_VAL_EXP,
REG_UNDEFINED): New anonymous enum, moved from inside of
struct frame_state_reg_info.
(struct frame_state_reg_info): Remove reg[].how element and the
anonymous enum there. Add how element.
* unwind-dw2.c: Include stddef.h.
(uw_frame_state_for): Don't clear first
offsetof (_Unwind_FrameState, regs.how[0]) bytes of *fs.
(execute_cfa_program, __frame_state_for, uw_update_context_1,
uw_update_context): Use fs->regs.how[X] instead of fs->regs.reg[X].how
or fs.regs.how[X] instead of fs.regs.reg[X].how.
* config/sh/linux-unwind.h (sh_fallback_frame_state): Likewise.
* config/bfin/linux-unwind.h (bfin_fallback_frame_state): Likewise.
* config/pa/linux-unwind.h (pa32_fallback_frame_state): Likewise.
* config/pa/hpux-unwind.h (UPDATE_FS_FOR_SAR, UPDATE_FS_FOR_GR,
UPDATE_FS_FOR_FR, UPDATE_FS_FOR_PC, pa_fallback_frame_state):
Likewise.
* config/alpha/vms-unwind.h (alpha_vms_fallback_frame_state):
Likewise.
* config/alpha/linux-unwind.h (alpha_fallback_frame_state): Likewise.
* config/arc/linux-unwind.h (arc_fallback_frame_state,
arc_frob_update_context): Likewise.
* config/riscv/linux-unwind.h (riscv_fallback_frame_state): Likewise.
* config/nios2/linux-unwind.h (NIOS2_REG): Likewise.
* config/nds32/linux-unwind.h (NDS32_PUT_FS_REG): Likewise.
* config/s390/tpf-unwind.h (s390_fallback_frame_state): Likewise.
* config/s390/linux-unwind.h (s390_fallback_frame_state): Likewise.
* config/sparc/sol2-unwind.h (sparc64_frob_update_context,
MD_FALLBACK_FRAME_STATE_FOR): Likewise.
* config/sparc/linux-unwind.h (sparc64_fallback_frame_state,
sparc64_frob_update_context, sparc_fallback_frame_state): Likewise.
* config/i386/sol2-unwind.h (x86_64_fallback_frame_state,
x86_fallback_frame_state): Likewise.
* config/i386/w32-unwind.h (i386_w32_fallback_frame_state): Likewise.
* config/i386/linux-unwind.h (x86_64_fallback_frame_state,
x86_fallback_frame_state): Likewise.
* config/i386/freebsd-unwind.h (x86_64_freebsd_fallback_frame_state):
Likewise.
* config/i386/dragonfly-unwind.h
(x86_64_dragonfly_fallback_frame_state): Likewise.
* config/i386/gnu-unwind.h (x86_gnu_fallback_frame_state): Likewise.
* config/csky/linux-unwind.h (csky_fallback_frame_state): Likewise.
* config/aarch64/linux-unwind.h (aarch64_fallback_frame_state):
Likewise.
* config/aarch64/freebsd-unwind.h
(aarch64_freebsd_fallback_frame_state): Likewise.
* config/aarch64/aarch64-unwind.h (aarch64_frob_update_context):
Likewise.
* config/or1k/linux-unwind.h (or1k_fallback_frame_state): Likewise.
* config/mips/linux-unwind.h (mips_fallback_frame_state): Likewise.
* config/loongarch/linux-unwind.h (loongarch_fallback_frame_state):
Likewise.
* config/m68k/linux-unwind.h (m68k_fallback_frame_state): Likewise.
* config/xtensa/linux-unwind.h (xtensa_fallback_frame_state):
Likewise.
* config/rs6000/darwin-fallback.c (set_offset): Likewise.
* config/rs6000/aix-unwind.h (MD_FROB_UPDATE_CONTEXT): Likewise.
* config/rs6000/linux-unwind.h (ppc_fallback_frame_state): Likewise.
* config/rs6000/freebsd-unwind.h (frob_update_context): Likewise.
2022-10-06 11:04:52 +02:00
|
|
|
fs->regs.how[16] = REG_SAVED_OFFSET;
|
2009-10-11 20:06:12 +00:00
|
|
|
fs->regs.reg[16].loc.offset = (long)&mctx->gregs[REG_RIP] - new_cfa;
|
|
|
|
fs->retaddr_column = 16;
|
|
|
|
fs->signal_frame = 1;
|
|
|
|
|
|
|
|
return _URC_NO_REASON;
|
|
|
|
}
|
|
|
|
|
|
|
|
#else
|
|
|
|
|
|
|
|
#define MD_FALLBACK_FRAME_STATE_FOR x86_fallback_frame_state
|
|
|
|
|
|
|
|
static _Unwind_Reason_Code
|
|
|
|
x86_fallback_frame_state (struct _Unwind_Context *context,
|
|
|
|
_Unwind_FrameState *fs)
|
|
|
|
{
|
|
|
|
unsigned char *pc = context->ra;
|
|
|
|
mcontext_t *mctx;
|
|
|
|
long new_cfa;
|
|
|
|
|
2019-05-14 17:17:23 +00:00
|
|
|
if (/* Solaris 11 since snv_125
|
2010-07-13 09:10:09 +00:00
|
|
|
-------------------------
|
|
|
|
<__sighndlr+0> push %ebp
|
|
|
|
<__sighndlr+1> mov %esp,%ebp
|
|
|
|
<__sighndlr+3> and $0xfffffff0,%esp
|
|
|
|
<__sighndlr+6> sub $0x4,%esp
|
|
|
|
<__sighndlr+9> pushl 0x10(%ebp)
|
|
|
|
<__sighndlr+12> pushl 0xc(%ebp)
|
|
|
|
<__sighndlr+15> pushl 0x8(%ebp)
|
|
|
|
<__sighndlr+18> call *0x14(%ebp)
|
|
|
|
<__sighndlr+21> leave <--- PC
|
|
|
|
<__sighndlr+22> ret */
|
|
|
|
(*(unsigned long *)(pc - 21) == 0x83ec8b55
|
|
|
|
&& *(unsigned long *)(pc - 17) == 0xec83f0e4
|
|
|
|
&& *(unsigned long *)(pc - 13) == 0x1075ff04
|
|
|
|
&& *(unsigned long *)(pc - 9) == 0xff0c75ff
|
|
|
|
&& *(unsigned long *)(pc - 5) == 0x55ff0875
|
|
|
|
&& (*(unsigned long *)(pc - 1) & 0x00ffffff) == 0x00c3c914))
|
2009-10-11 20:06:12 +00:00
|
|
|
{
|
|
|
|
struct handler_args {
|
|
|
|
int signo;
|
|
|
|
siginfo_t *sip;
|
|
|
|
ucontext_t *ucontext;
|
|
|
|
} *handler_args = context->cfa;
|
|
|
|
mctx = &handler_args->ucontext->uc_mcontext;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
return _URC_END_OF_STACK;
|
|
|
|
|
|
|
|
new_cfa = mctx->gregs[UESP];
|
|
|
|
|
|
|
|
fs->regs.cfa_how = CFA_REG_OFFSET;
|
|
|
|
fs->regs.cfa_reg = 4;
|
|
|
|
fs->regs.cfa_offset = new_cfa - (long) context->cfa;
|
|
|
|
|
|
|
|
/* The SVR4 register numbering macros aren't usable in libgcc. */
|
libgcc: Decrease size of _Unwind_FrameState and even more size of cleared area in uw_frame_state_for
The following patch implements something that has Florian found as
low hanging fruit in our unwinder and has been discussed in the
https://gcc.gnu.org/wiki/cauldron2022#cauldron2022talks.inprocess_unwinding_bof
talk.
_Unwind_FrameState type seems to be (unlike the pre-GCC 3 frame_state
which has been part of ABI) private to unwind-dw2.c + unwind.inc it
includes, it is always defined on the stack of some entrypoints, initialized
by static uw_frame_state_for and the address of it is also passed to other
static functions or the static inlines handling machine dependent unwinding,
but it isn't fortunately passed to any callbacks or public functions, so I
think we can safely change it any time we want.
Florian mentioned that the structure is large even on x86_64, 384 bytes
there, starts with 328 bytes long element with frame_state_reg_info type
which then starts with an array with __LIBGCC_DWARF_FRAME_REGISTERS__ + 1
elements, each of them is 16 bytes long, on x86_64
__LIBGCC_DWARF_FRAME_REGISTERS__ is just 17 but even that is big, on say
riscv __LIBGCC_DWARF_FRAME_REGISTERS__ is I think 128, on powerpc 111,
on sh 153 etc. And, we memset to zero the whole fs variable with the
_Unwind_FrameState type at the start of the unwinding.
The reason why each element is 16 byte (on 64-bit arches) is that it
contains some pointer or pointer sized integer and then an enum (with just
7 different enumerators) + padding.
The following patch decreases it by moving the enum into a separate
array and using just one byte for each register in that second array.
We could compress it even more, say 4 bits per register, but I don't
want to uglify the code for it too much and make the accesses slower.
Furthermore, the clearing of the object can clear only thos how array
and members after it, because REG_UNSAVED enumerator (0) doesn't actually
need any pointer or pointer sized integer, it is just the other kinds
that need to have there something.
By doing this, on x86_64 the above numbers change to _Unwind_FrameState
type being now 264 bytes long, frame_state_reg_info 208 bytes and we
don't clear the first 144 bytes of the object, so the memset is 120 bytes,
so ~ 31% of the old clearing size. On riscv 64-bit assuming it has same
structure layout rules for the few types used there that would be
~ 2160 bytes of _Unwind_FrameState type before and ~ 1264 bytes after,
with the memset previously ~ 2160 bytes and after ~ 232 bytes after.
We've also talked about possibly adding a number of initially initialized
regs and initializing the rest lazily, but at least for x86_64 with
18 elements in the array that doesn't seem to be worth it anymore,
especially because return address column is 16 there and that is usually the
first thing to be touched. It might theory help with lots of registers if
they are usually untouched, but would uglify and complicate any stores to
how by having to check there for the not initialized yet cases and lazy
initialization, and similarly for all reads of how to do there if below
last initialized one, use how, otherwise imply REG_UNSAVED.
The disadvantage of the patch is that touching reg[x].loc and how[x]
now means 2 cachelines rather than one as before, and I admit beyond
bootstrap/regtest I haven't benchmarked it in any way.
2022-10-06 Jakub Jelinek <jakub@redhat.com>
* unwind-dw2.h (REG_UNSAVED, REG_SAVED_OFFSET, REG_SAVED_REG,
REG_SAVED_EXP, REG_SAVED_VAL_OFFSET, REG_SAVED_VAL_EXP,
REG_UNDEFINED): New anonymous enum, moved from inside of
struct frame_state_reg_info.
(struct frame_state_reg_info): Remove reg[].how element and the
anonymous enum there. Add how element.
* unwind-dw2.c: Include stddef.h.
(uw_frame_state_for): Don't clear first
offsetof (_Unwind_FrameState, regs.how[0]) bytes of *fs.
(execute_cfa_program, __frame_state_for, uw_update_context_1,
uw_update_context): Use fs->regs.how[X] instead of fs->regs.reg[X].how
or fs.regs.how[X] instead of fs.regs.reg[X].how.
* config/sh/linux-unwind.h (sh_fallback_frame_state): Likewise.
* config/bfin/linux-unwind.h (bfin_fallback_frame_state): Likewise.
* config/pa/linux-unwind.h (pa32_fallback_frame_state): Likewise.
* config/pa/hpux-unwind.h (UPDATE_FS_FOR_SAR, UPDATE_FS_FOR_GR,
UPDATE_FS_FOR_FR, UPDATE_FS_FOR_PC, pa_fallback_frame_state):
Likewise.
* config/alpha/vms-unwind.h (alpha_vms_fallback_frame_state):
Likewise.
* config/alpha/linux-unwind.h (alpha_fallback_frame_state): Likewise.
* config/arc/linux-unwind.h (arc_fallback_frame_state,
arc_frob_update_context): Likewise.
* config/riscv/linux-unwind.h (riscv_fallback_frame_state): Likewise.
* config/nios2/linux-unwind.h (NIOS2_REG): Likewise.
* config/nds32/linux-unwind.h (NDS32_PUT_FS_REG): Likewise.
* config/s390/tpf-unwind.h (s390_fallback_frame_state): Likewise.
* config/s390/linux-unwind.h (s390_fallback_frame_state): Likewise.
* config/sparc/sol2-unwind.h (sparc64_frob_update_context,
MD_FALLBACK_FRAME_STATE_FOR): Likewise.
* config/sparc/linux-unwind.h (sparc64_fallback_frame_state,
sparc64_frob_update_context, sparc_fallback_frame_state): Likewise.
* config/i386/sol2-unwind.h (x86_64_fallback_frame_state,
x86_fallback_frame_state): Likewise.
* config/i386/w32-unwind.h (i386_w32_fallback_frame_state): Likewise.
* config/i386/linux-unwind.h (x86_64_fallback_frame_state,
x86_fallback_frame_state): Likewise.
* config/i386/freebsd-unwind.h (x86_64_freebsd_fallback_frame_state):
Likewise.
* config/i386/dragonfly-unwind.h
(x86_64_dragonfly_fallback_frame_state): Likewise.
* config/i386/gnu-unwind.h (x86_gnu_fallback_frame_state): Likewise.
* config/csky/linux-unwind.h (csky_fallback_frame_state): Likewise.
* config/aarch64/linux-unwind.h (aarch64_fallback_frame_state):
Likewise.
* config/aarch64/freebsd-unwind.h
(aarch64_freebsd_fallback_frame_state): Likewise.
* config/aarch64/aarch64-unwind.h (aarch64_frob_update_context):
Likewise.
* config/or1k/linux-unwind.h (or1k_fallback_frame_state): Likewise.
* config/mips/linux-unwind.h (mips_fallback_frame_state): Likewise.
* config/loongarch/linux-unwind.h (loongarch_fallback_frame_state):
Likewise.
* config/m68k/linux-unwind.h (m68k_fallback_frame_state): Likewise.
* config/xtensa/linux-unwind.h (xtensa_fallback_frame_state):
Likewise.
* config/rs6000/darwin-fallback.c (set_offset): Likewise.
* config/rs6000/aix-unwind.h (MD_FROB_UPDATE_CONTEXT): Likewise.
* config/rs6000/linux-unwind.h (ppc_fallback_frame_state): Likewise.
* config/rs6000/freebsd-unwind.h (frob_update_context): Likewise.
2022-10-06 11:04:52 +02:00
|
|
|
fs->regs.how[0] = REG_SAVED_OFFSET;
|
2009-10-11 20:06:12 +00:00
|
|
|
fs->regs.reg[0].loc.offset = (long)&mctx->gregs[EAX] - new_cfa;
|
libgcc: Decrease size of _Unwind_FrameState and even more size of cleared area in uw_frame_state_for
The following patch implements something that has Florian found as
low hanging fruit in our unwinder and has been discussed in the
https://gcc.gnu.org/wiki/cauldron2022#cauldron2022talks.inprocess_unwinding_bof
talk.
_Unwind_FrameState type seems to be (unlike the pre-GCC 3 frame_state
which has been part of ABI) private to unwind-dw2.c + unwind.inc it
includes, it is always defined on the stack of some entrypoints, initialized
by static uw_frame_state_for and the address of it is also passed to other
static functions or the static inlines handling machine dependent unwinding,
but it isn't fortunately passed to any callbacks or public functions, so I
think we can safely change it any time we want.
Florian mentioned that the structure is large even on x86_64, 384 bytes
there, starts with 328 bytes long element with frame_state_reg_info type
which then starts with an array with __LIBGCC_DWARF_FRAME_REGISTERS__ + 1
elements, each of them is 16 bytes long, on x86_64
__LIBGCC_DWARF_FRAME_REGISTERS__ is just 17 but even that is big, on say
riscv __LIBGCC_DWARF_FRAME_REGISTERS__ is I think 128, on powerpc 111,
on sh 153 etc. And, we memset to zero the whole fs variable with the
_Unwind_FrameState type at the start of the unwinding.
The reason why each element is 16 byte (on 64-bit arches) is that it
contains some pointer or pointer sized integer and then an enum (with just
7 different enumerators) + padding.
The following patch decreases it by moving the enum into a separate
array and using just one byte for each register in that second array.
We could compress it even more, say 4 bits per register, but I don't
want to uglify the code for it too much and make the accesses slower.
Furthermore, the clearing of the object can clear only thos how array
and members after it, because REG_UNSAVED enumerator (0) doesn't actually
need any pointer or pointer sized integer, it is just the other kinds
that need to have there something.
By doing this, on x86_64 the above numbers change to _Unwind_FrameState
type being now 264 bytes long, frame_state_reg_info 208 bytes and we
don't clear the first 144 bytes of the object, so the memset is 120 bytes,
so ~ 31% of the old clearing size. On riscv 64-bit assuming it has same
structure layout rules for the few types used there that would be
~ 2160 bytes of _Unwind_FrameState type before and ~ 1264 bytes after,
with the memset previously ~ 2160 bytes and after ~ 232 bytes after.
We've also talked about possibly adding a number of initially initialized
regs and initializing the rest lazily, but at least for x86_64 with
18 elements in the array that doesn't seem to be worth it anymore,
especially because return address column is 16 there and that is usually the
first thing to be touched. It might theory help with lots of registers if
they are usually untouched, but would uglify and complicate any stores to
how by having to check there for the not initialized yet cases and lazy
initialization, and similarly for all reads of how to do there if below
last initialized one, use how, otherwise imply REG_UNSAVED.
The disadvantage of the patch is that touching reg[x].loc and how[x]
now means 2 cachelines rather than one as before, and I admit beyond
bootstrap/regtest I haven't benchmarked it in any way.
2022-10-06 Jakub Jelinek <jakub@redhat.com>
* unwind-dw2.h (REG_UNSAVED, REG_SAVED_OFFSET, REG_SAVED_REG,
REG_SAVED_EXP, REG_SAVED_VAL_OFFSET, REG_SAVED_VAL_EXP,
REG_UNDEFINED): New anonymous enum, moved from inside of
struct frame_state_reg_info.
(struct frame_state_reg_info): Remove reg[].how element and the
anonymous enum there. Add how element.
* unwind-dw2.c: Include stddef.h.
(uw_frame_state_for): Don't clear first
offsetof (_Unwind_FrameState, regs.how[0]) bytes of *fs.
(execute_cfa_program, __frame_state_for, uw_update_context_1,
uw_update_context): Use fs->regs.how[X] instead of fs->regs.reg[X].how
or fs.regs.how[X] instead of fs.regs.reg[X].how.
* config/sh/linux-unwind.h (sh_fallback_frame_state): Likewise.
* config/bfin/linux-unwind.h (bfin_fallback_frame_state): Likewise.
* config/pa/linux-unwind.h (pa32_fallback_frame_state): Likewise.
* config/pa/hpux-unwind.h (UPDATE_FS_FOR_SAR, UPDATE_FS_FOR_GR,
UPDATE_FS_FOR_FR, UPDATE_FS_FOR_PC, pa_fallback_frame_state):
Likewise.
* config/alpha/vms-unwind.h (alpha_vms_fallback_frame_state):
Likewise.
* config/alpha/linux-unwind.h (alpha_fallback_frame_state): Likewise.
* config/arc/linux-unwind.h (arc_fallback_frame_state,
arc_frob_update_context): Likewise.
* config/riscv/linux-unwind.h (riscv_fallback_frame_state): Likewise.
* config/nios2/linux-unwind.h (NIOS2_REG): Likewise.
* config/nds32/linux-unwind.h (NDS32_PUT_FS_REG): Likewise.
* config/s390/tpf-unwind.h (s390_fallback_frame_state): Likewise.
* config/s390/linux-unwind.h (s390_fallback_frame_state): Likewise.
* config/sparc/sol2-unwind.h (sparc64_frob_update_context,
MD_FALLBACK_FRAME_STATE_FOR): Likewise.
* config/sparc/linux-unwind.h (sparc64_fallback_frame_state,
sparc64_frob_update_context, sparc_fallback_frame_state): Likewise.
* config/i386/sol2-unwind.h (x86_64_fallback_frame_state,
x86_fallback_frame_state): Likewise.
* config/i386/w32-unwind.h (i386_w32_fallback_frame_state): Likewise.
* config/i386/linux-unwind.h (x86_64_fallback_frame_state,
x86_fallback_frame_state): Likewise.
* config/i386/freebsd-unwind.h (x86_64_freebsd_fallback_frame_state):
Likewise.
* config/i386/dragonfly-unwind.h
(x86_64_dragonfly_fallback_frame_state): Likewise.
* config/i386/gnu-unwind.h (x86_gnu_fallback_frame_state): Likewise.
* config/csky/linux-unwind.h (csky_fallback_frame_state): Likewise.
* config/aarch64/linux-unwind.h (aarch64_fallback_frame_state):
Likewise.
* config/aarch64/freebsd-unwind.h
(aarch64_freebsd_fallback_frame_state): Likewise.
* config/aarch64/aarch64-unwind.h (aarch64_frob_update_context):
Likewise.
* config/or1k/linux-unwind.h (or1k_fallback_frame_state): Likewise.
* config/mips/linux-unwind.h (mips_fallback_frame_state): Likewise.
* config/loongarch/linux-unwind.h (loongarch_fallback_frame_state):
Likewise.
* config/m68k/linux-unwind.h (m68k_fallback_frame_state): Likewise.
* config/xtensa/linux-unwind.h (xtensa_fallback_frame_state):
Likewise.
* config/rs6000/darwin-fallback.c (set_offset): Likewise.
* config/rs6000/aix-unwind.h (MD_FROB_UPDATE_CONTEXT): Likewise.
* config/rs6000/linux-unwind.h (ppc_fallback_frame_state): Likewise.
* config/rs6000/freebsd-unwind.h (frob_update_context): Likewise.
2022-10-06 11:04:52 +02:00
|
|
|
fs->regs.how[3] = REG_SAVED_OFFSET;
|
2009-10-11 20:06:12 +00:00
|
|
|
fs->regs.reg[3].loc.offset = (long)&mctx->gregs[EBX] - new_cfa;
|
libgcc: Decrease size of _Unwind_FrameState and even more size of cleared area in uw_frame_state_for
The following patch implements something that has Florian found as
low hanging fruit in our unwinder and has been discussed in the
https://gcc.gnu.org/wiki/cauldron2022#cauldron2022talks.inprocess_unwinding_bof
talk.
_Unwind_FrameState type seems to be (unlike the pre-GCC 3 frame_state
which has been part of ABI) private to unwind-dw2.c + unwind.inc it
includes, it is always defined on the stack of some entrypoints, initialized
by static uw_frame_state_for and the address of it is also passed to other
static functions or the static inlines handling machine dependent unwinding,
but it isn't fortunately passed to any callbacks or public functions, so I
think we can safely change it any time we want.
Florian mentioned that the structure is large even on x86_64, 384 bytes
there, starts with 328 bytes long element with frame_state_reg_info type
which then starts with an array with __LIBGCC_DWARF_FRAME_REGISTERS__ + 1
elements, each of them is 16 bytes long, on x86_64
__LIBGCC_DWARF_FRAME_REGISTERS__ is just 17 but even that is big, on say
riscv __LIBGCC_DWARF_FRAME_REGISTERS__ is I think 128, on powerpc 111,
on sh 153 etc. And, we memset to zero the whole fs variable with the
_Unwind_FrameState type at the start of the unwinding.
The reason why each element is 16 byte (on 64-bit arches) is that it
contains some pointer or pointer sized integer and then an enum (with just
7 different enumerators) + padding.
The following patch decreases it by moving the enum into a separate
array and using just one byte for each register in that second array.
We could compress it even more, say 4 bits per register, but I don't
want to uglify the code for it too much and make the accesses slower.
Furthermore, the clearing of the object can clear only thos how array
and members after it, because REG_UNSAVED enumerator (0) doesn't actually
need any pointer or pointer sized integer, it is just the other kinds
that need to have there something.
By doing this, on x86_64 the above numbers change to _Unwind_FrameState
type being now 264 bytes long, frame_state_reg_info 208 bytes and we
don't clear the first 144 bytes of the object, so the memset is 120 bytes,
so ~ 31% of the old clearing size. On riscv 64-bit assuming it has same
structure layout rules for the few types used there that would be
~ 2160 bytes of _Unwind_FrameState type before and ~ 1264 bytes after,
with the memset previously ~ 2160 bytes and after ~ 232 bytes after.
We've also talked about possibly adding a number of initially initialized
regs and initializing the rest lazily, but at least for x86_64 with
18 elements in the array that doesn't seem to be worth it anymore,
especially because return address column is 16 there and that is usually the
first thing to be touched. It might theory help with lots of registers if
they are usually untouched, but would uglify and complicate any stores to
how by having to check there for the not initialized yet cases and lazy
initialization, and similarly for all reads of how to do there if below
last initialized one, use how, otherwise imply REG_UNSAVED.
The disadvantage of the patch is that touching reg[x].loc and how[x]
now means 2 cachelines rather than one as before, and I admit beyond
bootstrap/regtest I haven't benchmarked it in any way.
2022-10-06 Jakub Jelinek <jakub@redhat.com>
* unwind-dw2.h (REG_UNSAVED, REG_SAVED_OFFSET, REG_SAVED_REG,
REG_SAVED_EXP, REG_SAVED_VAL_OFFSET, REG_SAVED_VAL_EXP,
REG_UNDEFINED): New anonymous enum, moved from inside of
struct frame_state_reg_info.
(struct frame_state_reg_info): Remove reg[].how element and the
anonymous enum there. Add how element.
* unwind-dw2.c: Include stddef.h.
(uw_frame_state_for): Don't clear first
offsetof (_Unwind_FrameState, regs.how[0]) bytes of *fs.
(execute_cfa_program, __frame_state_for, uw_update_context_1,
uw_update_context): Use fs->regs.how[X] instead of fs->regs.reg[X].how
or fs.regs.how[X] instead of fs.regs.reg[X].how.
* config/sh/linux-unwind.h (sh_fallback_frame_state): Likewise.
* config/bfin/linux-unwind.h (bfin_fallback_frame_state): Likewise.
* config/pa/linux-unwind.h (pa32_fallback_frame_state): Likewise.
* config/pa/hpux-unwind.h (UPDATE_FS_FOR_SAR, UPDATE_FS_FOR_GR,
UPDATE_FS_FOR_FR, UPDATE_FS_FOR_PC, pa_fallback_frame_state):
Likewise.
* config/alpha/vms-unwind.h (alpha_vms_fallback_frame_state):
Likewise.
* config/alpha/linux-unwind.h (alpha_fallback_frame_state): Likewise.
* config/arc/linux-unwind.h (arc_fallback_frame_state,
arc_frob_update_context): Likewise.
* config/riscv/linux-unwind.h (riscv_fallback_frame_state): Likewise.
* config/nios2/linux-unwind.h (NIOS2_REG): Likewise.
* config/nds32/linux-unwind.h (NDS32_PUT_FS_REG): Likewise.
* config/s390/tpf-unwind.h (s390_fallback_frame_state): Likewise.
* config/s390/linux-unwind.h (s390_fallback_frame_state): Likewise.
* config/sparc/sol2-unwind.h (sparc64_frob_update_context,
MD_FALLBACK_FRAME_STATE_FOR): Likewise.
* config/sparc/linux-unwind.h (sparc64_fallback_frame_state,
sparc64_frob_update_context, sparc_fallback_frame_state): Likewise.
* config/i386/sol2-unwind.h (x86_64_fallback_frame_state,
x86_fallback_frame_state): Likewise.
* config/i386/w32-unwind.h (i386_w32_fallback_frame_state): Likewise.
* config/i386/linux-unwind.h (x86_64_fallback_frame_state,
x86_fallback_frame_state): Likewise.
* config/i386/freebsd-unwind.h (x86_64_freebsd_fallback_frame_state):
Likewise.
* config/i386/dragonfly-unwind.h
(x86_64_dragonfly_fallback_frame_state): Likewise.
* config/i386/gnu-unwind.h (x86_gnu_fallback_frame_state): Likewise.
* config/csky/linux-unwind.h (csky_fallback_frame_state): Likewise.
* config/aarch64/linux-unwind.h (aarch64_fallback_frame_state):
Likewise.
* config/aarch64/freebsd-unwind.h
(aarch64_freebsd_fallback_frame_state): Likewise.
* config/aarch64/aarch64-unwind.h (aarch64_frob_update_context):
Likewise.
* config/or1k/linux-unwind.h (or1k_fallback_frame_state): Likewise.
* config/mips/linux-unwind.h (mips_fallback_frame_state): Likewise.
* config/loongarch/linux-unwind.h (loongarch_fallback_frame_state):
Likewise.
* config/m68k/linux-unwind.h (m68k_fallback_frame_state): Likewise.
* config/xtensa/linux-unwind.h (xtensa_fallback_frame_state):
Likewise.
* config/rs6000/darwin-fallback.c (set_offset): Likewise.
* config/rs6000/aix-unwind.h (MD_FROB_UPDATE_CONTEXT): Likewise.
* config/rs6000/linux-unwind.h (ppc_fallback_frame_state): Likewise.
* config/rs6000/freebsd-unwind.h (frob_update_context): Likewise.
2022-10-06 11:04:52 +02:00
|
|
|
fs->regs.how[1] = REG_SAVED_OFFSET;
|
2009-10-11 20:06:12 +00:00
|
|
|
fs->regs.reg[1].loc.offset = (long)&mctx->gregs[ECX] - new_cfa;
|
libgcc: Decrease size of _Unwind_FrameState and even more size of cleared area in uw_frame_state_for
The following patch implements something that has Florian found as
low hanging fruit in our unwinder and has been discussed in the
https://gcc.gnu.org/wiki/cauldron2022#cauldron2022talks.inprocess_unwinding_bof
talk.
_Unwind_FrameState type seems to be (unlike the pre-GCC 3 frame_state
which has been part of ABI) private to unwind-dw2.c + unwind.inc it
includes, it is always defined on the stack of some entrypoints, initialized
by static uw_frame_state_for and the address of it is also passed to other
static functions or the static inlines handling machine dependent unwinding,
but it isn't fortunately passed to any callbacks or public functions, so I
think we can safely change it any time we want.
Florian mentioned that the structure is large even on x86_64, 384 bytes
there, starts with 328 bytes long element with frame_state_reg_info type
which then starts with an array with __LIBGCC_DWARF_FRAME_REGISTERS__ + 1
elements, each of them is 16 bytes long, on x86_64
__LIBGCC_DWARF_FRAME_REGISTERS__ is just 17 but even that is big, on say
riscv __LIBGCC_DWARF_FRAME_REGISTERS__ is I think 128, on powerpc 111,
on sh 153 etc. And, we memset to zero the whole fs variable with the
_Unwind_FrameState type at the start of the unwinding.
The reason why each element is 16 byte (on 64-bit arches) is that it
contains some pointer or pointer sized integer and then an enum (with just
7 different enumerators) + padding.
The following patch decreases it by moving the enum into a separate
array and using just one byte for each register in that second array.
We could compress it even more, say 4 bits per register, but I don't
want to uglify the code for it too much and make the accesses slower.
Furthermore, the clearing of the object can clear only thos how array
and members after it, because REG_UNSAVED enumerator (0) doesn't actually
need any pointer or pointer sized integer, it is just the other kinds
that need to have there something.
By doing this, on x86_64 the above numbers change to _Unwind_FrameState
type being now 264 bytes long, frame_state_reg_info 208 bytes and we
don't clear the first 144 bytes of the object, so the memset is 120 bytes,
so ~ 31% of the old clearing size. On riscv 64-bit assuming it has same
structure layout rules for the few types used there that would be
~ 2160 bytes of _Unwind_FrameState type before and ~ 1264 bytes after,
with the memset previously ~ 2160 bytes and after ~ 232 bytes after.
We've also talked about possibly adding a number of initially initialized
regs and initializing the rest lazily, but at least for x86_64 with
18 elements in the array that doesn't seem to be worth it anymore,
especially because return address column is 16 there and that is usually the
first thing to be touched. It might theory help with lots of registers if
they are usually untouched, but would uglify and complicate any stores to
how by having to check there for the not initialized yet cases and lazy
initialization, and similarly for all reads of how to do there if below
last initialized one, use how, otherwise imply REG_UNSAVED.
The disadvantage of the patch is that touching reg[x].loc and how[x]
now means 2 cachelines rather than one as before, and I admit beyond
bootstrap/regtest I haven't benchmarked it in any way.
2022-10-06 Jakub Jelinek <jakub@redhat.com>
* unwind-dw2.h (REG_UNSAVED, REG_SAVED_OFFSET, REG_SAVED_REG,
REG_SAVED_EXP, REG_SAVED_VAL_OFFSET, REG_SAVED_VAL_EXP,
REG_UNDEFINED): New anonymous enum, moved from inside of
struct frame_state_reg_info.
(struct frame_state_reg_info): Remove reg[].how element and the
anonymous enum there. Add how element.
* unwind-dw2.c: Include stddef.h.
(uw_frame_state_for): Don't clear first
offsetof (_Unwind_FrameState, regs.how[0]) bytes of *fs.
(execute_cfa_program, __frame_state_for, uw_update_context_1,
uw_update_context): Use fs->regs.how[X] instead of fs->regs.reg[X].how
or fs.regs.how[X] instead of fs.regs.reg[X].how.
* config/sh/linux-unwind.h (sh_fallback_frame_state): Likewise.
* config/bfin/linux-unwind.h (bfin_fallback_frame_state): Likewise.
* config/pa/linux-unwind.h (pa32_fallback_frame_state): Likewise.
* config/pa/hpux-unwind.h (UPDATE_FS_FOR_SAR, UPDATE_FS_FOR_GR,
UPDATE_FS_FOR_FR, UPDATE_FS_FOR_PC, pa_fallback_frame_state):
Likewise.
* config/alpha/vms-unwind.h (alpha_vms_fallback_frame_state):
Likewise.
* config/alpha/linux-unwind.h (alpha_fallback_frame_state): Likewise.
* config/arc/linux-unwind.h (arc_fallback_frame_state,
arc_frob_update_context): Likewise.
* config/riscv/linux-unwind.h (riscv_fallback_frame_state): Likewise.
* config/nios2/linux-unwind.h (NIOS2_REG): Likewise.
* config/nds32/linux-unwind.h (NDS32_PUT_FS_REG): Likewise.
* config/s390/tpf-unwind.h (s390_fallback_frame_state): Likewise.
* config/s390/linux-unwind.h (s390_fallback_frame_state): Likewise.
* config/sparc/sol2-unwind.h (sparc64_frob_update_context,
MD_FALLBACK_FRAME_STATE_FOR): Likewise.
* config/sparc/linux-unwind.h (sparc64_fallback_frame_state,
sparc64_frob_update_context, sparc_fallback_frame_state): Likewise.
* config/i386/sol2-unwind.h (x86_64_fallback_frame_state,
x86_fallback_frame_state): Likewise.
* config/i386/w32-unwind.h (i386_w32_fallback_frame_state): Likewise.
* config/i386/linux-unwind.h (x86_64_fallback_frame_state,
x86_fallback_frame_state): Likewise.
* config/i386/freebsd-unwind.h (x86_64_freebsd_fallback_frame_state):
Likewise.
* config/i386/dragonfly-unwind.h
(x86_64_dragonfly_fallback_frame_state): Likewise.
* config/i386/gnu-unwind.h (x86_gnu_fallback_frame_state): Likewise.
* config/csky/linux-unwind.h (csky_fallback_frame_state): Likewise.
* config/aarch64/linux-unwind.h (aarch64_fallback_frame_state):
Likewise.
* config/aarch64/freebsd-unwind.h
(aarch64_freebsd_fallback_frame_state): Likewise.
* config/aarch64/aarch64-unwind.h (aarch64_frob_update_context):
Likewise.
* config/or1k/linux-unwind.h (or1k_fallback_frame_state): Likewise.
* config/mips/linux-unwind.h (mips_fallback_frame_state): Likewise.
* config/loongarch/linux-unwind.h (loongarch_fallback_frame_state):
Likewise.
* config/m68k/linux-unwind.h (m68k_fallback_frame_state): Likewise.
* config/xtensa/linux-unwind.h (xtensa_fallback_frame_state):
Likewise.
* config/rs6000/darwin-fallback.c (set_offset): Likewise.
* config/rs6000/aix-unwind.h (MD_FROB_UPDATE_CONTEXT): Likewise.
* config/rs6000/linux-unwind.h (ppc_fallback_frame_state): Likewise.
* config/rs6000/freebsd-unwind.h (frob_update_context): Likewise.
2022-10-06 11:04:52 +02:00
|
|
|
fs->regs.how[2] = REG_SAVED_OFFSET;
|
2009-10-11 20:06:12 +00:00
|
|
|
fs->regs.reg[2].loc.offset = (long)&mctx->gregs[EDX] - new_cfa;
|
libgcc: Decrease size of _Unwind_FrameState and even more size of cleared area in uw_frame_state_for
The following patch implements something that has Florian found as
low hanging fruit in our unwinder and has been discussed in the
https://gcc.gnu.org/wiki/cauldron2022#cauldron2022talks.inprocess_unwinding_bof
talk.
_Unwind_FrameState type seems to be (unlike the pre-GCC 3 frame_state
which has been part of ABI) private to unwind-dw2.c + unwind.inc it
includes, it is always defined on the stack of some entrypoints, initialized
by static uw_frame_state_for and the address of it is also passed to other
static functions or the static inlines handling machine dependent unwinding,
but it isn't fortunately passed to any callbacks or public functions, so I
think we can safely change it any time we want.
Florian mentioned that the structure is large even on x86_64, 384 bytes
there, starts with 328 bytes long element with frame_state_reg_info type
which then starts with an array with __LIBGCC_DWARF_FRAME_REGISTERS__ + 1
elements, each of them is 16 bytes long, on x86_64
__LIBGCC_DWARF_FRAME_REGISTERS__ is just 17 but even that is big, on say
riscv __LIBGCC_DWARF_FRAME_REGISTERS__ is I think 128, on powerpc 111,
on sh 153 etc. And, we memset to zero the whole fs variable with the
_Unwind_FrameState type at the start of the unwinding.
The reason why each element is 16 byte (on 64-bit arches) is that it
contains some pointer or pointer sized integer and then an enum (with just
7 different enumerators) + padding.
The following patch decreases it by moving the enum into a separate
array and using just one byte for each register in that second array.
We could compress it even more, say 4 bits per register, but I don't
want to uglify the code for it too much and make the accesses slower.
Furthermore, the clearing of the object can clear only thos how array
and members after it, because REG_UNSAVED enumerator (0) doesn't actually
need any pointer or pointer sized integer, it is just the other kinds
that need to have there something.
By doing this, on x86_64 the above numbers change to _Unwind_FrameState
type being now 264 bytes long, frame_state_reg_info 208 bytes and we
don't clear the first 144 bytes of the object, so the memset is 120 bytes,
so ~ 31% of the old clearing size. On riscv 64-bit assuming it has same
structure layout rules for the few types used there that would be
~ 2160 bytes of _Unwind_FrameState type before and ~ 1264 bytes after,
with the memset previously ~ 2160 bytes and after ~ 232 bytes after.
We've also talked about possibly adding a number of initially initialized
regs and initializing the rest lazily, but at least for x86_64 with
18 elements in the array that doesn't seem to be worth it anymore,
especially because return address column is 16 there and that is usually the
first thing to be touched. It might theory help with lots of registers if
they are usually untouched, but would uglify and complicate any stores to
how by having to check there for the not initialized yet cases and lazy
initialization, and similarly for all reads of how to do there if below
last initialized one, use how, otherwise imply REG_UNSAVED.
The disadvantage of the patch is that touching reg[x].loc and how[x]
now means 2 cachelines rather than one as before, and I admit beyond
bootstrap/regtest I haven't benchmarked it in any way.
2022-10-06 Jakub Jelinek <jakub@redhat.com>
* unwind-dw2.h (REG_UNSAVED, REG_SAVED_OFFSET, REG_SAVED_REG,
REG_SAVED_EXP, REG_SAVED_VAL_OFFSET, REG_SAVED_VAL_EXP,
REG_UNDEFINED): New anonymous enum, moved from inside of
struct frame_state_reg_info.
(struct frame_state_reg_info): Remove reg[].how element and the
anonymous enum there. Add how element.
* unwind-dw2.c: Include stddef.h.
(uw_frame_state_for): Don't clear first
offsetof (_Unwind_FrameState, regs.how[0]) bytes of *fs.
(execute_cfa_program, __frame_state_for, uw_update_context_1,
uw_update_context): Use fs->regs.how[X] instead of fs->regs.reg[X].how
or fs.regs.how[X] instead of fs.regs.reg[X].how.
* config/sh/linux-unwind.h (sh_fallback_frame_state): Likewise.
* config/bfin/linux-unwind.h (bfin_fallback_frame_state): Likewise.
* config/pa/linux-unwind.h (pa32_fallback_frame_state): Likewise.
* config/pa/hpux-unwind.h (UPDATE_FS_FOR_SAR, UPDATE_FS_FOR_GR,
UPDATE_FS_FOR_FR, UPDATE_FS_FOR_PC, pa_fallback_frame_state):
Likewise.
* config/alpha/vms-unwind.h (alpha_vms_fallback_frame_state):
Likewise.
* config/alpha/linux-unwind.h (alpha_fallback_frame_state): Likewise.
* config/arc/linux-unwind.h (arc_fallback_frame_state,
arc_frob_update_context): Likewise.
* config/riscv/linux-unwind.h (riscv_fallback_frame_state): Likewise.
* config/nios2/linux-unwind.h (NIOS2_REG): Likewise.
* config/nds32/linux-unwind.h (NDS32_PUT_FS_REG): Likewise.
* config/s390/tpf-unwind.h (s390_fallback_frame_state): Likewise.
* config/s390/linux-unwind.h (s390_fallback_frame_state): Likewise.
* config/sparc/sol2-unwind.h (sparc64_frob_update_context,
MD_FALLBACK_FRAME_STATE_FOR): Likewise.
* config/sparc/linux-unwind.h (sparc64_fallback_frame_state,
sparc64_frob_update_context, sparc_fallback_frame_state): Likewise.
* config/i386/sol2-unwind.h (x86_64_fallback_frame_state,
x86_fallback_frame_state): Likewise.
* config/i386/w32-unwind.h (i386_w32_fallback_frame_state): Likewise.
* config/i386/linux-unwind.h (x86_64_fallback_frame_state,
x86_fallback_frame_state): Likewise.
* config/i386/freebsd-unwind.h (x86_64_freebsd_fallback_frame_state):
Likewise.
* config/i386/dragonfly-unwind.h
(x86_64_dragonfly_fallback_frame_state): Likewise.
* config/i386/gnu-unwind.h (x86_gnu_fallback_frame_state): Likewise.
* config/csky/linux-unwind.h (csky_fallback_frame_state): Likewise.
* config/aarch64/linux-unwind.h (aarch64_fallback_frame_state):
Likewise.
* config/aarch64/freebsd-unwind.h
(aarch64_freebsd_fallback_frame_state): Likewise.
* config/aarch64/aarch64-unwind.h (aarch64_frob_update_context):
Likewise.
* config/or1k/linux-unwind.h (or1k_fallback_frame_state): Likewise.
* config/mips/linux-unwind.h (mips_fallback_frame_state): Likewise.
* config/loongarch/linux-unwind.h (loongarch_fallback_frame_state):
Likewise.
* config/m68k/linux-unwind.h (m68k_fallback_frame_state): Likewise.
* config/xtensa/linux-unwind.h (xtensa_fallback_frame_state):
Likewise.
* config/rs6000/darwin-fallback.c (set_offset): Likewise.
* config/rs6000/aix-unwind.h (MD_FROB_UPDATE_CONTEXT): Likewise.
* config/rs6000/linux-unwind.h (ppc_fallback_frame_state): Likewise.
* config/rs6000/freebsd-unwind.h (frob_update_context): Likewise.
2022-10-06 11:04:52 +02:00
|
|
|
fs->regs.how[6] = REG_SAVED_OFFSET;
|
2009-10-11 20:06:12 +00:00
|
|
|
fs->regs.reg[6].loc.offset = (long)&mctx->gregs[ESI] - new_cfa;
|
libgcc: Decrease size of _Unwind_FrameState and even more size of cleared area in uw_frame_state_for
The following patch implements something that has Florian found as
low hanging fruit in our unwinder and has been discussed in the
https://gcc.gnu.org/wiki/cauldron2022#cauldron2022talks.inprocess_unwinding_bof
talk.
_Unwind_FrameState type seems to be (unlike the pre-GCC 3 frame_state
which has been part of ABI) private to unwind-dw2.c + unwind.inc it
includes, it is always defined on the stack of some entrypoints, initialized
by static uw_frame_state_for and the address of it is also passed to other
static functions or the static inlines handling machine dependent unwinding,
but it isn't fortunately passed to any callbacks or public functions, so I
think we can safely change it any time we want.
Florian mentioned that the structure is large even on x86_64, 384 bytes
there, starts with 328 bytes long element with frame_state_reg_info type
which then starts with an array with __LIBGCC_DWARF_FRAME_REGISTERS__ + 1
elements, each of them is 16 bytes long, on x86_64
__LIBGCC_DWARF_FRAME_REGISTERS__ is just 17 but even that is big, on say
riscv __LIBGCC_DWARF_FRAME_REGISTERS__ is I think 128, on powerpc 111,
on sh 153 etc. And, we memset to zero the whole fs variable with the
_Unwind_FrameState type at the start of the unwinding.
The reason why each element is 16 byte (on 64-bit arches) is that it
contains some pointer or pointer sized integer and then an enum (with just
7 different enumerators) + padding.
The following patch decreases it by moving the enum into a separate
array and using just one byte for each register in that second array.
We could compress it even more, say 4 bits per register, but I don't
want to uglify the code for it too much and make the accesses slower.
Furthermore, the clearing of the object can clear only thos how array
and members after it, because REG_UNSAVED enumerator (0) doesn't actually
need any pointer or pointer sized integer, it is just the other kinds
that need to have there something.
By doing this, on x86_64 the above numbers change to _Unwind_FrameState
type being now 264 bytes long, frame_state_reg_info 208 bytes and we
don't clear the first 144 bytes of the object, so the memset is 120 bytes,
so ~ 31% of the old clearing size. On riscv 64-bit assuming it has same
structure layout rules for the few types used there that would be
~ 2160 bytes of _Unwind_FrameState type before and ~ 1264 bytes after,
with the memset previously ~ 2160 bytes and after ~ 232 bytes after.
We've also talked about possibly adding a number of initially initialized
regs and initializing the rest lazily, but at least for x86_64 with
18 elements in the array that doesn't seem to be worth it anymore,
especially because return address column is 16 there and that is usually the
first thing to be touched. It might theory help with lots of registers if
they are usually untouched, but would uglify and complicate any stores to
how by having to check there for the not initialized yet cases and lazy
initialization, and similarly for all reads of how to do there if below
last initialized one, use how, otherwise imply REG_UNSAVED.
The disadvantage of the patch is that touching reg[x].loc and how[x]
now means 2 cachelines rather than one as before, and I admit beyond
bootstrap/regtest I haven't benchmarked it in any way.
2022-10-06 Jakub Jelinek <jakub@redhat.com>
* unwind-dw2.h (REG_UNSAVED, REG_SAVED_OFFSET, REG_SAVED_REG,
REG_SAVED_EXP, REG_SAVED_VAL_OFFSET, REG_SAVED_VAL_EXP,
REG_UNDEFINED): New anonymous enum, moved from inside of
struct frame_state_reg_info.
(struct frame_state_reg_info): Remove reg[].how element and the
anonymous enum there. Add how element.
* unwind-dw2.c: Include stddef.h.
(uw_frame_state_for): Don't clear first
offsetof (_Unwind_FrameState, regs.how[0]) bytes of *fs.
(execute_cfa_program, __frame_state_for, uw_update_context_1,
uw_update_context): Use fs->regs.how[X] instead of fs->regs.reg[X].how
or fs.regs.how[X] instead of fs.regs.reg[X].how.
* config/sh/linux-unwind.h (sh_fallback_frame_state): Likewise.
* config/bfin/linux-unwind.h (bfin_fallback_frame_state): Likewise.
* config/pa/linux-unwind.h (pa32_fallback_frame_state): Likewise.
* config/pa/hpux-unwind.h (UPDATE_FS_FOR_SAR, UPDATE_FS_FOR_GR,
UPDATE_FS_FOR_FR, UPDATE_FS_FOR_PC, pa_fallback_frame_state):
Likewise.
* config/alpha/vms-unwind.h (alpha_vms_fallback_frame_state):
Likewise.
* config/alpha/linux-unwind.h (alpha_fallback_frame_state): Likewise.
* config/arc/linux-unwind.h (arc_fallback_frame_state,
arc_frob_update_context): Likewise.
* config/riscv/linux-unwind.h (riscv_fallback_frame_state): Likewise.
* config/nios2/linux-unwind.h (NIOS2_REG): Likewise.
* config/nds32/linux-unwind.h (NDS32_PUT_FS_REG): Likewise.
* config/s390/tpf-unwind.h (s390_fallback_frame_state): Likewise.
* config/s390/linux-unwind.h (s390_fallback_frame_state): Likewise.
* config/sparc/sol2-unwind.h (sparc64_frob_update_context,
MD_FALLBACK_FRAME_STATE_FOR): Likewise.
* config/sparc/linux-unwind.h (sparc64_fallback_frame_state,
sparc64_frob_update_context, sparc_fallback_frame_state): Likewise.
* config/i386/sol2-unwind.h (x86_64_fallback_frame_state,
x86_fallback_frame_state): Likewise.
* config/i386/w32-unwind.h (i386_w32_fallback_frame_state): Likewise.
* config/i386/linux-unwind.h (x86_64_fallback_frame_state,
x86_fallback_frame_state): Likewise.
* config/i386/freebsd-unwind.h (x86_64_freebsd_fallback_frame_state):
Likewise.
* config/i386/dragonfly-unwind.h
(x86_64_dragonfly_fallback_frame_state): Likewise.
* config/i386/gnu-unwind.h (x86_gnu_fallback_frame_state): Likewise.
* config/csky/linux-unwind.h (csky_fallback_frame_state): Likewise.
* config/aarch64/linux-unwind.h (aarch64_fallback_frame_state):
Likewise.
* config/aarch64/freebsd-unwind.h
(aarch64_freebsd_fallback_frame_state): Likewise.
* config/aarch64/aarch64-unwind.h (aarch64_frob_update_context):
Likewise.
* config/or1k/linux-unwind.h (or1k_fallback_frame_state): Likewise.
* config/mips/linux-unwind.h (mips_fallback_frame_state): Likewise.
* config/loongarch/linux-unwind.h (loongarch_fallback_frame_state):
Likewise.
* config/m68k/linux-unwind.h (m68k_fallback_frame_state): Likewise.
* config/xtensa/linux-unwind.h (xtensa_fallback_frame_state):
Likewise.
* config/rs6000/darwin-fallback.c (set_offset): Likewise.
* config/rs6000/aix-unwind.h (MD_FROB_UPDATE_CONTEXT): Likewise.
* config/rs6000/linux-unwind.h (ppc_fallback_frame_state): Likewise.
* config/rs6000/freebsd-unwind.h (frob_update_context): Likewise.
2022-10-06 11:04:52 +02:00
|
|
|
fs->regs.how[7] = REG_SAVED_OFFSET;
|
2009-10-11 20:06:12 +00:00
|
|
|
fs->regs.reg[7].loc.offset = (long)&mctx->gregs[EDI] - new_cfa;
|
libgcc: Decrease size of _Unwind_FrameState and even more size of cleared area in uw_frame_state_for
The following patch implements something that has Florian found as
low hanging fruit in our unwinder and has been discussed in the
https://gcc.gnu.org/wiki/cauldron2022#cauldron2022talks.inprocess_unwinding_bof
talk.
_Unwind_FrameState type seems to be (unlike the pre-GCC 3 frame_state
which has been part of ABI) private to unwind-dw2.c + unwind.inc it
includes, it is always defined on the stack of some entrypoints, initialized
by static uw_frame_state_for and the address of it is also passed to other
static functions or the static inlines handling machine dependent unwinding,
but it isn't fortunately passed to any callbacks or public functions, so I
think we can safely change it any time we want.
Florian mentioned that the structure is large even on x86_64, 384 bytes
there, starts with 328 bytes long element with frame_state_reg_info type
which then starts with an array with __LIBGCC_DWARF_FRAME_REGISTERS__ + 1
elements, each of them is 16 bytes long, on x86_64
__LIBGCC_DWARF_FRAME_REGISTERS__ is just 17 but even that is big, on say
riscv __LIBGCC_DWARF_FRAME_REGISTERS__ is I think 128, on powerpc 111,
on sh 153 etc. And, we memset to zero the whole fs variable with the
_Unwind_FrameState type at the start of the unwinding.
The reason why each element is 16 byte (on 64-bit arches) is that it
contains some pointer or pointer sized integer and then an enum (with just
7 different enumerators) + padding.
The following patch decreases it by moving the enum into a separate
array and using just one byte for each register in that second array.
We could compress it even more, say 4 bits per register, but I don't
want to uglify the code for it too much and make the accesses slower.
Furthermore, the clearing of the object can clear only thos how array
and members after it, because REG_UNSAVED enumerator (0) doesn't actually
need any pointer or pointer sized integer, it is just the other kinds
that need to have there something.
By doing this, on x86_64 the above numbers change to _Unwind_FrameState
type being now 264 bytes long, frame_state_reg_info 208 bytes and we
don't clear the first 144 bytes of the object, so the memset is 120 bytes,
so ~ 31% of the old clearing size. On riscv 64-bit assuming it has same
structure layout rules for the few types used there that would be
~ 2160 bytes of _Unwind_FrameState type before and ~ 1264 bytes after,
with the memset previously ~ 2160 bytes and after ~ 232 bytes after.
We've also talked about possibly adding a number of initially initialized
regs and initializing the rest lazily, but at least for x86_64 with
18 elements in the array that doesn't seem to be worth it anymore,
especially because return address column is 16 there and that is usually the
first thing to be touched. It might theory help with lots of registers if
they are usually untouched, but would uglify and complicate any stores to
how by having to check there for the not initialized yet cases and lazy
initialization, and similarly for all reads of how to do there if below
last initialized one, use how, otherwise imply REG_UNSAVED.
The disadvantage of the patch is that touching reg[x].loc and how[x]
now means 2 cachelines rather than one as before, and I admit beyond
bootstrap/regtest I haven't benchmarked it in any way.
2022-10-06 Jakub Jelinek <jakub@redhat.com>
* unwind-dw2.h (REG_UNSAVED, REG_SAVED_OFFSET, REG_SAVED_REG,
REG_SAVED_EXP, REG_SAVED_VAL_OFFSET, REG_SAVED_VAL_EXP,
REG_UNDEFINED): New anonymous enum, moved from inside of
struct frame_state_reg_info.
(struct frame_state_reg_info): Remove reg[].how element and the
anonymous enum there. Add how element.
* unwind-dw2.c: Include stddef.h.
(uw_frame_state_for): Don't clear first
offsetof (_Unwind_FrameState, regs.how[0]) bytes of *fs.
(execute_cfa_program, __frame_state_for, uw_update_context_1,
uw_update_context): Use fs->regs.how[X] instead of fs->regs.reg[X].how
or fs.regs.how[X] instead of fs.regs.reg[X].how.
* config/sh/linux-unwind.h (sh_fallback_frame_state): Likewise.
* config/bfin/linux-unwind.h (bfin_fallback_frame_state): Likewise.
* config/pa/linux-unwind.h (pa32_fallback_frame_state): Likewise.
* config/pa/hpux-unwind.h (UPDATE_FS_FOR_SAR, UPDATE_FS_FOR_GR,
UPDATE_FS_FOR_FR, UPDATE_FS_FOR_PC, pa_fallback_frame_state):
Likewise.
* config/alpha/vms-unwind.h (alpha_vms_fallback_frame_state):
Likewise.
* config/alpha/linux-unwind.h (alpha_fallback_frame_state): Likewise.
* config/arc/linux-unwind.h (arc_fallback_frame_state,
arc_frob_update_context): Likewise.
* config/riscv/linux-unwind.h (riscv_fallback_frame_state): Likewise.
* config/nios2/linux-unwind.h (NIOS2_REG): Likewise.
* config/nds32/linux-unwind.h (NDS32_PUT_FS_REG): Likewise.
* config/s390/tpf-unwind.h (s390_fallback_frame_state): Likewise.
* config/s390/linux-unwind.h (s390_fallback_frame_state): Likewise.
* config/sparc/sol2-unwind.h (sparc64_frob_update_context,
MD_FALLBACK_FRAME_STATE_FOR): Likewise.
* config/sparc/linux-unwind.h (sparc64_fallback_frame_state,
sparc64_frob_update_context, sparc_fallback_frame_state): Likewise.
* config/i386/sol2-unwind.h (x86_64_fallback_frame_state,
x86_fallback_frame_state): Likewise.
* config/i386/w32-unwind.h (i386_w32_fallback_frame_state): Likewise.
* config/i386/linux-unwind.h (x86_64_fallback_frame_state,
x86_fallback_frame_state): Likewise.
* config/i386/freebsd-unwind.h (x86_64_freebsd_fallback_frame_state):
Likewise.
* config/i386/dragonfly-unwind.h
(x86_64_dragonfly_fallback_frame_state): Likewise.
* config/i386/gnu-unwind.h (x86_gnu_fallback_frame_state): Likewise.
* config/csky/linux-unwind.h (csky_fallback_frame_state): Likewise.
* config/aarch64/linux-unwind.h (aarch64_fallback_frame_state):
Likewise.
* config/aarch64/freebsd-unwind.h
(aarch64_freebsd_fallback_frame_state): Likewise.
* config/aarch64/aarch64-unwind.h (aarch64_frob_update_context):
Likewise.
* config/or1k/linux-unwind.h (or1k_fallback_frame_state): Likewise.
* config/mips/linux-unwind.h (mips_fallback_frame_state): Likewise.
* config/loongarch/linux-unwind.h (loongarch_fallback_frame_state):
Likewise.
* config/m68k/linux-unwind.h (m68k_fallback_frame_state): Likewise.
* config/xtensa/linux-unwind.h (xtensa_fallback_frame_state):
Likewise.
* config/rs6000/darwin-fallback.c (set_offset): Likewise.
* config/rs6000/aix-unwind.h (MD_FROB_UPDATE_CONTEXT): Likewise.
* config/rs6000/linux-unwind.h (ppc_fallback_frame_state): Likewise.
* config/rs6000/freebsd-unwind.h (frob_update_context): Likewise.
2022-10-06 11:04:52 +02:00
|
|
|
fs->regs.how[5] = REG_SAVED_OFFSET;
|
2009-10-11 20:06:12 +00:00
|
|
|
fs->regs.reg[5].loc.offset = (long)&mctx->gregs[EBP] - new_cfa;
|
libgcc: Decrease size of _Unwind_FrameState and even more size of cleared area in uw_frame_state_for
The following patch implements something that has Florian found as
low hanging fruit in our unwinder and has been discussed in the
https://gcc.gnu.org/wiki/cauldron2022#cauldron2022talks.inprocess_unwinding_bof
talk.
_Unwind_FrameState type seems to be (unlike the pre-GCC 3 frame_state
which has been part of ABI) private to unwind-dw2.c + unwind.inc it
includes, it is always defined on the stack of some entrypoints, initialized
by static uw_frame_state_for and the address of it is also passed to other
static functions or the static inlines handling machine dependent unwinding,
but it isn't fortunately passed to any callbacks or public functions, so I
think we can safely change it any time we want.
Florian mentioned that the structure is large even on x86_64, 384 bytes
there, starts with 328 bytes long element with frame_state_reg_info type
which then starts with an array with __LIBGCC_DWARF_FRAME_REGISTERS__ + 1
elements, each of them is 16 bytes long, on x86_64
__LIBGCC_DWARF_FRAME_REGISTERS__ is just 17 but even that is big, on say
riscv __LIBGCC_DWARF_FRAME_REGISTERS__ is I think 128, on powerpc 111,
on sh 153 etc. And, we memset to zero the whole fs variable with the
_Unwind_FrameState type at the start of the unwinding.
The reason why each element is 16 byte (on 64-bit arches) is that it
contains some pointer or pointer sized integer and then an enum (with just
7 different enumerators) + padding.
The following patch decreases it by moving the enum into a separate
array and using just one byte for each register in that second array.
We could compress it even more, say 4 bits per register, but I don't
want to uglify the code for it too much and make the accesses slower.
Furthermore, the clearing of the object can clear only thos how array
and members after it, because REG_UNSAVED enumerator (0) doesn't actually
need any pointer or pointer sized integer, it is just the other kinds
that need to have there something.
By doing this, on x86_64 the above numbers change to _Unwind_FrameState
type being now 264 bytes long, frame_state_reg_info 208 bytes and we
don't clear the first 144 bytes of the object, so the memset is 120 bytes,
so ~ 31% of the old clearing size. On riscv 64-bit assuming it has same
structure layout rules for the few types used there that would be
~ 2160 bytes of _Unwind_FrameState type before and ~ 1264 bytes after,
with the memset previously ~ 2160 bytes and after ~ 232 bytes after.
We've also talked about possibly adding a number of initially initialized
regs and initializing the rest lazily, but at least for x86_64 with
18 elements in the array that doesn't seem to be worth it anymore,
especially because return address column is 16 there and that is usually the
first thing to be touched. It might theory help with lots of registers if
they are usually untouched, but would uglify and complicate any stores to
how by having to check there for the not initialized yet cases and lazy
initialization, and similarly for all reads of how to do there if below
last initialized one, use how, otherwise imply REG_UNSAVED.
The disadvantage of the patch is that touching reg[x].loc and how[x]
now means 2 cachelines rather than one as before, and I admit beyond
bootstrap/regtest I haven't benchmarked it in any way.
2022-10-06 Jakub Jelinek <jakub@redhat.com>
* unwind-dw2.h (REG_UNSAVED, REG_SAVED_OFFSET, REG_SAVED_REG,
REG_SAVED_EXP, REG_SAVED_VAL_OFFSET, REG_SAVED_VAL_EXP,
REG_UNDEFINED): New anonymous enum, moved from inside of
struct frame_state_reg_info.
(struct frame_state_reg_info): Remove reg[].how element and the
anonymous enum there. Add how element.
* unwind-dw2.c: Include stddef.h.
(uw_frame_state_for): Don't clear first
offsetof (_Unwind_FrameState, regs.how[0]) bytes of *fs.
(execute_cfa_program, __frame_state_for, uw_update_context_1,
uw_update_context): Use fs->regs.how[X] instead of fs->regs.reg[X].how
or fs.regs.how[X] instead of fs.regs.reg[X].how.
* config/sh/linux-unwind.h (sh_fallback_frame_state): Likewise.
* config/bfin/linux-unwind.h (bfin_fallback_frame_state): Likewise.
* config/pa/linux-unwind.h (pa32_fallback_frame_state): Likewise.
* config/pa/hpux-unwind.h (UPDATE_FS_FOR_SAR, UPDATE_FS_FOR_GR,
UPDATE_FS_FOR_FR, UPDATE_FS_FOR_PC, pa_fallback_frame_state):
Likewise.
* config/alpha/vms-unwind.h (alpha_vms_fallback_frame_state):
Likewise.
* config/alpha/linux-unwind.h (alpha_fallback_frame_state): Likewise.
* config/arc/linux-unwind.h (arc_fallback_frame_state,
arc_frob_update_context): Likewise.
* config/riscv/linux-unwind.h (riscv_fallback_frame_state): Likewise.
* config/nios2/linux-unwind.h (NIOS2_REG): Likewise.
* config/nds32/linux-unwind.h (NDS32_PUT_FS_REG): Likewise.
* config/s390/tpf-unwind.h (s390_fallback_frame_state): Likewise.
* config/s390/linux-unwind.h (s390_fallback_frame_state): Likewise.
* config/sparc/sol2-unwind.h (sparc64_frob_update_context,
MD_FALLBACK_FRAME_STATE_FOR): Likewise.
* config/sparc/linux-unwind.h (sparc64_fallback_frame_state,
sparc64_frob_update_context, sparc_fallback_frame_state): Likewise.
* config/i386/sol2-unwind.h (x86_64_fallback_frame_state,
x86_fallback_frame_state): Likewise.
* config/i386/w32-unwind.h (i386_w32_fallback_frame_state): Likewise.
* config/i386/linux-unwind.h (x86_64_fallback_frame_state,
x86_fallback_frame_state): Likewise.
* config/i386/freebsd-unwind.h (x86_64_freebsd_fallback_frame_state):
Likewise.
* config/i386/dragonfly-unwind.h
(x86_64_dragonfly_fallback_frame_state): Likewise.
* config/i386/gnu-unwind.h (x86_gnu_fallback_frame_state): Likewise.
* config/csky/linux-unwind.h (csky_fallback_frame_state): Likewise.
* config/aarch64/linux-unwind.h (aarch64_fallback_frame_state):
Likewise.
* config/aarch64/freebsd-unwind.h
(aarch64_freebsd_fallback_frame_state): Likewise.
* config/aarch64/aarch64-unwind.h (aarch64_frob_update_context):
Likewise.
* config/or1k/linux-unwind.h (or1k_fallback_frame_state): Likewise.
* config/mips/linux-unwind.h (mips_fallback_frame_state): Likewise.
* config/loongarch/linux-unwind.h (loongarch_fallback_frame_state):
Likewise.
* config/m68k/linux-unwind.h (m68k_fallback_frame_state): Likewise.
* config/xtensa/linux-unwind.h (xtensa_fallback_frame_state):
Likewise.
* config/rs6000/darwin-fallback.c (set_offset): Likewise.
* config/rs6000/aix-unwind.h (MD_FROB_UPDATE_CONTEXT): Likewise.
* config/rs6000/linux-unwind.h (ppc_fallback_frame_state): Likewise.
* config/rs6000/freebsd-unwind.h (frob_update_context): Likewise.
2022-10-06 11:04:52 +02:00
|
|
|
fs->regs.how[8] = REG_SAVED_OFFSET;
|
2009-10-11 20:06:12 +00:00
|
|
|
fs->regs.reg[8].loc.offset = (long)&mctx->gregs[EIP] - new_cfa;
|
|
|
|
fs->retaddr_column = 8;
|
2013-05-28 13:52:50 +00:00
|
|
|
|
|
|
|
/* SIGFPE for IEEE-754 exceptions is delivered after the faulting insn
|
|
|
|
rather than before it, so don't set fs->signal_frame in that case.
|
|
|
|
We test whether the ES field of the Status Register is zero. */
|
|
|
|
if ((mctx->fpregs.fp_reg_set.fpchip_state.status & 0x80) == 0)
|
|
|
|
fs->signal_frame = 1;
|
2009-10-11 20:06:12 +00:00
|
|
|
|
|
|
|
return _URC_NO_REASON;
|
|
|
|
}
|
|
|
|
|
|
|
|
#endif
|