// File: /workspace/github_c_makefile_star2_O1/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 0x11f515
cmpq $0x0, 0x2b0(%r14)
je 0xf5cc5
xorl %ebx, %ebx
movq 0x2a8(%r14), %rax
movq (%rax,%rbx,8), %r15
movq %r15, %rdi
callq 0x1210d4
movq %r15, %rdi
movl $0x1, %esi
callq 0x121262
incq %rbx
cmpq 0x2b0(%r14), %rbx
jb 0xf5c99
cmpq $0x0, 0x10(%r14)
je 0xf5e5e
movabsq $0x100000001b3, %r12    # imm = 0x100000001B3
leaq 0x20(%r14), %rbx
movq %rbx, (%rsp)
movq %r14, %rdi
callq 0xc4154
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 0xd20d5
movq %r13, %rdi
callq 0x11f547
movabsq $0x782b96602f424981, %rax # imm = 0x782B96602F424981
cmpq %rax, %r15
jne 0xf5d9d
movq %rbp, %rdi
callq 0x101990
jmp 0xf5e44
movq %r13, %rbx
movq (%rbp), %r15
leaq 0xb36bd(%rip), %rdx     # 0x1a9468
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 0xf5e00
movq 0x10(%rax), %rdx
movl $0x18, %ecx
cmpq %r15, %rdx
je 0xf5e00
movq 0x20(%rax), %rdx
movl $0x28, %ecx
cmpq %r15, %rdx
je 0xf5e00
movq 0x30(%rax), %rdx
movl $0x38, %ecx
cmpq %r15, %rdx
jne 0xf5e59
movq (%rax,%rcx), %r13
testq %r13, %r13
jne 0xf5e30
movabsq $0x782b96602f424981, %rdi # imm = 0x782B96602F424981
movq %r15, %rsi
callq 0xf3f85
movq %rax, %r13
leaq 0xb3643(%rip), %rdi     # 0x1a9468
movq %r15, %rsi
movq %rax, %rdx
callq 0x12128c
movq %r13, %rdi
movq %rbp, %rsi
callq *0xb8(%r13)
movq %rbx, %r13
movq (%rsp), %rbx
movq %r13, %rdi
callq 0x11f515
cmpq $0x0, 0x10(%r14)
jne 0xf5ce2
jmp 0xf5e5e
xorl %r13d, %r13d
jmp 0xf5e04
cmpq $0x0, 0x2b0(%r14)
je 0xf5e86
xorl %ebx, %ebx
movq 0x2a8(%r14), %rax
movq (%rax,%rbx,8), %rdi
callq 0x121165
incq %rbx
cmpq 0x2b0(%r14), %rbx
jb 0xf5e6a
leaq 0x2a0(%r14), %rdi
callq 0xc3e55
leaq 0x20(%r14), %rdi
callq 0xd144d
movq %r14, %rdi
callq 0xc3e55
movq %r13, %rdi
callq 0x11f547
movq %r13, %rdi
addq $0x8, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
jmp 0x11f3ee
nopl (%rax)