// File: /workspace/github_c_makefile_star2_O0/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
movq %rsp, %rbp
subq $0x50, %rsp
movq %rdi, -0x8(%rbp)
movq -0x8(%rbp), %rdi
addq $0x60, %rdi
callq 0x10fc20
movq $0x0, -0x10(%rbp)
movq -0x10(%rbp), %rax
movq -0x8(%rbp), %rcx
cmpq 0x2b0(%rcx), %rax
jae 0xd3cfe
movq -0x8(%rbp), %rax
movq 0x2a8(%rax), %rax
movq -0x10(%rbp), %rcx
movq (%rax,%rcx,8), %rax
movq %rax, -0x18(%rbp)
movq -0x18(%rbp), %rdi
callq 0x112210
movq -0x18(%rbp), %rdi
movl $0x1, %esi
callq 0x112410
movq -0x10(%rbp), %rax
addq $0x1, %rax
movq %rax, -0x10(%rbp)
jmp 0xd3cb1
jmp 0xd3d00
movq -0x8(%rbp), %rax
cmpq $0x0, 0x10(%rax)
jbe 0xd3d98
movq -0x8(%rbp), %rdi
callq 0x96f50
movq %rax, -0x20(%rbp)
movq -0x20(%rbp), %rax
movq (%rax), %rax
movq %rax, -0x28(%rbp)
movq -0x20(%rbp), %rax
movq 0x8(%rax), %rax
movq %rax, -0x30(%rbp)
movq -0x28(%rbp), %rdi
movq -0x30(%rbp), %rsi
callq 0xd14c0
movq %rax, -0x38(%rbp)
movq -0x8(%rbp), %rdi
addq $0x20, %rdi
movq -0x38(%rbp), %rsi
callq 0xac140
movq -0x8(%rbp), %rdi
addq $0x60, %rdi
callq 0x10fc70
movabsq $0x782b96602f424981, %rax # imm = 0x782B96602F424981
cmpq %rax, -0x28(%rbp)
jne 0xd3d7d
movq -0x20(%rbp), %rdi
callq 0xe4d10
jmp 0xd3d86
movq -0x20(%rbp), %rdi
callq 0xd20c0
movq -0x8(%rbp), %rdi
addq $0x60, %rdi
callq 0x10fc20
jmp 0xd3d00
movq $0x0, -0x40(%rbp)
movq -0x40(%rbp), %rax
movq -0x8(%rbp), %rcx
cmpq 0x2b0(%rcx), %rax
jae 0xd3ddf
movq -0x8(%rbp), %rax
movq 0x2a8(%rax), %rax
movq -0x40(%rbp), %rcx
movq (%rax,%rcx,8), %rax
movq %rax, -0x48(%rbp)
movq -0x48(%rbp), %rdi
callq 0x1122a0
movq -0x40(%rbp), %rax
addq $0x1, %rax
movq %rax, -0x40(%rbp)
jmp 0xd3da0
movq -0x8(%rbp), %rdi
addq $0x2a0, %rdi            # imm = 0x2A0
callq 0x969e0
movq -0x8(%rbp), %rdi
addq $0x20, %rdi
callq 0xab210
movq -0x8(%rbp), %rdi
callq 0x969e0
movq -0x8(%rbp), %rdi
addq $0x60, %rdi
callq 0x10fc70
movq -0x8(%rbp), %rdi
addq $0x60, %rdi
callq 0x10fa50
addq $0x50, %rsp
popq %rbp
retq
nopw %cs:(%rax,%rax)
nop