This is the mail archive of the
libc-alpha@sourceware.org
mailing list for the glibc project.
Re: [PATCH 2/5] support: don't pass to resolv_test_start a big struct by value
On Пн, Mar 25, 2019 at 13:35:56, Florian Weimer <fw@deneb.enyo.de>
wrote:
* Konstantin Kharlamov:
On Пн, Mar 25, 2019 at 11:33:28, Florian Weimer <fw@deneb.enyo.de>
wrote:
* Konstantin Kharlamov:
diff --git a/support/resolv_test.h b/support/resolv_test.h
index c9e48205ab..880330ad5c 100644
--- a/support/resolv_test.h
+++ b/support/resolv_test.h
@@ -116,7 +116,7 @@ void resolv_test_init (void);
needed. As a side effect, NSS is reconfigured to use nss_dns
only
for aplicable databases, and the process may enter a network
namespace for better isolation. */
-struct resolv_test *resolv_test_start (struct
resolv_redirect_config);
+struct resolv_test *resolv_test_start (const struct
resolv_redirect_config*);
This patch would adjusting all the tests that call
resolv_test_start,
and these changes are missing from the patch. It is unclear how
this
change would be an improvement because most tests call
resolv_test_start exactly once and the parameter object is never
used
again. Passing a pointer requires writing the argument object to
the
stack *and* supplying its address to resolv_test_start, which
requires
more work. (Maybe some targets have more optimized code for struct
initialization than passing many zero arguments, but that's a GCC
issue which will eventually be fixed.)
Wow, are you saying that in the assembly the address that gets
passed
to resolve_test_start() would be not the address of struct, but
instead
an address of an addres on a stack that is an address of the
struct…?
With the pointer-to-struct argument, you need to write the temporary
object to the stack and pass its address.
With the struct argument, you need to write the temporary object to
the stack, in the form of an argument list.
The second case avoids computing and passing the address of the
temporary object.
Can't reproduce here. Testcase:
$ cat test.c
#include <stdlib.h>
struct Foo {
int a;
char b;
};
void get_foo(struct Foo*);
int main() {
struct Foo foo = {};
get_foo(&foo);
}
$ gcc test.c -S -fverbose-asm -o a.S -g3 -O0
Produces the following code for main() in a.S file (snip of a relevant
part):
.globl main
.type main, @function
main:
.LFB6:
.file 1 "test.c"
.loc 1 10 12
.cfi_startproc
pushq %rbp #
.cfi_def_cfa_offset 16
.cfi_offset 6, -16
movq %rsp, %rbp #,
.cfi_def_cfa_register 6
subq $16, %rsp #,
# test.c:10: int main() {
.loc 1 10 12
movq %fs:40, %rax # MEM[(<address-space-1> long unsigned int
*)40B], tmp91
movq %rax, -8(%rbp) # tmp91, D.2539
xorl %eax, %eax # tmp91
# test.c:11: struct Foo foo = {};
.loc 1 11 16
movq $0, -16(%rbp) #, foo
# test.c:12: get_foo(&foo);
.loc 1 12 5
leaq -16(%rbp), %rax #, tmp89
movq %rax, %rdi # tmp89,
call get_foo@PLT #
movl $0, %eax #, _5
# test.c:13: }
The 3 actions being done just before get_foo(), commented:
leaq -16(%rbp), %rax # put address of the struct to rax register
movq %rax, %rdi # move content of rax into rdi (for
whatever reason)
call get_foo@PLT # call the function
Note, it doesn't put the address into stack, it passes it in registers,
just as I'd expect.