Permalink
Fetching contributors…
Cannot retrieve contributors at this time
269 lines (188 sloc) 9.04 KB
; 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.
; ***********************************************************************
; File: JitHelpers_InlineGetThread.asm, see history in jithelp.asm
;
; Notes: These routinues will be patched at runtime with the location in
; the TLS to find the Thread* and are the fastest implementation
; of their specific functionality.
; ***********************************************************************
include AsmMacros.inc
include asmconstants.inc
; Min amount of stack space that a nested function should allocate.
MIN_SIZE equ 28h
JIT_NEW equ ?JIT_New@@YAPEAVObject@@PEAUCORINFO_CLASS_STRUCT_@@@Z
Object__DEBUG_SetAppDomain equ ?DEBUG_SetAppDomain@Object@@QEAAXPEAVAppDomain@@@Z
CopyValueClassUnchecked equ ?CopyValueClassUnchecked@@YAXPEAX0PEAVMethodTable@@@Z
JIT_Box equ ?JIT_Box@@YAPEAVObject@@PEAUCORINFO_CLASS_STRUCT_@@PEAX@Z
g_pStringClass equ ?g_pStringClass@@3PEAVMethodTable@@EA
FramedAllocateString equ ?FramedAllocateString@@YAPEAVStringObject@@K@Z
JIT_NewArr1 equ ?JIT_NewArr1@@YAPEAVObject@@PEAUCORINFO_CLASS_STRUCT_@@_J@Z
INVALIDGCVALUE equ 0CCCCCCCDh
extern JIT_NEW:proc
extern CopyValueClassUnchecked:proc
extern JIT_Box:proc
extern g_pStringClass:QWORD
extern FramedAllocateString:proc
extern JIT_NewArr1:proc
extern JIT_InternalThrow:proc
; IN: rcx: MethodTable*
; OUT: rax: new object
LEAF_ENTRY JIT_TrialAllocSFastMP_InlineGetThread, _TEXT
mov edx, [rcx + OFFSET__MethodTable__m_BaseSize]
; m_BaseSize is guaranteed to be a multiple of 8.
INLINE_GETTHREAD r11
mov r10, [r11 + OFFSET__Thread__m_alloc_context__alloc_limit]
mov rax, [r11 + OFFSET__Thread__m_alloc_context__alloc_ptr]
add rdx, rax
cmp rdx, r10
ja AllocFailed
mov [r11 + OFFSET__Thread__m_alloc_context__alloc_ptr], rdx
mov [rax], rcx
ret
AllocFailed:
jmp JIT_NEW
LEAF_END JIT_TrialAllocSFastMP_InlineGetThread, _TEXT
; HCIMPL2(Object*, JIT_Box, CORINFO_CLASS_HANDLE type, void* unboxedData)
NESTED_ENTRY JIT_BoxFastMP_InlineGetThread, _TEXT
mov rax, [rcx + OFFSETOF__MethodTable__m_pWriteableData]
; Check whether the class has not been initialized
test dword ptr [rax + OFFSETOF__MethodTableWriteableData__m_dwFlags], MethodTableWriteableData__enum_flag_Unrestored
jnz ClassNotInited
mov r8d, [rcx + OFFSET__MethodTable__m_BaseSize]
; m_BaseSize is guaranteed to be a multiple of 8.
INLINE_GETTHREAD r11
mov r10, [r11 + OFFSET__Thread__m_alloc_context__alloc_limit]
mov rax, [r11 + OFFSET__Thread__m_alloc_context__alloc_ptr]
add r8, rax
cmp r8, r10
ja AllocFailed
mov [r11 + OFFSET__Thread__m_alloc_context__alloc_ptr], r8
mov [rax], rcx
; Check whether the object contains pointers
test dword ptr [rcx + OFFSETOF__MethodTable__m_dwFlags], MethodTable__enum_flag_ContainsPointers
jnz ContainsPointers
; We have no pointers - emit a simple inline copy loop
; Copy the contents from the end
mov ecx, [rcx + OFFSET__MethodTable__m_BaseSize]
sub ecx, 18h ; sizeof(ObjHeader) + sizeof(Object) + last slot
align 16
CopyLoop:
mov r8, [rdx+rcx]
mov [rax+rcx+8], r8
sub ecx, 8
jge CopyLoop
REPRET
ContainsPointers:
; Do call to CopyValueClassUnchecked(object, data, pMT)
push_vol_reg rax
alloc_stack 20h
END_PROLOGUE
mov r8, rcx
lea rcx, [rax + 8]
call CopyValueClassUnchecked
add rsp, 20h
pop rax
ret
ClassNotInited:
AllocFailed:
jmp JIT_Box
NESTED_END JIT_BoxFastMP_InlineGetThread, _TEXT
LEAF_ENTRY AllocateStringFastMP_InlineGetThread, _TEXT
; We were passed the number of characters in ECX
; we need to load the method table for string from the global
mov r9, [g_pStringClass]
; Instead of doing elaborate overflow checks, we just limit the number of elements
; to (LARGE_OBJECT_SIZE - 256)/sizeof(WCHAR) or less.
; This will avoid all overflow problems, as well as making sure
; big string objects are correctly allocated in the big object heap.
cmp ecx, (ASM_LARGE_OBJECT_SIZE - 256)/2
jae OversizedString
; Calculate the final size to allocate.
; We need to calculate baseSize + cnt*2, then round that up by adding 7 and anding ~7.
lea edx, [STRING_BASE_SIZE + ecx*2 + 7]
and edx, -8
INLINE_GETTHREAD r11
mov r10, [r11 + OFFSET__Thread__m_alloc_context__alloc_limit]
mov rax, [r11 + OFFSET__Thread__m_alloc_context__alloc_ptr]
add rdx, rax
cmp rdx, r10
ja AllocFailed
mov [r11 + OFFSET__Thread__m_alloc_context__alloc_ptr], rdx
mov [rax], r9
mov [rax + OFFSETOF__StringObject__m_StringLength], ecx
ret
OversizedString:
AllocFailed:
jmp FramedAllocateString
LEAF_END AllocateStringFastMP_InlineGetThread, _TEXT
; HCIMPL2(Object*, JIT_NewArr1VC_MP_InlineGetThread, CORINFO_CLASS_HANDLE arrayMT, INT_PTR size)
LEAF_ENTRY JIT_NewArr1VC_MP_InlineGetThread, _TEXT
; We were passed a (shared) method table in RCX, which contains the element type.
; The element count is in RDX
; NOTE: if this code is ported for CORINFO_HELP_NEWSFAST_ALIGN8, it will need
; to emulate the double-specific behavior of JIT_TrialAlloc::GenAllocArray.
; Do a conservative check here. This is to avoid overflow while doing the calculations. We don't
; have to worry about "large" objects, since the allocation quantum is never big enough for
; LARGE_OBJECT_SIZE.
; For Value Classes, this needs to be 2^16 - slack (2^32 / max component size),
; The slack includes the size for the array header and round-up ; for alignment. Use 256 for the
; slack value out of laziness.
; In both cases we do a final overflow check after adding to the alloc_ptr.
cmp rdx, (65535 - 256)
jae OversizedArray
movzx r8d, word ptr [rcx + OFFSETOF__MethodTable__m_dwFlags] ; component size is low 16 bits
imul r8d, edx
add r8d, dword ptr [rcx + OFFSET__MethodTable__m_BaseSize]
; round the size to a multiple of 8
add r8d, 7
and r8d, -8
INLINE_GETTHREAD r11
mov r10, [r11 + OFFSET__Thread__m_alloc_context__alloc_limit]
mov rax, [r11 + OFFSET__Thread__m_alloc_context__alloc_ptr]
add r8, rax
jc AllocFailed
cmp r8, r10
ja AllocFailed
mov [r11 + OFFSET__Thread__m_alloc_context__alloc_ptr], r8
mov [rax], rcx
mov dword ptr [rax + OFFSETOF__ArrayBase__m_NumComponents], edx
ret
OversizedArray:
AllocFailed:
jmp JIT_NewArr1
LEAF_END JIT_NewArr1VC_MP_InlineGetThread, _TEXT
; HCIMPL2(Object*, JIT_NewArr1OBJ_MP_InlineGetThread, CORINFO_CLASS_HANDLE arrayMT, INT_PTR size)
LEAF_ENTRY JIT_NewArr1OBJ_MP_InlineGetThread, _TEXT
; We were passed a (shared) method table in RCX, which contains the element type.
; The element count is in RDX
; NOTE: if this code is ported for CORINFO_HELP_NEWSFAST_ALIGN8, it will need
; to emulate the double-specific behavior of JIT_TrialAlloc::GenAllocArray.
; Verifies that LARGE_OBJECT_SIZE fits in 32-bit. This allows us to do array size
; arithmetic using 32-bit registers.
.erre ASM_LARGE_OBJECT_SIZE lt 100000000h
cmp rdx, (ASM_LARGE_OBJECT_SIZE - 256)/8 ; sizeof(void*)
jae OversizedArray
; In this case we know the element size is sizeof(void *), or 8 for x64
; This helps us in two ways - we can shift instead of multiplying, and
; there's no need to align the size either
mov r8d, dword ptr [rcx + OFFSET__MethodTable__m_BaseSize]
lea r8d, [r8d + edx * 8]
; No need for rounding in this case - element size is 8, and m_BaseSize is guaranteed
; to be a multiple of 8.
INLINE_GETTHREAD r11
mov r10, [r11 + OFFSET__Thread__m_alloc_context__alloc_limit]
mov rax, [r11 + OFFSET__Thread__m_alloc_context__alloc_ptr]
add r8, rax
cmp r8, r10
ja AllocFailed
mov [r11 + OFFSET__Thread__m_alloc_context__alloc_ptr], r8
mov [rax], rcx
mov dword ptr [rax + OFFSETOF__ArrayBase__m_NumComponents], edx
ret
OversizedArray:
AllocFailed:
jmp JIT_NewArr1
LEAF_END JIT_NewArr1OBJ_MP_InlineGetThread, _TEXT
end