📄 ccmglue_cpu.s
字号:
cmp lr, a2 bhs doPatch ldr a2, SYMBOL(CVMJITcodeCacheAOTStart) ldr a2, [a2] ldr a2, [a2] cmp lr, a2 movhs pc, lr#endifLABEL(doPatch) ldr a2, CONSTANT(0xe1a00000)/* get the patch, a nop instruction */ str a2, [lr, #-4] /* apply the patch */ /* flush the patched instruction */ sub a1, lr, #4 /* begin */ add a2, a1, #4 /* end */ CALL_VM_FUNCTION(CVMflushCache) /* return to the helper */ ldr pc, [JFP, #OFFSET_CVMCompiledFrame_PC] /* * Resolve a cp entry and run the clinit if necessary */ ENTRY(CVMCCMruntimeResolveGlue)ENTRY1 ( CVMCCMruntimeResolveGlue )LABEL(CVMCCMruntimeResolveGlueLocal) /* a3 = cpIndex * lr = address of cachedConstant, 4 bytes before returnAddress * ip = address of ccm helper to call * setup remaining arguments and call the helper */ mov a1, sp /* a1 = ccee */ ldr a2, [sp, #OFFSET_CVMCCExecEnv_ee] /* a2 = ee */ mov a4, lr /* a4 = address of cachedConstant */ /* flush state */ str JSP, [JFP, #OFFSET_CVMFrame_topOfStack] add lr, lr, #4 /* lr = address we want to return to */ str lr, [JFP, #OFFSET_CVMCompiledFrame_PC] str JFP, [a2, #OFFSET_CVMExecEnv_interpreterStack+OFFSET_CVMStack_currentFrame] /* call the helper */ mov lr, pc mov pc, ip /* reload the return address */ ldr lr, [JFP, #OFFSET_CVMCompiledFrame_PC] /* At this point we know that the either class initialization is * not needed (result is TRUE), or is being done by the * current thread. For the later we just return. */ cmp a1, #0 /* FALSE means current thread is running clinit */ moveq pc, lr /* At this point we know that any needed class initialization has * been done. Patch the first instruction of the generated code * to branch around the call to this helper, and also around * the cachedConstant word. */#ifdef CVM_JIT_COPY_CCMCODE_TO_CODECACHE#define RESOLVE_PATCH_OFFSET 16#else#define RESOLVE_PATCH_OFFSET 20#endif ldr a2, L_MAKEBRANCH_1 /* get the patch */ add lr, lr, #4 str a2, [lr, #-RESOLVE_PATCH_OFFSET] /* apply the patch */ /* flush the patched instruction */ sub a1, lr, #RESOLVE_PATCH_OFFSET /* begin */ add a2, a1, #4 /* end */ CALL_VM_FUNCTION(CVMflushCache) /* return to compiled code */ ldr pc, [JFP, #OFFSET_CVMCompiledFrame_PC]LABEL(L_MAKEBRANCH_1) WORD(MAKE_BRANCH(RESOLVE_PATCH_OFFSET)) ENTRY(CVMCCMruntimeResolveNewClassBlockAndClinitGlue)ENTRY1(CVMCCMruntimeResolveNewClassBlockAndClinitGlue) IMPORT(CVMCCMruntimeResolveNewClassBlockAndClinit) ldr ip, SYMBOL(CVMCCMruntimeResolveNewClassBlockAndClinit) b CVMCCMruntimeResolveGlueLocal SET_SIZE(CVMCCMruntimeResolveNewClassBlockAndClinitGlue) ENTRY(CVMCCMruntimeResolveGetstaticFieldBlockAndClinitGlue)ENTRY1(CVMCCMruntimeResolveGetstaticFieldBlockAndClinitGlue) IMPORT(CVMCCMruntimeResolveGetstaticFieldBlockAndClinit) ldr ip, SYMBOL(CVMCCMruntimeResolveGetstaticFieldBlockAndClinit) b CVMCCMruntimeResolveGlueLocal SET_SIZE(CVMCCMruntimeResolveGetstaticFieldBlockAndClinitGlue) ENTRY(CVMCCMruntimeResolvePutstaticFieldBlockAndClinitGlue)ENTRY1(CVMCCMruntimeResolvePutstaticFieldBlockAndClinitGlue) IMPORT(CVMCCMruntimeResolvePutstaticFieldBlockAndClinit) ldr ip, SYMBOL(CVMCCMruntimeResolvePutstaticFieldBlockAndClinit) b CVMCCMruntimeResolveGlueLocal SET_SIZE(CVMCCMruntimeResolvePutstaticFieldBlockAndClinitGlue) ENTRY(CVMCCMruntimeResolveStaticMethodBlockAndClinitGlue)ENTRY1(CVMCCMruntimeResolveStaticMethodBlockAndClinitGlue) IMPORT(CVMCCMruntimeResolveStaticMethodBlockAndClinit) ldr ip, SYMBOL(CVMCCMruntimeResolveStaticMethodBlockAndClinit) b CVMCCMruntimeResolveGlueLocal SET_SIZE(CVMCCMruntimeResolveStaticMethodBlockAndClinitGlue) ENTRY(CVMCCMruntimeResolveClassBlockGlue)ENTRY1(CVMCCMruntimeResolveClassBlockGlue) IMPORT(CVMCCMruntimeResolveClassBlock) ldr ip, SYMBOL(CVMCCMruntimeResolveClassBlock) b CVMCCMruntimeResolveGlueLocal SET_SIZE(CVMCCMruntimeResolveClassBlockGlue) ENTRY(CVMCCMruntimeResolveArrayClassBlockGlue)ENTRY1(CVMCCMruntimeResolveArrayClassBlockGlue) IMPORT(CVMCCMruntimeResolveArrayClassBlock) ldr ip, SYMBOL(CVMCCMruntimeResolveArrayClassBlock) b CVMCCMruntimeResolveGlueLocal SET_SIZE(CVMCCMruntimeResolveArrayClassBlockGlue) ENTRY(CVMCCMruntimeResolveGetfieldFieldOffsetGlue)ENTRY1(CVMCCMruntimeResolveGetfieldFieldOffsetGlue) IMPORT(CVMCCMruntimeResolveGetfieldFieldOffset) ldr ip, SYMBOL(CVMCCMruntimeResolveGetfieldFieldOffset) b CVMCCMruntimeResolveGlueLocal SET_SIZE(CVMCCMruntimeResolveGetfieldFieldOffsetGlue) ENTRY(CVMCCMruntimeResolvePutfieldFieldOffsetGlue)ENTRY1(CVMCCMruntimeResolvePutfieldFieldOffsetGlue) IMPORT(CVMCCMruntimeResolvePutfieldFieldOffset) ldr ip, SYMBOL(CVMCCMruntimeResolvePutfieldFieldOffset) b CVMCCMruntimeResolveGlueLocal SET_SIZE(CVMCCMruntimeResolvePutfieldFieldOffsetGlue) ENTRY(CVMCCMruntimeResolveSpecialMethodBlockGlue)ENTRY1(CVMCCMruntimeResolveSpecialMethodBlockGlue) IMPORT(CVMCCMruntimeResolveSpecialMethodBlock) ldr ip, SYMBOL(CVMCCMruntimeResolveSpecialMethodBlock) b CVMCCMruntimeResolveGlueLocal SET_SIZE(CVMCCMruntimeResolveSpecialMethodBlockGlue) ENTRY(CVMCCMruntimeResolveMethodBlockGlue)ENTRY1(CVMCCMruntimeResolveMethodBlockGlue) IMPORT(CVMCCMruntimeResolveMethodBlock) ldr ip, SYMBOL(CVMCCMruntimeResolveMethodBlock) b CVMCCMruntimeResolveGlueLocal SET_SIZE(CVMCCMruntimeResolveMethodBlockGlue)/* * Resolve a vtable offset. The protocol here is slight * different because the result could possibly be an MB pointer * rather than just an offset. Calling code looks like this: * ld destreg,cache * mov ARG1, cpIndex * call CVMCCMruntimeResolveMethodTableOffsetGlue * mov mbDestreg,RETURN1 * b haveMB * cache: * .word -1 * return1: * ld destreg, cache * * If the helper returns 0, then the cache will have been filled with * the vtable offset and we go let the general resolver glue code * do the rewrite and return. * Otherwise, the helper returned the MB pointer and we return that * directly. */ ENTRY(CVMCCMruntimeResolveMethodTableOffsetGlue)ENTRY1 ( CVMCCMruntimeResolveMethodTableOffsetGlue ) IMPORT(CVMCCMruntimeResolveMethodTableOffset) /* a3 = cpIndex */ /* lr = address of instruction following call */ ldr ip, SYMBOL(CVMCCMruntimeResolveMethodTableOffset) /* setup remaining arguments and call the helper */ mov a1, sp /* a1 = ccee */ ldr a2, [sp, #OFFSET_CVMCCExecEnv_ee] /* a2 = ee */ add a4, lr, #8 /* a4 = address of cachedConstant */ /* flush state */ str JSP, [JFP, #OFFSET_CVMFrame_topOfStack] add lr, a4, #4 /* lr = address we want to return to normally */ str JFP, [a2, #OFFSET_CVMExecEnv_interpreterStack+OFFSET_CVMStack_currentFrame] str lr, [JFP, #OFFSET_CVMCompiledFrame_PC] /* call the helper */ mov lr, pc mov pc, ip /* reload the return address */ ldr lr, [JFP, #OFFSET_CVMCompiledFrame_PC] cmp a1, #0 /* 0 means cache contains vtbl address */ /* will return value already in a1 at point just after call */ subne pc, lr, #12 /* At this point we know that the method table offset has been * written to the cache word. * Patch the first instruction of the generated code * to branch around the call to this helper, around the special * case return code, and around the cachedConstant word. */#define RESOLVE_METHOD_TABLE_PATCH_OFFSET (RESOLVE_PATCH_OFFSET+8) ldr a2, L_MAKEBRANCH_2 add lr, lr, #4 str a2, [lr, #-RESOLVE_METHOD_TABLE_PATCH_OFFSET] /* flush the patched instruction */ sub a1, lr, #RESOLVE_METHOD_TABLE_PATCH_OFFSET /* begin */ add a2, a1, #4 /* end */ CALL_VM_FUNCTION(CVMflushCache) /* return to compiled code */ ldr pc, [JFP, #OFFSET_CVMCompiledFrame_PC]LABEL(L_MAKEBRANCH_2) WORD(MAKE_BRANCH(RESOLVE_METHOD_TABLE_PATCH_OFFSET)) /* lookup an interface mb */ ENTRY(CVMCCMruntimeLookupInterfaceMBGlue)ENTRY1 ( CVMCCMruntimeLookupInterfaceMBGlue ) /* r1 = object to invoke with * r2 = interface mb * lr = address of guess from last interface mb lookup */ add lr, lr, #4 /* skip pass the guess addr to the return addr */#define OCB r1#define INTERFACE_MB r2#define OINTERFACES ip /* ocb = CVMobjectGetClass(obj); */ ldr OCB, [r1, #OFFSET_CVMObjectHeader_clas] /* get ocb from obj */ bic OCB, OCB, #3 /* ocb &= ~0x3; prepare ocb */ /* interfaces = ocb->interfacesX */ ldr OINTERFACES, [r1, #OFFSET_CVMClassBlock_interfacesX] cmp OINTERFACES, #0 /* Check if ocb->interfacesX == NULL. */ beq call_lookup_helper /* ointerfaceCount = ocb->interfacesX->interfaceCountX; */ ldrh r3, [OINTERFACES, #OFFSET_CVMInterfaces_interfaceCountX]#define GUESS r0 ldr GUESS, [lr, #-4] /* load guess value */ cmp GUESS, r3 /* cmp guess and ointerfaceCount */ bcs call_lookup_helper /* if guess >= ointerfaceCount, invalid */ /* If we get here than the guess is within the valid range: */ add r3, OINTERFACES, #OFFSET_CVMInterfaces_itable mov GUESS, GUESS, asl #CONSTANT_LOG2_CVMInterfaceTable_SIZE ldr r3, [r3, GUESS] /* target ICB = &ointerfaces.itable[guess] */ /* Free up the GUESS reg (r0) for use below. Save its content first: */ str GUESS, [sp, #OFFSET_CVMCCExecEnv_ccmStorage+0]#undef GUESS#ifdef CVM_METHODBLOCK_HAS_CB ldr r0, [INTERFACE_MB, #OFFSET_CVMMethodBlock_cbX] /* get icb */#else#if CONSTANT_CVMMethodBlock_size != 28#error Wrong CVMMethodBlock size#endif#ifdef OFFSET_CVMMethodBlock_cbX#error OFFSET_CVMMethodBlock_cbX defined but not CVM_METHODBLOCK_HAS_CB#endif ldrb r0, [INTERFACE_MB, #OFFSET_CVMMethodBlock_methodIndexX] /* Here is a way to do r0 = r0 * 28 * r0 = r0 * 32 * r0 = r0 - r0 / 8 */ mov r0, r0, asl #5 sub r0, r0, r0, asr #3 sub r0, INTERFACE_MB, r0 ldr r0, [r0, #-OFFSET_CVMMethodRange_mb]#endif /* Check if the guess' interface CB is the one we want: */ cmp r3, r0 /* test if target ICB == source ICB */ bne 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 SOURCE_MB_IDX r3 /* get source mb MethodSlotIndex */ ldr SOURCE_MB_IDX, [INTERFACE_MB, #OFFSET_CVMMethodBlock_codeX]#define TARGET_METHODTABLE_INDICES ip#define GUESS r0 /* Reload the GUESS reg (r0) content from earlier: */ ldr GUESS, [sp, #OFFSET_CVMCCExecEnv_ccmStorage+0] /* Target methodTableIndices = ocb->interfacesX.itable[guess].methodTableIndicesX; */ add ip, OINTERFACES, #OFFSET_CVMInterfaces_itable0_intfInfoX ldr TARGET_METHODTABLE_INDICES, [ip, GUESS]#undef GUESS#undef OINTERFACES /* Get the interface mb from the ocb's vtbl: */ ldr r0, [OCB, #OFFSET_CVMClassBlock_methodTablePtrX] mov r3, SOURCE_MB_IDX, \ asl #CONSTANT_LOG2_CVMInterfaceTable_methodTableIndex_SIZE ldrh ip, [TARGET_METHODTABLE_INDICES, r3] /* r0 = ocb->methodTablePtrX[ip]: */ ldr r0, [r0, ip, asl #2] mov pc, lrLABEL(call_lookup_helper) sub a4, lr, #4 /* load guessCb adderess */ /* r1 = a2 = ocb * r2 = a3 = imb * r3 = a4 = guess address */#define SAVESET {a2, a3, lr} FIXUP_FRAMES(JFP, SAVESET, 3)#undef SAVESET CALL_HELPER_AND_PASS_CACHE_ADDR(CVMCCMruntimeLookupInterfaceMB)#undef OCB#undef TARGET_METHODTABLE_INDICES/* support for fastlocking with C sync helpers */#if defined(CVM_JIT_CCM_USE_C_HELPER) || defined(CVM_JIT_CCM_USE_C_SYNC_HELPER)/* * Entry point for monitorenter. */ ENTRY(CVMCCMruntimeMonitorEnterGlue)ENTRY1 ( CVMCCMruntimeMonitorEnterGlue ) /* Arguments: * r2 = a3 = 'obj' * * Also incoming: * r4 = v1 = jfp * r5 = v2 = jsp * sp = ccee */ CALL_HELPER_AND_PASS_EE(CVMCCMruntimeMonitorEnter)/* * Entry point for monitorexit. */ ENTRY(CVMCCMruntimeMonitorExitGlue)ENTRY1 ( CVMCCMruntimeMonitorExitGlue ) /* Arguments: * r2 = a3 = 'obj' * * Also incoming: * r4 = v1 = jfp * r5 = v2 = jsp * sp = ccee */ CALL_HELPER_AND_PASS_EE(CVMCCMruntimeMonitorExit)/* Support for fastlocking with swap/spinlock based microlocks */#elif CVM_FASTLOCK_TYPE == CVM_FASTLOCK_MICROLOCK && \ CVM_MICROLOCK_TYPE == CVM_MICROLOCK_SWAP_SPINLOCK/* * Entry point for monitorenter. */ ENTRY(CVMCCMruntimeMonitorEnterGlue)ENTRY1 ( CVMCCMruntimeMonitorEnterGlue ) /* Arguments: * r2 = a3 = 'obj' * * Also incoming: * r4 = v1 = jfp * r5 = v2 = jsp * sp = ccee */ /* Do fastTryLock(): */ /* r0 = µlock r1 = ee r2 = obj, scratch r3 = obits, scratch
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -