// File: /workspace/github_c_makefile_star2_O3/johsteffens[P]beth/lib/bcore/bcore_spect.c
// Function: hmap_s_down
static void hmap_s_down( hmap_s* o )
{
    bcore_mutex_s_lock( &o->mutex );

    /// clear and lock all caches because shut down procedure can change perspective addresses (this includes o->cache)
    for( uz_t i = 0; i < o->cache_arr.size; i++ )
    {
        bcore_tp_fastmap_s* cache = o->cache_arr.data[ i ];
        bcore_tp_fastmap_s_clear( cache );
        bcore_tp_fastmap_s_set_locked( cache, true );
    }

    // shut down in reverse order of creation
    while( o->arr.size > 0 )
    {
        vd_t spect = bcore_arr_vd_s_pop( &o->arr );
        tp_t p_type = ( ( bcore_spect_header_s* )spect )->p_type;
        tp_t o_type = ( ( bcore_spect_header_s* )spect )->o_type;
        tp_t sig    = bcore_tp_fold_tp( p_type, o_type );
        bcore_hmap_u3vd_s_remove_h( &o->map, sig );

        /** During discard we lift the lock because the spect's destructor
         *  may retrieve (even recreate) perspective instances.
         *
         *  This could re-add perspectives that have already been destroyed, giving those a different address.
         *  Nevertheless, this is safe at this point for the following reasons:
         *    1. Non-perspective objects, possibly referencing perspectives, have already been taken down.
         *    2. Perspective B can only reference perspective A when A was added before B to the registry.
         *       Shutting down in reverse order ensures that A is never destroyed before B.
         *    3. (follows from 2) Cyclic references are not possible.
         *    4. Caches are cleared and locked.
         *
         *  Temporarily re-added perspectives reside at the tail-end of o->arr
         *  and are taken down again in this loop without cyclic re-instantiation.
         *  (Halting is guaranteed.)
         */
        bcore_mutex_s_unlock( &o->mutex );
        if( p_type == TYPEOF_bcore_inst_s )
        {
            bcore_inst_s_discard( spect );
        }
        else
        {
            bcore_inst_a_discard( spect );
        }
        bcore_mutex_s_lock( &o->mutex );
    }

    /// shut down all caches (this includes o->cache)
    for( uz_t i = 0; i < o->cache_arr.size; i++ )
    {
        bcore_tp_fastmap_s* cache = o->cache_arr.data[ i ];
        bcore_tp_fastmap_s_down( cache );
    }
    bcore_arr_vd_s_down( &o->cache_arr );

    bcore_hmap_u3vd_s_down( &o->map );
    bcore_arr_vd_s_down(    &o->arr );
    bcore_mutex_s_unlock( &o->mutex );
    bcore_mutex_s_down( &o->mutex );
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
pushq %rax
movq %rdi, %r14
leaq 0x60(%rdi), %r13
movq %r13, %rdi
callq 0x1142c9
cmpq $0x0, 0x2b0(%r14)
je 0xeb83a
xorl %ebx, %ebx
movq 0x2a8(%r14), %rax
movq (%rax,%rbx,8), %r15
movq %r15, %rdi
callq 0x115df4
movq %r15, %rdi
movl $0x1, %esi
callq 0x115f82
incq %rbx
movq 0x2b0(%r14), %rax
cmpq %rax, %rbx
jb 0xeb809
jmp 0xeb83c
xorl %eax, %eax
cmpq $0x0, 0x10(%r14)
je 0xeb9d5
movabsq $0x100000001b3, %r12    # imm = 0x100000001B3
leaq 0x20(%r14), %rbx
movq %rbx, (%rsp)
movq %r14, %rdi
callq 0xba6a4
movq %rax, %rbp
movq (%rax), %r15
movq 0x8(%rax), %rsi
movq %rsi, %rax
movl $0xff, %edx
andq %rdx, %rax
xorq %r15, %rax
imulq %r12, %rax
movl %esi, %ecx
shrl $0x8, %ecx
movl $0xff, %edi
andl %edi, %ecx
xorq %rax, %rcx
imulq %r12, %rcx
movl %esi, %eax
shrl $0x10, %eax
andl %edi, %eax
xorq %rcx, %rax
imulq %r12, %rax
movl %esi, %ecx
shrl $0x18, %ecx
xorq %rax, %rcx
imulq %r12, %rcx
movq %rsi, %rax
shrq $0x20, %rax
andq %rdx, %rax
xorq %rcx, %rax
imulq %r12, %rax
movq %rsi, %rcx
shrq $0x28, %rcx
andq %rdx, %rcx
xorq %rax, %rcx
imulq %r12, %rcx
movq %rsi, %rax
shrq $0x30, %rax
andq %rdx, %rax
xorq %rcx, %rax
imulq %r12, %rax
shrq $0x38, %rsi
xorq %rax, %rsi
imulq %r12, %rsi
movq %rbx, %rdi
callq 0xc7ec3
movq %r13, %rdi
callq 0x1142fb
movabsq $0x782b96602f424981, %rax # imm = 0x782B96602F424981
cmpq %rax, %r15
jne 0xeb914
movq %rbp, %rdi
callq 0xf71ec
jmp 0xeb9bb
movq %r13, %rbx
movq (%rbp), %r15
leaq 0xb0b46(%rip), %rdx     # 0x19c468
movl (%rdx), %eax
cltq
leaq (%rax,%rax,2), %rax
movq 0x20(%rdx,%rax,8), %rcx
movq 0x18(%rdx,%rax,8), %rdx
andq %r15, %rdx
shlq $0x4, %rdx
leaq (%rcx,%rdx), %rax
movq (%rcx,%rdx), %rdx
movl $0x8, %ecx
cmpq %r15, %rdx
je 0xeb977
movq 0x10(%rax), %rdx
movl $0x18, %ecx
cmpq %r15, %rdx
je 0xeb977
movq 0x20(%rax), %rdx
movl $0x28, %ecx
cmpq %r15, %rdx
je 0xeb977
movq 0x30(%rax), %rdx
movl $0x38, %ecx
cmpq %r15, %rdx
jne 0xeb980
movq (%rax,%rcx), %r13
testq %r13, %r13
jne 0xeb9a7
movabsq $0x782b96602f424981, %rdi # imm = 0x782B96602F424981
movq %r15, %rsi
callq 0xe9bc5
movq %rax, %r13
leaq 0xb0acc(%rip), %rdi     # 0x19c468
movq %r15, %rsi
movq %rax, %rdx
callq 0x115fac
movq %r13, %rdi
movq %rbp, %rsi
callq *0xb8(%r13)
movq %rbx, %r13
movq (%rsp), %rbx
movq %r13, %rdi
callq 0x1142c9
cmpq $0x0, 0x10(%r14)
jne 0xeb859
movq 0x2b0(%r14), %rax
testq %rax, %rax
je 0xeb9f8
xorl %ebx, %ebx
movq 0x2a8(%r14), %rax
movq (%rax,%rbx,8), %rdi
callq 0x115e85
incq %rbx
cmpq 0x2b0(%r14), %rbx
jb 0xeb9dc
leaq 0x2a0(%r14), %rdi
callq 0xba394
leaq 0x20(%r14), %rdi
callq 0xc7249
movq %r14, %rdi
callq 0xba394
movq %r13, %rdi
callq 0x1142fb
movq %r13, %rdi
addq $0x8, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
jmp 0x1141a2
nop