// File: /workspace/github_c_makefile_star2_O2/johsteffens[P]beth/lib/bcore/bcore_spect.c
// Function: bcore_spect_get_typed
vc_t bcore_spect_get_typed( tp_t p_type, tp_t o_type )
{
    assert( hmap_s_g != NULL );

    tp_t sig = bcore_tp_fold_tp( p_type, o_type );
    vc_t val = hmap_s_cache_get( hmap_s_g, sig );
    if( val ) return val;

    bcore_mutex_s_lock( &hmap_s_g->mutex );
    vd_t* vdp = bcore_hmap_u3vd_s_get( &hmap_s_g->map, sig );
    if( vdp )
    {
        hmap_s_cache_set( hmap_s_g, sig, *vdp );
        bcore_mutex_s_unlock( &hmap_s_g->mutex );
        return *vdp;
    }

    /** Recursion counter used to detect recursions in bcore_spect_get_typed.
     *  This allows detecting certain types of cyclic reflections, which the
     *  framework cannot handle.
     */
    static sz_t recursion_count = 0;
    const sz_t recursion_count_limit = 256;
    recursion_count++;

    // Unlock because create_from_self may make use of registry
    bcore_mutex_s_unlock( &hmap_s_g->mutex );

    if( recursion_count > recursion_count_limit )
    {
        ERR_fa
        (
            "Recursion limit '#<sz_t>' was reached at object '#<sc_t>'.\n"
            "\n"
            "\tThis happens when static elements across multiple reflections form a cycle.\n"
            "\n"
            "\tPossible Solution:\n"
            "\t   1. Determine the cycle.\n"
            "\t   2. Unspecify the type in one element or make it non-static.\n"
            "\n"
            "\tTyped-links and aware-links are both non-static links.\n"
            "\n"
            "\tExample:\n"
            "\t  foo_s => bar;       // could be cyclic\n"
            "\t  aware foo_s => bar; // not cyclic (foo_s must be aware)\n"
            "\t  typed foo_s => bar; // not cyclic\n"
            "\t  vd_t bar;           // not cyclic\n"
            "\n",
            recursion_count_limit,
            ifnameof( o_type )
        );
    }

    const bcore_self_s* p_self = bcore_flect_get_self( p_type );
    const bcore_self_s* o_self = bcore_flect_get_self( o_type );
    vd_t spect = NULL;
    vd_t discard_spect = NULL; // in case multiple threads try to register, redundant creations must be discarded

    fp_t create_from_self = bcore_self_s_try_external_fp( p_self, bcore_name_enroll( "bcore_spect_fp_create_from_self" ), 0 );
    if( create_from_self )
    {
        spect = ( ( bcore_spect_fp_create_from_self )create_from_self )( o_self );
    }
    else // use generic creation
    {
        spect = bcore_spect_create_from_self( p_self, o_self );
    }

    // Lock for registering the perspective (if still not registered)
    bcore_mutex_s_lock( &hmap_s_g->mutex );

    recursion_count--;

    // Due to the unlocked period, the perspective might have
    // been registered by another thread meanwhile.
    // In that case we discard spect and retrieve the registered version.
    if( bcore_hmap_u3vd_s_exists( &hmap_s_g->map, sig ) )
    {
        discard_spect = spect;
        spect = *bcore_hmap_u3vd_s_get( &hmap_s_g->map, sig );
    }
    else
    {
        bcore_arr_vd_s_push( &hmap_s_g->arr, spect );
        bcore_hmap_u3vd_s_set( &hmap_s_g->map, sig, spect, false );
    }

    bcore_mutex_s_unlock( &hmap_s_g->mutex );

    if( discard_spect ) bcore_inst_a_discard( discard_spect );
    return spect;
}

// Assembly:
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
movq %rsi, %r14
movq %rdi, %r15
callq 0x79b3e
movq %rax, %rbx
movq 0x9e256(%rip), %r13     # 0x117e08
leaq 0x88(%r13), %rdi
movq %rax, %rsi
callq 0x79a2a
movq %rax, %r12
testq %rax, %rax
jne 0x79d4c
addq $0x60, %r13
movq %r13, %rdi
callq 0x97ae2
movq 0x9e228(%rip), %rdi     # 0x117e08
addq $0x20, %rdi
movq %rbx, %rsi
callq 0x66b16
testq %rax, %rax
je 0x79c24
movq %rax, %r12
movq (%rax), %rdx
movl $0x88, %edi
addq 0x9e205(%rip), %rdi     # 0x117e08
movq %rbx, %rsi
callq 0x98d4b
movq 0x9e1f6(%rip), %rdi     # 0x117e08
addq $0x60, %rdi
callq 0x97b12
movq (%r12), %r12
jmp 0x79d4c
incq 0x9e1e5(%rip)           # 0x117e10
movq 0x9e1d6(%rip), %rdi     # 0x117e08
addq $0x60, %rdi
callq 0x97b12
cmpq $0x101, 0x9e1ca(%rip) # imm = 0x101
jl 0x79c7a
movq %r14, %rdi
callq 0x79d59
leaq 0x4c763(%rip), %rdi     # 0xc63ba
leaq 0x4c772(%rip), %rsi     # 0xc63d0
leaq 0x4c779(%rip), %rcx     # 0xc63de
movl $0x100, %r8d            # imm = 0x100
movl $0x134, %edx            # imm = 0x134
movq %rax, %r9
xorl %eax, %eax
callq 0x60186
movq %r15, %rdi
callq 0x64ca3
movq %rax, %r15
movq %r14, %rdi
callq 0x64ca3
movq %rax, %r14
leaq 0x4c936(%rip), %rdi     # 0xc65cd
callq 0x7227a
movq %r15, %rdi
movq %rax, %rsi
xorl %edx, %edx
callq 0x6449c
testq %rax, %rax
je 0x79cb5
movq %r14, %rdi
callq *%rax
jmp 0x79cc0
movq %r15, %rdi
movq %r14, %rsi
callq 0x79d6f
movq %rax, %r14
movq 0x9e13e(%rip), %rdi     # 0x117e08
addq $0x60, %rdi
callq 0x97ae2
decq 0x9e136(%rip)           # 0x117e10
movq 0x9e127(%rip), %rdi     # 0x117e08
addq $0x20, %rdi
movq %rbx, %rsi
callq 0x6721a
movq 0x9e114(%rip), %rdi     # 0x117e08
testb %al, %al
je 0x79d09
addq $0x20, %rdi
movq %rbx, %rsi
callq 0x66b16
movq (%rax), %r12
jmp 0x79d2f
movq %r14, %rsi
callq 0x5cc09
movq 0x9e0f0(%rip), %rdi     # 0x117e08
addq $0x20, %rdi
movq %rbx, %rsi
movq %r14, %rdx
xorl %ecx, %ecx
callq 0x66bf0
movq %r14, %r12
xorl %r14d, %r14d
movq 0x9e0d2(%rip), %rdi     # 0x117e08
addq $0x60, %rdi
callq 0x97b12
testq %r14, %r14
je 0x79d4c
movq %r14, %rdi
callq 0x7a289
movq %r12, %rax
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
retq