ccmglue_cpu.s
来自「This is a resource based on j2me embedde」· S 代码 · 共 812 行 · 第 1/2 页
S
812 行
/* * @(#)ccmglue_cpu.S 1.7 06/10/23 * * Portions Copyright 2000-2008 Sun Microsystems, Inc. All Rights * Reserved. Use is subject to license terms. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License version * 2 only, as published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License version 2 for more details (a copy is * included at /legal/license.txt). * * You should have received a copy of the GNU General Public License * version 2 along with this work; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA * * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa * Clara, CA 95054 or visit www.sun.com if you need additional * information or have any questions. *//* * The file includes glue code that aids in the calling of some the * CCM C helpers, and also do shortcuts to try to avoid having * to call the helpers. */ #include "javavm/include/asmmacros_cpu.h"#include "javavm/include/jit/jitasmmacros_cpu.h"#include "javavm/include/jit/jitasmconstants.h"#include "javavm/include/porting/jit/jit.h"#include "javavm/include/jit/jitcisc_cpu.h"#include "javavm/include/porting/sync.h"#if (CVM_FASTLOCK_TYPE != CVM_FASTLOCK_ATOMICOPS)#error "Only CVM_FASTLOCK_TYPE == CVM_FASTLOCK_ATOMICOPS supported"#endif#ifdef CVM_DEBUG_ASSERTS.file "ccmglue_cpu.S"ccmglue_cpu_filename:.asciz "ccmglue_cpu.S"CVMCCMruntimeThrowNullPointerExceptionGlue_assert_expression:.asciz "%eax == (%esp)"#endif/* CVMCCMruntimeThrowDivideByZeroGlue */ENTRY(CVMCCMruntimeThrowDivideByZeroGlue ) FIXUP_FRAMES_0(JFP, A1 /* scratch */, CVMCCMruntimeThrowDivideByZeroGlue_L1)CVMCCMruntimeThrowDivideByZeroGlue_L1: CALL_HELPER_4(A1 /* scratch */, CCEE_AS_ARG, EE_AS_ARG, AS_ARG($SYM_NAME(java_lang_ArithmeticException_Classblock )), AS_ARG($divideByZeroString), SYM_NAME(CVMCCMruntimeThrowClass))SET_SIZE( CVMCCMruntimeThrowDivideByZeroGlue )/* CVMCCMruntimeCheckArrayAssignableGlue */ENTRY(CVMCCMruntimeCheckArrayAssignableGlue )#define SCRATCH A1 # A3 = cb of array object (with low bits still set) # A4 = cb or rhs object (with low bits still set) andl $~3, A3 # clear low bits of array cb movl OFFSET_CVMClassBlock_arrayInfoX(A3), A3 # arraycb->arrayInfo andl $~3, A4 # clear low bits of rhs cb movl OFFSET_CVMArrayInfo_elementCb(A3), A3 # arrayInfo->elemCb cmpl A3, A4 # check if elemClass(arr) == class(rhs) je CVMCCMruntimeCheckArrayAssignableGlue_L1 movl SYM_NAME(java_lang_Object_Classblock), SCRATCH cmpl A3, SCRATCH # check if elemClass(arr) == Object jne CVMCCMruntimeCheckArrayAssignableGlue_L2CVMCCMruntimeCheckArrayAssignableGlue_L1: retCVMCCMruntimeCheckArrayAssignableGlue_L2: FIXUP_FRAMES_1(JFP, SCRATCH, A3, CVMCCMruntimeCheckArrayAssignableGlue_L3)CVMCCMruntimeCheckArrayAssignableGlue_L3: CALL_HELPER_4(SCRATCH, CCEE_AS_ARG, EE_AS_ARG, AS_ARG(A3), AS_ARG(A4), SYM_NAME(CVMCCMruntimeCheckArrayAssignable))#undef SCRATCHSET_SIZE( CVMCCMruntimeCheckArrayAssignableGlue )/* do a checkcast check */ENTRY(CVMCCMruntimeCheckCastGlue )#define GUESS_CB_ADDR A4 # A1 = object to cast # A3 = castCb # 0(%esp) = guess cb address # cc = eq if A1 is null popl GUESS_CB_ADDR # return address (points to first byte after # call instruction == first byte of guess cb) je CVMCCMruntimeCheckCastGlue_L1 # return FALSE if object is NULL movl 0(A1), A2 # A2 = object.cb movl 0(GUESS_CB_ADDR), A1 # load the guess cb andl $~3, A2 # mask off low bits of object cb cmpl A1, A2 # see if guess is correct jne call_checkcast_helper mov $1, A1 # return TRUE if equalCVMCCMruntimeCheckCastGlue_L1: add $4, GUESS_CB_ADDR jmp *GUESS_CB_ADDR # return, null or same as last successful castcall_checkcast_helper: /* need to call the helper * A2 = objectCb * A3 = instanceCb * A4 = cache address (setup by CALL_HELPER_AND_PASS_CACHE_ADDR) */#define SCRATCH A1 pushl GUESS_CB_ADDR # save return address add $4, 0(%esp) # == instruction after guess cb FIXUP_FRAMES_2(JFP, SCRATCH, A2, A3, call_checkcast_helper_L1)call_checkcast_helper_L1: CALL_HELPER_4(SCRATCH, CCEE_AS_ARG, AS_ARG(A2), AS_ARG(A3), AS_ARG(A4), SYM_NAME(CVMCCMruntimeCheckCast))#undef SCRATCH#undef GUESS_CB_ADDRSET_SIZE( CVMCCMruntimeCheckCastGlue )/* do an instanceof check */ENTRY(CVMCCMruntimeInstanceOfGlue )#define GUESS_CB_ADDR A4 # A1 = object to cast # A3 = instanceofCb # 0(%esp) = guess cb address # cc = eq if A1 is null popl GUESS_CB_ADDR # return address (points to first byte after # call instruction == first byte of guess cb) je CVMCCMruntimeInstanceOfGlue_L1 # return FALSE if object is NULL movl 0(A1), A2 # A2 = object.cb movl 0(GUESS_CB_ADDR), A1 # load the guess cb andl $~3, A2 # mask off low bits of object cb cmpl A1, A2 # see if guess is correct jne call_instanceof_helper mov $1, A1 # return TRUE if equalCVMCCMruntimeInstanceOfGlue_L1: add $4, GUESS_CB_ADDR jmp *GUESS_CB_ADDR # return, null or same as last successful cast call_instanceof_helper: /* need to call the helper * A2 = objectCb * A3 = instanceCb * A4 = cache address (setup by CALL_HELPER_AND_PASS_CACHE_ADDR) */#define SCRATCH A1 pushl GUESS_CB_ADDR # save return address add $4, 0(%esp) # == instruction after guess cb CALL_HELPER_4(SCRATCH, CCEE_AS_ARG, AS_ARG(A2), AS_ARG(A3), AS_ARG(A4), SYM_NAME(CVMCCMruntimeInstanceOf))#undef SCRATCH#undef GUESS_CB_ADDRSET_SIZE( CVMCCMruntimeInstanceOfGlue )/* * Resolve a cp entry and run the clinit if necessary */#define RTARGET A2#define SCRATCH A1ENTRY(CVMCCMruntimeResolveGlue ) # %o2 = cpIndex # %o7 = call instr # +4 = delay slot # +8 = address of branch to try again # +12 = cachedConstant # +16 = helper return # %g1 = address of ccm helper to call movl 0(%esp), A4 /* return address here is address of cachedConstant */ addl $4, 0(%esp) /* modify the return address to the insn after the cached Constant */ CALL_HELPER_4(SCRATCH, CCEE_AS_ARG, EE_AS_ARG, AS_ARG(A3), AS_ARG(A4), *RTARGET)#define RESOLVE(f) \ ENTRY2(f,Glue) \ movl $SYM_NAME(f), RTARGET ; \ jmp SYM_NAME(CVMCCMruntimeResolveGlue) ;RESOLVE(CVMCCMruntimeResolveNewClassBlockAndClinit)RESOLVE(CVMCCMruntimeResolveGetstaticFieldBlockAndClinit)RESOLVE(CVMCCMruntimeResolvePutstaticFieldBlockAndClinit)RESOLVE(CVMCCMruntimeResolveStaticMethodBlockAndClinit)RESOLVE(CVMCCMruntimeResolveClassBlock)RESOLVE(CVMCCMruntimeResolveArrayClassBlock)RESOLVE(CVMCCMruntimeResolveGetfieldFieldOffset)RESOLVE(CVMCCMruntimeResolvePutfieldFieldOffset)RESOLVE(CVMCCMruntimeResolveSpecialMethodBlock)RESOLVE(CVMCCMruntimeResolveMethodBlock)RESOLVE(CVMCCMruntimeResolveMethodTableOffset)#undef RTARGET#undef SCRATCH /* CVMCCMruntimeRunClassInitializerGlue */ENTRY(CVMCCMruntimeRunClassInitializerGlue ) # A3 = target cb#define SCRATCH A1 CALL_HELPER_3_NO_RET(SCRATCH, CCEE_AS_ARG, EE_AS_ARG, AS_ARG(A3), SYM_NAME(CVMCCMruntimeRunClassInitializer)) /* At this point we know that either class initialization is * not needed (result is TRUE), or is being done by the * current thread. For the later we just return. */ cmp $0, %eax jne CVMCCMruntimeRunClassInitializerGlue_L1 ret CVMCCMruntimeRunClassInitializerGlue_L1: /* At this point we know the class has been intialized. Patch the * the call to this helper to be a nop. * WARNING: Don't attempt to patch over the ldr of the cb with * a branch around the call to the helper. The ldr may be the * first instruction of a block, which means we may also try to * patch it when doing a gc-rendezvous. */ pushl %esi # callee saved movl 4(%esp), %esi # addr of call subl $5, %esi # call is 5 bytes long movl 0(%esi), %eax # load call movl 4(%esi), %edx # load call movl $0x90909090, %ebx # 4 nops movl %edx, %ecx movb $0x90, %cl # 5th nop CVMJITX86_CMPXCHG8B(0(%esi)) popl %esi ret #if 0 /* no necessary on x86 */ CALL_HELPER_2(SCRATCH, AS_ARG(A1), AS_ARG(A2), CVMJITflushCache)#endif#undef SCRATCH SET_SIZE( CVMCCMruntimeRunClassInitializerGlue )/* CVMCCMruntimeLookupInterfaceMBGlue */ENTRY(CVMCCMruntimeLookupInterfaceMBGlue ) # A2 = object to invoke with # A3 = interface mb # 0(%esp) = address of guess from last interface mb lookup#if 0 /* SVMC_JIT d022609 2003-09-19T. temporarily enable runtime call until problem with `CONSTANT_LOG2_CVMInterfaceTable_SIZE' is solved. */ # # If you just want to call the C helper and write very little # assembler code: # movl OFFSET_CVMObjectHeader_clas(A2), A2 andl $(~3), A2 movl 0(%esp), A4 addl $4, 0(%esp) # == instruction after guess cb#define SCRATCH A1 FIXUP_FRAMES_2(JFP, SCRATCH, A2, A3, CVMCCMruntimeLookupInterfaceMBGlue_L1)CVMCCMruntimeLookupInterfaceMBGlue_L1: CALL_HELPER_4(SCRATCH, CCEE_AS_ARG, AS_ARG(A2), AS_ARG(A3), AS_ARG(A4), SYM_NAME(CVMCCMruntimeLookupInterfaceMB))#undef SCRATCH#else /* #if 1 */ # # Following is the fast version of CVMCCMruntimeLookupInterfaceMBGlue, # which only calls to C helper when the guess is wrong. ##define OCB A2#define INTERFACE_MB A3#define GUESS %esi#define GUESSw %si#define OINTERFACES %edi/* * | 4. word (free) <- 16 + OFFSET_CVMCCExecEnv_ccmStorage(%esp) * +--------------- * | 3. word (free) <- 12 + OFFSET_CVMCCExecEnv_ccmStorage(%esp) * +--------------- * | 2. %edi (JSP) <- 8 + OFFSET_CVMCCExecEnv_ccmStorage(%esp) * +--------------- * | 1. %esi <- 4 + OFFSET_CVMCCExecEnv_ccmStorage(%esp) * +--------------- * : * | 1. ret addr. <- 0(%esp) * +--------------- */ # saving callee saved registers (see CVMCPU_NON_VOLATILE_SET) movl %esi, 4 + OFFSET_CVMCCExecEnv_ccmStorage(%esp) movl %edi, 8 + OFFSET_CVMCCExecEnv_ccmStorage(%esp) # %edi is JSP /* ocb = CVMobjectGetClass(obj); */ movl OFFSET_CVMObjectHeader_clas(A2), OCB # get ocb from obj andl $~3, OCB # ocb &= ~0x3; prepare ocb /* interfaces = ocb->interfacesX */ movl OFFSET_CVMClassBlock_interfacesX(OCB), OINTERFACES cmpl $0, OINTERFACES # Check if ocb->interfacesX == NULL. je call_lookup_helper movl 0(%esp), GUESS movl 0(GUESS), GUESS # load guess value /* cmp guess and ocb->interfacesX->interfaceCountX */ cmpw OFFSET_CVMInterfaces_interfaceCountX(OINTERFACES), GUESSw jae call_lookup_helper # if guess >= ointerfaceCount, invalid /* If we get here then the guess is within the valid range: */ /* shll $CONSTANT_LOG2_CVMInterfaceTable_SIZE, GUESS */ shll $3, GUESS /* target ICB = &ointerfaces.itable[guess] */ movl OFFSET_CVMInterfaces_itable(OINTERFACES, GUESS), A4#ifdef CVM_METHODBLOCK_HAS_CB /* A1 = source ICB */ movl OFFSET_CVMMethodBlock_cbX(INTERFACE_MB), A1 # get icb#else#ifdef OFFSET_CVMMethodBlock_cbX#error OFFSET_CVMMethodBlock_cbX defined but not CVM_METHODBLOCK_HAS_CB#endif movzbl OFFSET_CVMMethodBlock_methodIndexX(INTERFACE_MB), A1#if IMPLEMENTED_STACKMAP_CACHE_AND_REDUCED_MB_SIZE_FURTHER#error ported this from sparc and wonder how this should ever work (rr). /* FIXME: When method size is 28 fix appropriately */ # Here's a way to do r0 = 20r0 # First set r0 = r0 << 4 (16r0) # Now add a quarter of that value to itself: r0 = r0 + r0 / 4 # r0 = 32 * r0 shll $4, A1 /* FIXME: When method size is 28, just subtract 1/8 of 32*r0 to get 28*r0 */ # r0 = r0 + r0 / 4#define SCRATCH %edi movl A1, SCRATCH shrl $2, SCRATCH addl SCRATCH, A1#undef scratch#endif#if (CONSTANT_CVMMethodBlock_size == 28) # A1 = CONSTANT_CVMMethodBlock_size * A1 imull $CONSTANT_CVMMethodBlock_size, A1#else #error Wrong CVMMethodBlock size, not tested yet#endif negl A1 addl INTERFACE_MB, A1 movl -OFFSET_CVMMethodRange_mb(A1), A1#endif /* Check if the guess' interface CB is the one we want: */ cmpl A4, A1 # test if target ICB == source ICB jne call_lookup_helper # go call helper if guess failed. /* If we get here, then the guess is correct. Go fetch the method block from the interface CB: */#define TARGET_METHODTABLE_INDICES %edi /* Target methodTableIndices = ocb->interfacesX.itable[guess].methodTableIndicesX; */ movl OFFSET_CVMInterfaces_itable0_intfInfoX(OINTERFACES, GUESS), TARGET_METHODTABLE_INDICES#undef GUESS#undef OINTERFACES#define SOURCE_MB_IDX A4 /* get source mb MethodSlotIndex */ movl OFFSET_CVMMethodBlock_codeX(INTERFACE_MB), SOURCE_MB_IDX /* Get the interface mb from the ocb's vtbl: */ movl OFFSET_CVMClassBlock_methodTablePtrX(OCB), A1 /* shll $CONSTANT_LOG2_CVMInterfaceTable_methodTableIndex_SIZE, A4 */ shll $1, A4 movzwl 0(TARGET_METHODTABLE_INDICES, A4), TARGET_METHODTABLE_INDICES#undef SOURCE_MB_IDX /* A1 = ocb->methodTablePtrX[ip]: */ movl 0(A1, TARGET_METHODTABLE_INDICES, 4), A1 addl $4, 0(%esp) # == instruction after guess cb movl 4 + OFFSET_CVMCCExecEnv_ccmStorage(%esp), %esi movl 8 + OFFSET_CVMCCExecEnv_ccmStorage(%esp), %edi ret call_lookup_helper: movl 4 + OFFSET_CVMCCExecEnv_ccmStorage(%esp), %esi movl 8 + OFFSET_CVMCCExecEnv_ccmStorage(%esp), %edi movl 0(%esp), A4 addl $4, 0(%esp) # == instruction after guess cb#define SCRATCH A1 FIXUP_FRAMES_2(JFP, SCRATCH, A2, A3, CVMCCMruntimeLookupInterfaceMBGlue_L1)CVMCCMruntimeLookupInterfaceMBGlue_L1: CALL_HELPER_4(SCRATCH, CCEE_AS_ARG, AS_ARG(A2), AS_ARG(A3), AS_ARG(A4), SYM_NAME(CVMCCMruntimeLookupInterfaceMB))#undef SCRATCH #undef OCB#undef INTERFACE_MB#undef COUNT#endif /* 0 */SET_SIZE( CVMCCMruntimeLookupInterfaceMBGlue )/* CVMCCMruntimeThrowObjectGlue */ENTRY(CVMCCMruntimeThrowObjectGlue ) # A3 = CVMObject#define SCRATCH A1 FIXUP_FRAMES_1(JFP, SCRATCH, A3, CVMCCMruntimeThrowObjectGlue_L1)CVMCCMruntimeThrowObjectGlue_L1: CALL_HELPER_3(SCRATCH, CCEE_AS_ARG, EE_AS_ARG, AS_ARG(A3), SYM_NAME(CVMCCMruntimeThrowObject))
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?