// Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. .intel_syntax noprefix #include // generated by the build from AsmOffsets.cpp #include // Allocate non-array, non-finalizable object. If the allocation doesn't fit into the current thread's // allocation context then automatically fallback to the slow allocation path. // RDI == EEType NESTED_ENTRY RhpNewFast, _TEXT, NoHandler push_nonvol_reg rbx mov rbx, rdi // rax = GetThread() INLINE_GETTHREAD // // rbx contains EEType pointer // mov edx, [rbx + OFFSETOF__EEType__m_uBaseSize] // // rax: Thread pointer // rbx: EEType pointer // rdx: base size // mov rsi, [rax + OFFSETOF__Thread__m_alloc_context__alloc_ptr] add rdx, rsi cmp rdx, [rax + OFFSETOF__Thread__m_alloc_context__alloc_limit] ja LOCAL_LABEL(RhpNewFast_RarePath) // set the new alloc pointer mov [rax + OFFSETOF__Thread__m_alloc_context__alloc_ptr], rdx mov rax, rsi // set the new object's EEType pointer mov [rsi], rbx .cfi_remember_state pop_nonvol_reg rbx ret .cfi_restore_state .cfi_def_cfa_offset 16 // workaround cfi_restore_state bug LOCAL_LABEL(RhpNewFast_RarePath): mov rdi, rbx // restore EEType xor esi, esi pop_nonvol_reg rbx jmp C_FUNC(RhpNewObject) NESTED_END RhpNewFast, _TEXT // Allocate non-array object with finalizer // RDI == EEType LEAF_ENTRY RhpNewFinalizable, _TEXT mov esi, GC_ALLOC_FINALIZE jmp C_FUNC(RhpNewObject) LEAF_END RhpNewFinalizable, _TEXT // Allocate non-array object // RDI == EEType // ESI == alloc flags NESTED_ENTRY RhpNewObject, _TEXT, NoHandler PUSH_COOP_PINVOKE_FRAME rcx END_PROLOGUE // RCX: transition frame // Preserve the EEType in RBX mov rbx, rdi mov edx, [rdi + OFFSETOF__EEType__m_uBaseSize] // cbSize // Call the rest of the allocation helper. // void* RhpGcAlloc(EEType *pEEType, UInt32 uFlags, UIntNative cbSize, void * pTransitionFrame) call C_FUNC(RhpGcAlloc) // Set the new object's EEType pointer on success. test rax, rax jz LOCAL_LABEL(NewOutOfMemory) mov [rax + OFFSETOF__Object__m_pEEType], rbx // If the object is bigger than RH_LARGE_OBJECT_SIZE, we must publish it to the BGC mov esi, [rbx + OFFSETOF__EEType__m_uBaseSize] .att_syntax cmp $RH_LARGE_OBJECT_SIZE, %rsi .intel_syntax noprefix jb LOCAL_LABEL(New_SkipPublish) mov rdi, rax // rdi: object // rsi: already contains object size call C_FUNC(RhpPublishObject) // rax: this function returns the object that was passed-in LOCAL_LABEL(New_SkipPublish): .cfi_remember_state POP_COOP_PINVOKE_FRAME ret .cfi_restore_state .cfi_def_cfa_offset 96 // workaround cfi_restore_state bug LOCAL_LABEL(NewOutOfMemory): // This is the OOM failure path. We're going to tail-call to a managed helper that will throw // an out of memory exception that the caller of this allocator understands. mov rdi, rbx // EEType pointer xor esi, esi // Indicate that we should throw OOM. POP_COOP_PINVOKE_FRAME jmp C_FUNC(RhExceptionHandling_FailedAllocation) NESTED_END RhpNewObject, _TEXT // Allocate a string. // RDI == EEType // ESI == character/element count NESTED_ENTRY RhNewString, _TEXT, NoHandler // we want to limit the element count to the non-negative 32-bit int range cmp rsi, 07fffffffh ja LOCAL_LABEL(StringSizeOverflow) push_nonvol_reg rbx push_nonvol_reg r12 push_register rcx // padding mov rbx, rdi // save EEType mov r12, rsi // save element count // rax = GetThread() INLINE_GETTHREAD mov rcx, rax // rcx = Thread* // Compute overall allocation size (align(base size + (element size * elements), 8)). lea rax, [r12 * STRING_COMPONENT_SIZE + STRING_BASE_SIZE + 7] and rax, -8 // rax == string size // rbx == EEType // rcx == Thread* // r12 == element count mov rdx, rax add rax, [rcx + OFFSETOF__Thread__m_alloc_context__alloc_ptr] jc LOCAL_LABEL(RhNewString_RarePath) // rax == new alloc ptr // rbx == EEType // rcx == Thread* // rdx == string size // r12 == element count cmp rax, [rcx + OFFSETOF__Thread__m_alloc_context__alloc_limit] ja LOCAL_LABEL(RhNewString_RarePath) mov [rcx + OFFSETOF__Thread__m_alloc_context__alloc_ptr], rax // calc the new object pointer sub rax, rdx mov [rax + OFFSETOF__Object__m_pEEType], rbx mov [rax + OFFSETOF__String__m_Length], r12d .cfi_remember_state pop_register rcx // padding pop_nonvol_reg r12 pop_nonvol_reg rbx ret .cfi_restore_state .cfi_def_cfa_offset 32 // workaround cfi_restore_state bug LOCAL_LABEL(RhNewString_RarePath): mov rdi, rbx // restore EEType mov rsi, r12 // restore element count // passing string size in rdx pop_register rcx // padding pop_nonvol_reg r12 pop_nonvol_reg rbx jmp C_FUNC(RhpNewArrayRare) LOCAL_LABEL(StringSizeOverflow): // We get here if the size of the final string object can't be represented as an unsigned // 32-bit value. We're going to tail-call to a managed helper that will throw // an OOM exception that the caller of this allocator understands. // rdi holds EEType pointer already xor esi, esi // Indicate that we should throw OOM. jmp C_FUNC(RhExceptionHandling_FailedAllocation) NESTED_END RhNewString, _TEXT // Allocate one dimensional, zero based array (SZARRAY). // RDI == EEType // ESI == element count NESTED_ENTRY RhpNewArray, _TEXT, NoHandler // we want to limit the element count to the non-negative 32-bit int range cmp rsi, 07fffffffh ja LOCAL_LABEL(ArraySizeOverflow) push_nonvol_reg rbx push_nonvol_reg r12 push_register rcx // padding mov rbx, rdi // save EEType mov r12, rsi // save element count // rax = GetThread() INLINE_GETTHREAD mov rcx, rax // rcx = Thread* // Compute overall allocation size (align(base size + (element size * elements), 8)). movzx eax, word ptr [rbx + OFFSETOF__EEType__m_usComponentSize] mul r12 mov edx, [rbx + OFFSETOF__EEType__m_uBaseSize] add rax, rdx add rax, 7 and rax, -8 // rax == array size // rbx == EEType // rcx == Thread* // r12 == element count mov rdx, rax add rax, [rcx + OFFSETOF__Thread__m_alloc_context__alloc_ptr] jc LOCAL_LABEL(RhpNewArray_RarePath) // rax == new alloc ptr // rbx == EEType // rcx == Thread* // rdx == array size // r12 == element count cmp rax, [rcx + OFFSETOF__Thread__m_alloc_context__alloc_limit] ja LOCAL_LABEL(RhpNewArray_RarePath) mov [rcx + OFFSETOF__Thread__m_alloc_context__alloc_ptr], rax // calc the new object pointer sub rax, rdx mov [rax + OFFSETOF__Object__m_pEEType], rbx mov [rax + OFFSETOF__Array__m_Length], r12d .cfi_remember_state pop_register rcx // padding pop_nonvol_reg r12 pop_nonvol_reg rbx ret .cfi_restore_state .cfi_def_cfa_offset 32 // workaround cfi_restore_state bug LOCAL_LABEL(RhpNewArray_RarePath): mov rdi, rbx // restore EEType mov rsi, r12 // restore element count // passing array size in rdx pop_register rcx // padding pop_nonvol_reg r12 pop_nonvol_reg rbx jmp C_FUNC(RhpNewArrayRare) LOCAL_LABEL(ArraySizeOverflow): // We get here if the size of the final array object can't be represented as an unsigned // 32-bit value. We're going to tail-call to a managed helper that will throw // an overflow exception that the caller of this allocator understands. // rdi holds EEType pointer already mov esi, 1 // Indicate that we should throw OverflowException jmp C_FUNC(RhExceptionHandling_FailedAllocation) NESTED_END RhpNewArray, _TEXT NESTED_ENTRY RhpNewArrayRare, _TEXT, NoHandler // rdi == EEType // rsi == element count // rdx == array size PUSH_COOP_PINVOKE_FRAME rcx END_PROLOGUE // rcx: transition frame // Preserve the EEType in RBX mov rbx, rdi // Preserve the element count in R12 mov r12, rsi // Preserve the size in R13 mov r13, rdx // passing EEType in rdi xor rsi, rsi // uFlags // pasing size in rdx // pasing pTransitionFrame in rcx // Call the rest of the allocation helper. // void* RhpGcAlloc(EEType *pEEType, UInt32 uFlags, UIntNative cbSize, void * pTransitionFrame) call C_FUNC(RhpGcAlloc) // Set the new object's EEType pointer and length on success. test rax, rax jz LOCAL_LABEL(ArrayOutOfMemory) mov [rax + OFFSETOF__Object__m_pEEType], rbx mov [rax + OFFSETOF__Array__m_Length], r12d // If the object is bigger than RH_LARGE_OBJECT_SIZE, we must publish it to the BGC .att_syntax cmp $RH_LARGE_OBJECT_SIZE, %r13 .intel_syntax noprefix jb LOCAL_LABEL(NewArray_SkipPublish) mov rdi, rax // rcx: object mov rsi, r13 // rdx: object size call C_FUNC(RhpPublishObject) // rax: this function returns the object that was passed-in LOCAL_LABEL(NewArray_SkipPublish): .cfi_remember_state POP_COOP_PINVOKE_FRAME ret .cfi_restore_state .cfi_def_cfa_offset 96 // workaround cfi_restore_state bug LOCAL_LABEL(ArrayOutOfMemory): // This is the OOM failure path. We're going to tail-call to a managed helper that will throw // an out of memory exception that the caller of this allocator understands. mov rdi, rbx // EEType pointer xor esi, esi // Indicate that we should throw OOM. POP_COOP_PINVOKE_FRAME jmp C_FUNC(RhExceptionHandling_FailedAllocation) NESTED_END RhpNewArrayRare, _TEXT