Created
January 19, 2012 16:48
-
-
Save antirez/1641112 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Dump of assembler code for function zslGetRank: | |
zsl argument -> %rdi | |
o argument -> %rsi | |
score argument -> %xmm0 | |
x variable -> %rbx | |
0x0000000000427fd0 <+0>: push %r14 | |
0x0000000000427fd2 <+2>: push %r13 | |
0x0000000000427fd4 <+4>: mov %rsi,%r13 | |
o -> %r13 | |
0x0000000000427fd7 <+7>: push %r12 | |
0x0000000000427fd9 <+9>: push %rbp | |
0x0000000000427fda <+10>: push %rbx | |
0x0000000000427fdb <+11>: sub $0x10,%rsp | |
allocates 16 bytes of stack | |
0x0000000000427fdf <+15>: mov 0x18(%rdi),%r14d | |
move zsl->level into %r14d | |
0x0000000000427fe3 <+19>: mov (%rdi),%rbx | |
move zsl->header into %rbx (x variable) | |
0x0000000000427fe6 <+22>: sub $0x1,%r14d | |
move %r14d is set to (zsl->level-1) | |
0x0000000000427fea <+26>: js 0x428076 <zslGetRank+166> | |
return to caller if %r14d (holding the current level) is < 0 | |
0x0000000000427ff0 <+32>: xor %r12d,%r12d | |
set %r12d to 0 (rank variable) | |
0x0000000000427ff3 <+35>: nopl 0x0(%rax,%rax,1) | |
NOP (used for alighment I guess) | |
0x0000000000427ff8 <+40>: movslq %r14d,%rbp | |
set %rbp 64 bit register to the value of the 32 bit register %r14d (i variable) | |
0x0000000000427ffb <+43>: add $0x1,%rbp | |
0x0000000000427fff <+47>: shl $0x4,%rbp | |
Compute the (current_level+1)*16 adding+shifting left by 4 | |
0x0000000000428003 <+51>: mov 0x8(%rbx,%rbp,1),%rax | |
Store x->level[i].forward into %rax | |
Note that 0x8(%rbx,%rbp,1) is used to access: | |
%rbx+(%rbp*1)+0x8 | |
Since %rbx points to current node (x variable, type zskiplistNode), and | |
the 'level' field is at offset 24, and is an array of zskiplistLevel structures | |
that are 16 bytes each. The 'forward' field is at offset 0 in each of this | |
structures. | |
So for instance if level is 2, %rbp is set to (2+1)*16, that is enough to skip | |
two fields out of three in the zskiplistNode structure, and to select the right | |
offset of the level array. However we still miss 8 bytes to select the 'forward' | |
field, and this is why there is the 0x8 displacement. | |
0x0000000000428008 <+56>: test %rax,%rax | |
Check if x->level[i] == NULL | |
0x000000000042800b <+59>: je 0x428052 <zslGetRank+130> | |
If x->level[i] == NULL go to zslGetRank+130 (while condition false) | |
0x000000000042800d <+61>: nopl (%rax) | |
Padding | |
0x0000000000428010 <+64>: movsd 0x8(%rax),%xmm1 | |
set %xmm1 to x->level[i].forward->score | |
(note that %rax is x->level[i].forward) | |
0x0000000000428015 <+69>: ucomisd %xmm1,%xmm0 | |
0x0000000000428019 <+73>: ja 0x42803c <zslGetRank+108> | |
if x->level[i].forward->score < score go to +108 (while condition true) | |
0x000000000042801b <+75>: ucomisd %xmm0,%xmm1 | |
0x000000000042801f <+79>: jne 0x428052 <zslGetRank+130> | |
if x->level[i].forward != score go to +130 (while condition false) | |
0x0000000000428021 <+81>: jp 0x428052 <zslGetRank+130> | |
also go to +130 if one of the two is NaN (PF=1) | |
0x0000000000428023 <+83>: mov (%rax),%rdi | |
%rdi -> x->level[i].forward->obj | |
0x0000000000428026 <+86>: mov %r13,%rsi | |
%r13 -> o | |
0x0000000000428029 <+89>: movsd %xmm0,(%rsp) | |
Save %xmm0 before call | |
0x000000000042802e <+94>: callq 0x41b840 <compareStringObjects> | |
0x0000000000428033 <+99>: test %eax,%eax | |
Check if compareStringObjects(x->level[i].forward->obj,o) <= 0 | |
0x0000000000428035 <+101>: movsd (%rsp),%xmm0 | |
Restore %xmm0 | |
0x000000000042803a <+106>: jg 0x428052 <zslGetRank+130> | |
If instead compareStringObjects() returned > 0, go to +130 | |
0x000000000042803c <+108>: mov 0x10(%rbp,%rbx,1),%eax | |
%eax -> (%rbp+%rbx+16) -> (x->level[i]->span) | |
0x0000000000428040 <+112>: mov 0x8(%rbx,%rbp,1),%rbx | |
%rbx -> x->level[i]->forward (variable x) | |
0x0000000000428045 <+117>: add %rax,%r12 | |
rank var (%r12) += %rax (that was x->level[i]->span) | |
0x0000000000428048 <+120>: mov 0x8(%rbx,%rbp,1),%rax | |
%rax -> x->level[i]->forward | |
0x000000000042804d <+125>: test %rax,%rax | |
0x0000000000428050 <+128>: jne 0x428010 <zslGetRank+64> | |
Loop again if x->level[i]->forward != NULL, jumping to +64 | |
0x0000000000428052 <+130>: mov (%rbx),%rdi | |
0x0000000000428055 <+133>: test %rdi,%rdi | |
0x0000000000428058 <+136>: je 0x428070 <zslGetRank+160> | |
if (x->obj == NULL) jump to +160 (iterate for again) | |
0x000000000042805a <+138>: mov %r13,%rsi | |
0x000000000042805d <+141>: movsd %xmm0,(%rsp) | |
0x0000000000428062 <+146>: callq 0x41b910 <equalStringObjects> | |
Call equalStringObject with x->obj in %rdi, and o in %rsi | |
0x0000000000428067 <+151>: test %eax,%eax | |
0x0000000000428069 <+153>: movsd (%rsp),%xmm0 | |
0x000000000042806e <+158>: jne 0x428079 <zslGetRank+169> | |
if return value from function is != 0, then the if condition | |
(x->obj && equalStringObjects(x->obj,o)) is true and we jump to +169 | |
that is where the function returns. | |
0x0000000000428070 <+160>: sub $0x1,%r14d | |
0x0000000000428074 <+164>: jns 0x427ff8 <zslGetRank+40> | |
If variable 'i' (current level, in %r14d) is jet >= 0, iterate the for loop. | |
0x0000000000428076 <+166>: xor %r12d,%r12d | |
0x0000000000428079 <+169>: add $0x10,%rsp | |
0x000000000042807d <+173>: mov %r12,%rax | |
0x0000000000428080 <+176>: pop %rbx | |
0x0000000000428081 <+177>: pop %rbp | |
0x0000000000428082 <+178>: pop %r12 | |
0x0000000000428084 <+180>: pop %r13 | |
0x0000000000428086 <+182>: pop %r14 | |
0x0000000000428088 <+184>: retq | |
return to the caller, with %r12 (rank) in %eax |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment