.text
.globl init_profiler
.globl profile_r
.globl profile_l
.globl profile_l2
.globl profile_n
.globl profile_n2
.globl profile_s
.globl profile_s2
.globl profile_t
.globl write_profile_information
.globl write_profile_stack
.globl stack_trace_depth
.if ! LINUX
.globl allocate_memory
.endif
.globl __STRING__
.globl openF
.globl closeF
.globl writeFC
.globl writeFI
.globl _ab_stack_size
.globl _ew_print_string
.globl _ew_print_char
.globl _ew_print_text
.globl _create_profile_file_name
.globl profile_file_name
/* extrn print_error */
/* extrn profile_stack_pointer */
next = 0
time = 8
n_profiler_calls = 16
n_strict_calls = 24
n_lazy_calls = 32
n_curried_calls = 40
n_words_allocated = 48
name_ = 56
FunctionProfile = 64
profile_t:
push rax
push rdx
rdtsc
push rcx
mov rcx,qword ptr [rip+profile_stack_pointer]
sub edx,dword ptr [rip+global_time_hi]
push rbx
mov ebx,dword ptr [rip+global_time_lo]
mov eax,eax
shl rdx,32
sub rax,rbx
mov rbx,qword ptr [rcx-8]
add rax,rdx
sub rcx,8
mov qword ptr [rip+global_last_tail_call],rbx
mov qword ptr [rip+profile_stack_pointer],rcx
inc qword ptr [rbx+n_profiler_calls]
add qword ptr [rbx+time],rax
mov rax,qword ptr [rip+global_n_words_free]
mov qword ptr [rip+global_n_words_free],r15
sub rax,r15
add qword ptr [rbx+n_words_allocated],rax
pop rbx
pop rcx
rdtsc
mov dword ptr [rip+global_time_hi],edx
pop rdx
mov dword ptr [rip+global_time_lo],eax
pop rax
ret
profile_r:
push rax
push rdx
rdtsc
push rcx
mov rcx,qword ptr [rip+profile_stack_pointer]
sub edx,dword ptr [rip+global_time_hi]
push rbx
mov ebx,dword ptr [rip+global_time_lo]
mov eax,eax
shl rdx,32
sub rax,rbx
mov rbx,qword ptr [rcx-8]
add rax,rdx
sub rcx,8
mov qword ptr [rip+global_last_tail_call],0
mov qword ptr [rip+profile_stack_pointer],rcx
inc qword ptr [rbx+n_profiler_calls]
add qword ptr [rbx+time],rax
mov rax,qword ptr [rip+global_n_words_free]
mov qword ptr [rip+global_n_words_free],r15
sub rax,r15
add qword ptr [rbx+n_words_allocated],rax
pop rbx
pop rcx
rdtsc
mov dword ptr [rip+global_time_hi],edx
pop rdx
mov dword ptr [rip+global_time_lo],eax
pop rax
ret
profile_l:
push rax
push rdx
rdtsc
push rbx
mov rbx,qword ptr [rbp]
test rbx,rbx
je allocate_function_profile_record_l
allocate_function_profile_record_lr:
push rcx
mov rbp,qword ptr [rip+global_last_tail_call]
mov rcx,qword ptr [rip+profile_stack_pointer]
test rbp,rbp
jne use_tail_calling_function_l
mov rbp,qword ptr [rcx-8]
use_tail_calling_function_lr:
mov qword ptr [rcx],rbx
add rcx,8
inc qword ptr [rbx+n_curried_calls]
att_jmp profile_n_
allocate_function_profile_record_l:
att_call allocate_function_profile_record
att_jmp allocate_function_profile_record_lr
use_tail_calling_function_l:
mov qword ptr [rip+global_last_tail_call],0
att_jmp use_tail_calling_function_lr
profile_l2:
push rax
push rdx
rdtsc
push rbx
mov rbx,qword ptr [rbp]
test rbx,rbx
je allocate_function_profile_record_l2
allocate_function_profile_record_l2r:
push rcx
mov rbp,qword ptr [rip+global_last_tail_call]
mov rcx,qword ptr [rip+profile_stack_pointer]
test rbp,rbp
jne use_tail_calling_function_l2
mov rbp,qword ptr [rcx-8]
use_tail_calling_function_l2r:
mov qword ptr [rcx],rbx
mov qword ptr [rcx+8],rbx
add rcx,16
inc qword ptr [rbx+n_curried_calls]
att_jmp profile_n_
allocate_function_profile_record_l2:
att_call allocate_function_profile_record
att_jmp allocate_function_profile_record_l2r
use_tail_calling_function_l2:
mov qword ptr [rip+global_last_tail_call],0
att_jmp use_tail_calling_function_l2r
profile_n:
push rax
push rdx
rdtsc
push rbx
mov rbx,qword ptr [rbp]
test rbx,rbx
je allocate_function_profile_record_n
allocate_function_profile_record_nr:
push rcx
mov rbp,qword ptr [rip+global_last_tail_call]
mov rcx,qword ptr [rip+profile_stack_pointer]
test rbp,rbp
jne use_tail_calling_function_n
mov rbp,qword ptr [rcx-8]
use_tail_calling_function_nr:
mov qword ptr [rcx],rbx
add rcx,8
inc qword ptr [rbx+n_lazy_calls]
att_jmp profile_n_
allocate_function_profile_record_n:
att_call allocate_function_profile_record
att_jmp allocate_function_profile_record_nr
use_tail_calling_function_n:
mov qword ptr [rip+global_last_tail_call],0
att_jmp use_tail_calling_function_nr
profile_n2:
push rax
push rdx
rdtsc
push rbx
mov rbx,qword ptr [rbp]
test rbx,rbx
je allocate_function_profile_record_n2
allocate_function_profile_record_n2r:
push rcx
mov rbp,qword ptr [rip+global_last_tail_call]
mov rcx,qword ptr [rip+profile_stack_pointer]
test rbp,rbp
jne use_tail_calling_function_n2
mov rbp,qword ptr [rcx-8]
use_tail_calling_function_n2r:
mov qword ptr [rcx],rbx
mov qword ptr [rcx+8],rbx
add rcx,16
inc qword ptr [rbx+n_lazy_calls]
att_jmp profile_n_
allocate_function_profile_record_n2:
att_call allocate_function_profile_record
att_jmp allocate_function_profile_record_n2r
use_tail_calling_function_n2:
mov qword ptr [rip+global_last_tail_call],0
att_jmp use_tail_calling_function_n2r
profile_s2:
push rax
push rdx
rdtsc
push rbx
mov rbx,qword ptr [rbp]
test rbx,rbx
je allocate_function_profile_record_s2
allocate_function_profile_record_s2r:
push rcx
mov rbp,qword ptr [rip+global_last_tail_call]
mov rcx,qword ptr [rip+profile_stack_pointer]
test rbp,rbp
jne use_tail_calling_function_s2
mov rbp,qword ptr [rcx-8]
use_tail_calling_function_s2r:
mov qword ptr [rcx],rbx
mov qword ptr [rcx+8],rbx
add rcx,16
att_jmp profile_s_
allocate_function_profile_record_s2:
att_call allocate_function_profile_record
att_jmp allocate_function_profile_record_s2r
use_tail_calling_function_s2:
mov qword ptr [rip+global_last_tail_call],0
att_jmp use_tail_calling_function_s2r
profile_s:
push rax
push rdx
rdtsc
push rbx
mov rbx,qword ptr [rbp]
test rbx,rbx
je allocate_function_profile_record_s
allocate_function_profile_record_sr:
push rcx
mov rbp,qword ptr [rip+global_last_tail_call]
mov rcx,qword ptr [rip+profile_stack_pointer]
test rbp,rbp
jne use_tail_calling_function_s
mov rbp,qword ptr [rcx-8]
use_tail_calling_function_sr:
mov qword ptr [rcx],rbx
add rcx,8
profile_s_:
inc qword ptr [rbx+n_strict_calls]
profile_n_:
mov qword ptr [rip+profile_stack_pointer],rcx
sub edx,dword ptr [rip+global_time_hi]
mov ebx,dword ptr [rip+global_time_lo]
mov eax,eax
shl rdx,32
sub rax,rbx
add rax,rdx
inc qword ptr [rbp+n_profiler_calls]
add qword ptr [rbp+time],rax
mov rax,qword ptr [rip+global_n_words_free]
mov qword ptr [rip+global_n_words_free],r15
sub rax,r15
add qword ptr [rbp+n_words_allocated],rax
pop rcx
pop rbx
rdtsc
mov dword ptr [rip+global_time_hi],edx
pop rdx
mov dword ptr [rip+global_time_lo],eax
pop rax
ret
allocate_function_profile_record_s:
att_call allocate_function_profile_record
att_jmp allocate_function_profile_record_sr
use_tail_calling_function_s:
mov qword ptr [rip+global_last_tail_call],0
att_jmp use_tail_calling_function_sr
/* argument: rbp: function name adress-4 */
/* result: rbx: function profile record adress */
allocate_function_profile_record:
push rax
mov rax,qword ptr [rip+global_n_free_records_in_block]
mov rbx,qword ptr [rip+global_last_allocated_block]
test rax,rax
jne no_alloc
push rcx
push rdx
push rbp
.if LINUX
sub rsp,104
mov qword ptr [rsp],rsi
mov qword ptr [rsp+8],rdi
mov qword ptr [rsp+16],r8
mov qword ptr [rsp+24],r10
mov qword ptr [rsp+32],r11
movsd qword ptr [rsp+40],xmm0
movsd qword ptr [rsp+48],xmm1
movsd qword ptr [rsp+56],xmm2
movsd qword ptr [rsp+64],xmm3
movsd qword ptr [rsp+72],xmm4
movsd qword ptr [rsp+80],xmm5
movsd qword ptr [rsp+88],xmm6
movsd qword ptr [rsp+96],xmm7
.else
sub rsp,72
mov qword ptr [rsp],r8
mov qword ptr [rsp+8],r10
mov qword ptr [rsp+16],r11
movsd qword ptr [rsp+24],xmm0
movsd qword ptr [rsp+32],xmm1
movsd qword ptr [rsp+40],xmm2
movsd qword ptr [rsp+48],xmm3
movsd qword ptr [rsp+56],xmm4
movsd qword ptr [rsp+64],xmm5
.endif
mov rbp,rsp
sub rsp,40
and rsp,-16
.if LINUX
mov rdi,8192
/* 128*FunctionProfile */
att_call _malloc
.else
mov rcx,128*FunctionProfile
att_call allocate_memory
.endif
mov rsp,rbp
.if LINUX
mov rsi,qword ptr [rsp]
mov rdi,qword ptr [rsp+8]
mov r8,qword ptr [rsp+16]
mov r10,qword ptr [rsp+24]
mov r11,qword ptr [rsp+32]
movlpd xmm0,qword ptr [rsp+40]
movlpd xmm1,qword ptr [rsp+48]
movlpd xmm2,qword ptr [rsp+56]
movlpd xmm3,qword ptr [rsp+64]
movlpd xmm4,qword ptr [rsp+72]
movlpd xmm5,qword ptr [rsp+80]
movlpd xmm6,qword ptr [rsp+88]
movlpd xmm7,qword ptr [rsp+96]
add rsp,104
.else
mov r8,qword ptr [rsp]
mov r10,qword ptr [rsp+8]
mov r11,qword ptr [rsp+16]
movlpd xmm0,qword ptr [rsp+24]
movlpd xmm1,qword ptr [rsp+32]
movlpd xmm2,qword ptr [rsp+40]
movlpd xmm3,qword ptr [rsp+48]
movlpd xmm4,qword ptr [rsp+56]
movlpd xmm5,qword ptr [rsp+64]
add rsp,72
.endif
test rax,rax
pop rbp
pop rdx
pop rcx
je no_memory
mov rbx,rax
mov rax,128
mov qword ptr [rip+global_last_allocated_block],rbx
no_alloc:
dec rax
mov qword ptr [rip+global_n_free_records_in_block],rax
lea rax,[rbx+FunctionProfile]
mov qword ptr [rip+global_last_allocated_block],rax
xor rax,rax
mov qword ptr [rbx+time],rax
mov qword ptr [rbx+n_profiler_calls],rax
mov qword ptr [rbx+n_strict_calls],rax
mov qword ptr [rbx+n_lazy_calls],rax
mov qword ptr [rbx+n_curried_calls],rax
mov qword ptr [rbx+n_words_allocated],rax
mov rax,qword ptr [rip+global_profile_records]
mov qword ptr [rbx+name_],rbp
mov qword ptr [rbx+next],rax
mov qword ptr [rip+global_profile_records],rbx
mov qword ptr [rbp],rbx
pop rax
ret
no_memory:
lea rbp,[rip+not_enough_memory_for_profiler]
pop rax
att_jmp print_error
write_profile_information:
mov rbp,rsp
sub rsp,40
and rsp,-16
.if LINUX
mov r13,rsi
mov r14,rdi
lea rdi,[rip+profile_file_name]
.else
lea rcx,[rip+profile_file_name]
.endif
att_call _create_profile_file_name
.if LINUX
mov rsi,r13
mov rdi,r14
.endif
mov rsp,rbp
mov rax,1
lea rcx,[rip+profile_file_name]
att_call openF
test r10,r10
je cannot_open
mov rbp,qword ptr [rip+global_profile_records]
write_profile_lp:
test rbp,rbp
je end_list
mov rdx,qword ptr [rbp+name_]
push rbp
push rdx
movsxd rax,dword ptr [rdx-4]
lea rdx,[rdx+rax-4]
mov eax,dword ptr [rdx]
add rdx,4
write_module_name_lp:
sub rax,1
jc end_module_name
push rax
push rdx
movzx r10,byte ptr [rdx]
att_call writeFC
pop rdx
pop rax
add rdx,1
att_jmp write_module_name_lp
end_module_name:
mov r10,32 # ' '
att_call writeFC
pop rdx
add rdx,7
write_function_name_lp:
movzx r10,byte ptr [rdx+1]
add rdx,1
test r10,r10
je end_function_name
push rdx
att_call writeFC
pop rdx
att_jmp write_function_name_lp
end_function_name:
mov r10,32 # ' '
att_call writeFC
mov rbp,qword ptr [rsp]
mov r10,qword ptr [rbp+n_strict_calls]
att_call writeFI_space
mov rbp,qword ptr [rsp]
mov r10,qword ptr [rbp+n_lazy_calls]
att_call writeFI_space
mov rbp,qword ptr [rsp]
mov r10,qword ptr [rbp+n_curried_calls]
att_call writeFI_space
mov rbp,qword ptr [rsp]
mov r10,qword ptr [rbp+n_profiler_calls]
att_call writeFI_space
mov rbp,qword ptr [rsp]
mov r10,qword ptr [rbp+n_words_allocated]
att_call writeFI_space
mov rbp,qword ptr [rsp]
mov r10,qword ptr [rbp+time]
att_call writeFI
mov r10,10
att_call writeFC
pop rbp
mov rbp,qword ptr [rbp+next]
att_jmp write_profile_lp
writeFI_space:
att_call writeFI
mov r10,32 # ' '
att_jmp writeFC
end_list:
att_call closeF
cannot_open:
ret
write_profile_stack:
mov rax,qword ptr [rip+profile_stack_pointer]
test rax,rax
je stack_not_initialised
push rax
mov rbp,rsp
sub rsp,40
and rsp,-16
.if LINUX
mov r13,rsi
mov r14,rdi
lea rdi,[rip+stack_trace_string]
.else
lea rcx,[rip+stack_trace_string]
.endif
att_call _ew_print_string
.if LINUX
mov rsi,r13
mov rdi,r14
.endif
mov rsp,rbp
pop rax
/* mov rbp,12 */
mov rbp,qword ptr [rip+stack_trace_depth]
write_functions_on_stack:
mov rbx,qword ptr [rax-8]
sub rax,8
test rbx,rbx
je end_profile_stack
push rax
mov rcx,qword ptr [rbx+name_]
push rbp
mov edx,dword ptr [rcx-4]
add rcx,8
mov r12d,dword ptr [rdx]
lea r13,[rdx+4]
mov rbp,rsp
sub rsp,40
and rsp,-16
.if LINUX
mov r11,rsi
mov r14,rdi
mov rdi,rcx
.endif
att_call _ew_print_string
.if LINUX
lea rdi,[rip+module_string]
.else
lea rcx,[rip+module_string]
.endif
att_call _ew_print_string
.if LINUX
mov rsi,r12
mov rdi,r13
.else
mov rdx,r12
mov rcx,r13
.endif
att_call _ew_print_text
.if LINUX
mov rdi,93 # ']'
.else
mov rcx,93 # ']'
.endif
att_call _ew_print_char
.if LINUX
mov rdi,10
.else
mov rcx,10
.endif
att_call _ew_print_char
.if LINUX
mov rsi,r11
mov rdi,r14
.endif
mov rsp,rbp
pop rbp
pop rax
sub rbp,1
att_jne write_functions_on_stack
end_profile_stack:
stack_not_initialised:
ret
init_profiler:
mov rbp,rsp
sub rsp,40
and rsp,-16
.if LINUX
mov r13,rsi
mov r14,rdi
mov rdi,qword ptr [rip+_ab_stack_size]
att_call _malloc
mov rsi,r13
mov rdi,r14
.else
mov rcx,qword ptr [rip+ab_stack_size]
att_call allocate_memory
.endif
mov rsp,rbp
test rax,rax
je init_profiler_error
push rax
lea rbp,[rip+start_string]
att_call allocate_function_profile_record
pop rdx
mov qword ptr [rdx+8],rbx
mov qword ptr [rdx],0
add rdx,16
mov qword ptr [rip+profile_stack_pointer],rdx
mov qword ptr [rip+global_last_tail_call],0
mov qword ptr [rip+global_n_words_free],r15
rdtsc
mov dword ptr [rip+global_time_hi],edx
mov dword ptr [rip+global_time_lo],eax
ret
init_profiler_error:
mov qword ptr [rip+profile_stack_pointer],0
lea rbp,[rip+not_enough_memory_for_profile_stack]
att_jmp print_error
.data
.align 8
global_n_free_records_in_block:
.quad 0
/* 0 n free records in block */
global_last_allocated_block:
.quad 0
/* 8 latest allocated block */
global_profile_records:
.quad 0
/* 16 profile record list */
global_time_hi:
.long 0
/* 24 clock */
global_time_lo:
.long 0
global_last_tail_call:
.quad 0
/* last tail calling function */
global_n_words_free:
.quad 0
profile_file_name:
.quad __STRING__+2
.quad 0
.quad 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
.quad 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
.quad 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
.quad 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
.quad 0
stack_trace_depth:
.quad 12
.align 8
/* m_system also defined in istartup.s */
/* m_system: */
/* .quad 6 */
/* .ascii "System" */
/* .byte 0 */
/* .byte 0 */
.long m_system-.
start_string:
.quad 0
.ascii "start"
.byte 0
.align 8
not_enough_memory_for_profile_stack:
.ascii "not enough memory for profile stack"
.byte 10
.byte 0
not_enough_memory_for_profiler:
.ascii "not enough memory for profiler"
.byte 10
.byte 0
stack_trace_string:
.ascii "Stack trace:"
.byte 10
.byte 0
module_string:
.ascii " [module: "
.byte 0
.align 8
/* end */