📄 ccmglue_cpu.s
字号:
r4 = v1 = JFP r5 = v2 = JSP r12 = lockrec */#define EE r1#define OBJ r2#define OBITS r3#define MICROLOCK r0#define LOCKREC r12/* IAI-04 */ /* W_MICROLOCK = address of microlock */#ifdef IAI_CACHE_GLOBAL_VARIABLES_IN_WMMX /* Get address of microlock from wmmx register */ textrmuw MICROLOCK, W_MICROLOCK, #0 cmp OBJ, #0#else ldr MICROLOCK, SYMBOL(CVMobjGlobalMicroLockPtr) /* Make sure that the object is not NULL: */ cmp OBJ, #0 /* Get address of object microlock */ ldr MICROLOCK, [MICROLOCK] #endif beq SYM_NAME(CVMCCMruntimeThrowNullPointerExceptionGlue) ldr r3, [MICROLOCK] /* Acquire the microlock: */ mov r3, #CVM_MICROLOCK_LOCKED /* Swap CVM_MICROLOCK_LOCKED into */#ifndef CVM_MP_SAFE swp r3, r3, [MICROLOCK] /* the lockWord. */ cmp r3, #CVM_MICROLOCK_UNLOCKED /* See if we succeeded. */ bne _monenterSlowAcquireMicrolock /* Branch if failed. */#elseLABEL(_monenterAcquireMicrolockMPSafe) ldrex r12, [MICROLOCK] cmp r12, #CVM_MICROLOCK_UNLOCKED /* is the lock free? */ bne _monenterSlowAcquireMicrolock /* No. Go slow */ strex r12, r3, [MICROLOCK] /* try acquire the lock */ cmp r12, #0 /* strex succeed? */ bne _monenterAcquireMicrolockMPSafe /* if strex failed, try again */ mcr p15, 0, r12, c7, c10, 5 /* memory barrier. r12 has 0. */#endif /* The microlock has been acquired: */LABEL(_monenterLockObj) ldr OBITS, [OBJ, #OFFSET_CVMObjectHeader_various32] /* Get obits. */ ldr EE, [sp, #OFFSET_CVMCCExecEnv_ee] and r12, OBITS, #0x3 cmp r12, #CONSTANT_CVM_LOCKSTATE_UNLOCKED bne _monenterObjAlreadyLocked /* If we get here, then the object has not been locked yet. */ /* lockrec = ee->objLocksFreeOwned: */ ldr LOCKREC, [EE, #OFFSET_CVMExecEnv_objLocksFreeOwned] cmp LOCKREC, #0 beq _monenterRecordNotAvailable /* lockrec->u.fast.bits = obits: */ str OBITS, [LOCKREC, #OFFSET_CVMOwnedMonitor_u_fast_bits] /* Now, r3 (i.e. OBITS) is free. */#ifdef CVM_DEBUG /* lockrec->state = CONSTANT_CVM_OWNEDMON_OWNED: */ mov r3, #CONSTANT_CVM_OWNEDMON_OWNED str r3, [LOCKREC, #OFFSET_CVMOwnedMonitor_state]#endif /* obj->hdr.various32 = lockrec: */ str LOCKREC, [OBJ, #OFFSET_CVMObjectHeader_various32] /* lockrec->count = 1: */ mov r3, #1 /* Initial lock re-entry count. */ str r3, [LOCKREC, #OFFSET_CVMOwnedMonitor_count] /* lockrec->object = obj: */ str OBJ, [LOCKREC, #OFFSET_CVMOwnedMonitor_object] /* Now, r2 (i.e OBJ) is free. */ #ifdef CVM_MP_SAFE mov r3, #0 mcr p15, 0, r3, c7, c10, 5 /* memory barrier. */#endif /* Release the microlock: */ mov r3, #CVM_MICROLOCK_UNLOCKED str r3, [MICROLOCK] /* microlock->lockWord = UNLOCKED. */ /* Remove lockrec from the ee's free list: */ /* nextRec = lockrec->next: */ ldr r2, [LOCKREC, #OFFSET_CVMOwnedMonitor_next] /* ee->objLocksFreeOwned = nextRec: */ str r2, [EE, #OFFSET_CVMExecEnv_objLocksFreeOwned] /* Add the lockrec to the ee's owned list: */ /* nextRec = ee->objLocksOwned: */ ldr r2, [EE, #OFFSET_CVMExecEnv_objLocksOwned] /* lockrec->next = nextRec: */ str r2, [LOCKREC, #OFFSET_CVMOwnedMonitor_next] /* ee->objLocksOwned = lockrec: */ str LOCKREC, [EE, #OFFSET_CVMExecEnv_objLocksOwned] mov pc, lr /* Return to the caller. */LABEL(_monenterSlowAcquireMicrolock) /* Call a C function to acquire the microlock: NOTE: We have to save OBJ below because it is in a volatile reg. However, it is safe to simply save it in a ccmStorage field without worrying about GC scans because we are currently GC unsafe and won't be becoming GC safe while acquiring the microlock. */ str MICROLOCK, [sp, #OFFSET_CVMCCExecEnv_ccmStorage+0] str OBJ, [sp, #OFFSET_CVMCCExecEnv_ccmStorage+4] str lr, [sp, #OFFSET_CVMCCExecEnv_ccmStorage+8] CALL_VM_FUNCTION(CVMmicrolockLockImpl) ldr MICROLOCK, [sp, #OFFSET_CVMCCExecEnv_ccmStorage+0] ldr OBJ, [sp, #OFFSET_CVMCCExecEnv_ccmStorage+4] ldr lr, [sp, #OFFSET_CVMCCExecEnv_ccmStorage+8] b _monenterLockObjLABEL(_monenterObjAlreadyLocked) cmp r12, #CONSTANT_CVM_LOCKSTATE_LOCKED bne _monenterFastReentryFailed /* Make sure the current thread owns this lock: */ ldr r12, [OBITS, #OFFSET_CVMOwnedMonitor_owner] cmp r12, EE bne _monenterFastReentryFailed ldr r12, [OBITS, #OFFSET_CVMOwnedMonitor_count] add r12, r12, #1 str r12, [OBITS, #OFFSET_CVMOwnedMonitor_count] /* Release the microlock: */ mov r3, #CVM_MICROLOCK_UNLOCKED str r3, [MICROLOCK] /* microlock->lockWord = UNLOCKED. */ mov pc, lr /* Return to the caller. */LABEL(_monenterFastReentryFailed)LABEL(_monenterRecordNotAvailable) /* Release the microlock: */ mov r3, #CVM_MICROLOCK_UNLOCKED str r3, [MICROLOCK] /* Load the ccee. The ee, and obj are already loaded. */ mov r0, sp str lr, [JFP, #OFFSET_CVMCompiledFrame_PC] str JFP, [a2, #OFFSET_CVMExecEnv_interpreterStack+OFFSET_CVMStack_currentFrame] BRANCH_TO_VM_FUNCTION(CVMCCMruntimeMonitorEnter)#undef EE#undef OBJ#undef OBITS#undef MICROLOCK#undef LOCKREC/* * Entry point for monitorexit. */ ENTRY(CVMCCMruntimeMonitorExitGlue)ENTRY1 ( CVMCCMruntimeMonitorExitGlue ) /* Arguments: * r2 = a3 = 'obj' * * Also incoming: * r4 = v1 = jfp * r5 = v2 = jsp * sp = ccee */ /* Do fastTryUnlock(): */ /* r0 = a1 = µlock r1 = a2 = ee r2 = a3 = obj, scratch r3 = a4 = scratch r4 = v1 = JFP r5 = v2 = JSP r12 = lockrec */#define EE r1#define OBJ r2#define MICROLOCK r0#define LOCKREC r12/* IAI-04 */ /* W_MICROLOCK = address of microlock */#ifdef IAI_CACHE_GLOBAL_VARIABLES_IN_WMMX textrmuw MICROLOCK, W_MICROLOCK, #0 cmp OBJ, #0#else ldr MICROLOCK, SYMBOL(CVMobjGlobalMicroLockPtr) /* Make sure that the object is not NULL: */ cmp OBJ, #0 /* Get address of object microlock */ ldr MICROLOCK, [MICROLOCK]#endif beq SYM_NAME(CVMCCMruntimeThrowNullPointerExceptionGlue) ldr r3, [MICROLOCK]LABEL(_monexitAcquireMicrolock) mov r3, #CVM_MICROLOCK_LOCKED /* Swap CVM_MICROLOCK_LOCKED into */#ifndef CVM_MP_SAFE swp r3, r3, [MICROLOCK] /* the lockWord. */ cmp r3, #CVM_MICROLOCK_UNLOCKED /* See if we succeeded. */ bne _monexitSlowAcquireMicrolock /* Branch if failed. */#elseLABEL(_monexitAcquireMicrolockMPSafe) ldrex r12, [MICROLOCK] cmp r12, #CVM_MICROLOCK_UNLOCKED /* is the lock free? */ bne _monexitSlowAcquireMicrolock /* No. Go slow */ strex r12, r3, [MICROLOCK] /* acquire the lock */ cmp r12, #0 /* strex succeed? */ bne _monexitAcquireMicrolockMPSafe /* if strex failed, try again */ mcr p15, 0, r12, c7, c10, 5 /* memory barrier. r12 has 0 */#endif /* The microlock has been acquired: */LABEL(_monexitUnlockObj) /* Check to see if the object is locked with a fastlock: */ ldr LOCKREC, [OBJ, #OFFSET_CVMObjectHeader_various32] /* Get obits.*/ ldr EE, [sp, #OFFSET_CVMCCExecEnv_ee] tst LOCKREC, #0x3 /* (obits & 0x3) == CVM_LOCKSTATE_LOCKED? */ bne _monexitFastTryUnlockFailed /* If not, we failed. */ /* If we get here, then the object is locked with a fastlock: */ /* Make sure that the current thread owns the monitor: */ ldr r3, [LOCKREC, #OFFSET_CVMOwnedMonitor_owner] cmp r3, EE bne _monexitFastTryUnlockFailed /* If not, we failed. */ /* If we get here, then the current thread does own the monitor, and all is well. Proceed with unlocking: */ ldr r3, [LOCKREC, #OFFSET_CVMOwnedMonitor_count] subs r3, r3, #1 bne _monexitFastTryUnlockSuccess /* If not zero, we are done. */ /* If we get here, then the re-entry count has reached 0. */ /* Restore the obits to the object header: */ ldr r3, [LOCKREC, #OFFSET_CVMOwnedMonitor_u_fast_bits] str r3, [OBJ, #OFFSET_CVMObjectHeader_various32]#ifdef CVM_DEBUG /* Make the lockrec play nice with the debug assertions: */ mov r3, #CONSTANT_CVM_OWNEDMON_FREE str r3, [LOCKREC, #OFFSET_CVMOwnedMonitor_state] mov r3, #0 str r3, [LOCKREC, #OFFSET_CVMOwnedMonitor_u_fast_bits] str r3, [LOCKREC, #OFFSET_CVMOwnedMonitor_object] str r3, [LOCKREC, #OFFSET_CVMOwnedMonitor_count]#endif#ifdef CVM_MP_SAFE mov r3, #0 mcr p15, 0, r3, c7, c10, 5 /* memory barrier. */#endif /* Release the microlock: */ mov r3, #CVM_MICROLOCK_UNLOCKED str r3, [MICROLOCK] /* Now, r2 (i.e. OBJ) is free. */ /* Check if the lockrec is the first one on the thread's owned list: */ ldr r3, [EE, #OFFSET_CVMExecEnv_objLocksOwned] cmp r3, LOCKREC bne _monexitFastTryUnlockFindPrevLockRecord /* Remove the lockrec from the ee's owned list: */ ldr r3, [LOCKREC, #OFFSET_CVMOwnedMonitor_next] str r3, [EE, #OFFSET_CVMExecEnv_objLocksOwned]LABEL(_monexitFastTryUnlockAddLockRecordToFreeList) /* Add the lockrec to the ee's free list: */ ldr r3, [EE, #OFFSET_CVMExecEnv_objLocksFreeOwned] str r3, [LOCKREC, #OFFSET_CVMOwnedMonitor_next] str LOCKREC, [EE, #OFFSET_CVMExecEnv_objLocksFreeOwned] mov pc, lr /* Return to the caller. */#define PREV_REC r3LABEL(_monexitFastTryUnlockFindPrevLockRecord) ldr r2, [PREV_REC, #OFFSET_CVMOwnedMonitor_next] cmp r2, LOCKREC beq _monexitFastTryUnlockFoundPrevLockRecord mov PREV_REC, r2 b _monexitFastTryUnlockFindPrevLockRecordLABEL(_monexitFastTryUnlockFoundPrevLockRecord) /* Remove the lockrec from the ee's owned list: */ ldr r2, [LOCKREC, #OFFSET_CVMOwnedMonitor_next] str r2, [PREV_REC, #OFFSET_CVMOwnedMonitor_next] b _monexitFastTryUnlockAddLockRecordToFreeList#undef PREV_RECLABEL(_monexitFastTryUnlockSuccess) /* Set the new re-entry count: */ str r3, [LOCKREC, #OFFSET_CVMOwnedMonitor_count] /* Release the microlock: */ mov r3, #CVM_MICROLOCK_UNLOCKED str r3, [MICROLOCK] mov pc, lr /* Return to the caller. */LABEL(_monexitSlowAcquireMicrolock) /* Call a C function to acquire the microlock: NOTE: We have to save OBJ below because it is in a volatile reg. However, it is safe to simply save it in a non-volatile reg without worrying about GC scans because we are currently GC unsafe and won't be becoming GC safe while acquiring the microlock. */ str MICROLOCK, [sp, #OFFSET_CVMCCExecEnv_ccmStorage+0] str OBJ, [sp, #OFFSET_CVMCCExecEnv_ccmStorage+4] str lr, [sp, #OFFSET_CVMCCExecEnv_ccmStorage+8] CALL_VM_FUNCTION(CVMmicrolockLockImpl) ldr MICROLOCK, [sp, #OFFSET_CVMCCExecEnv_ccmStorage+0] ldr OBJ, [sp, #OFFSET_CVMCCExecEnv_ccmStorage+4] ldr lr, [sp, #OFFSET_CVMCCExecEnv_ccmStorage+8] b _monexitUnlockObj /* Go unlock the object if possible. */LABEL(_monexitFastTryUnlockFailed) /* Release the microlock: */ mov r3, #CVM_MICROLOCK_UNLOCKED str r3, [MICROLOCK] /* Let C helper do the hard stuff: */ /* Load the ccee. The ee, and obj are already loaded. */ mov r0, sp str lr, [JFP, #OFFSET_CVMCompiledFrame_PC] str JFP, [a2, #OFFSET_CVMExecEnv_interpreterStack+OFFSET_CVMStack_currentFrame] BRANCH_TO_VM_FUNCTION(CVMCCMruntimeMonitorExit)#undef EE#undef OBJ#undef MICROLOCK#undef LOCKREC/* We only support fastlocking with atomic ops */#elif CVM_FASTLOCK_TYPE == CVM_FASTLOCK_ATOMICOPS/* * Entry point for monitorenter. */ LEAF_ENTRY CVMCCMruntimeMonitorEnterGlue ; ; Arguments: ; r2 = a3 = 'obj' ; ; Also incoming: ; r4 = v1 = jfp ; r5 = v2 = jsp ; sp = ccee ;/* TODO: This monitorenter and monitorexit code has not undergone thorough multi-threaded stress testing yet. It needs to undergo stress testing before release. */#if 0 ; ; If you just want to call the C helper and write very little ; assembler code, then just the following line is needed. ; CALL_HELPER_AND_PASS_EE(CVMCCMruntimeMonitorEnter)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -