📄 ccmglue_cpu.s
字号:
/* * @(#)ccmglue_cpu.S 1.41 06/10/29 * * 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. *//* * Copyright 2005 Intel Corporation. All rights reserved. *//* * 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/sync.h"/* * NOTE: Some linker such as the ARM RVCT (v2.2) linker sorts * sections by attributes and section name. To make sure * the CCM copied code in the same order as they are included * in ccmcodecachecopy_cpu.S, we need to name the sections * in alphabetical order. */ SET_SECTION_EXEC(s1_ccmglue_cpu)/* * Make a pc-relative branch instruction. Used for patching and instruction * to jump around generated code. */ #ifdef __RVCT__#define MAKE_BRANCH(offset) \ ((14 << 28) :OR: /* COND_AL */ \ (5 << 25) :OR: /* branch opcode */ \ (((offset - 8) >> 2) :AND: 0x00ffffff)) /* branch offset */ #else#define MAKE_BRANCH(offset) \ ((14 << 28) | /* COND_AL */ \ (5 << 25) | /* branch opcode */ \ (((offset - 8) >> 2) & 0x00ffffff)) /* branch offset */ #endif/* * Macro for calling a helper. Sets up the ccee and ee as first two * arguments and flushes the pc to the frame and the frame to the * interpreter stack. */#ifndef __RVCT__#define CALL_HELPER_AND_PASS_EE(HELPER) \ mov a1, sp ; \ ldr a2, [sp, #OFFSET_CVMCCExecEnv_ee] ; \ str lr, [JFP, #OFFSET_CVMCompiledFrame_PC] ; \ str JFP, [a2, #OFFSET_CVMExecEnv_interpreterStack+OFFSET_CVMStack_currentFrame] ; \ BRANCH_TO_VM_FUNCTION(HELPER)#else MACRO CALL_HELPER_AND_PASS_EE0 $HELPER IMPORT $HELPER mov a1, sp ldr a2, [sp, #OFFSET_CVMCCExecEnv_ee] str lr, [JFP, #OFFSET_CVMCompiledFrame_PC] str JFP, [a2, #OFFSET_CVMExecEnv_interpreterStack+OFFSET_CVMStack_currentFrame] BRANCH_TO_VM_FUNCTION($HELPER) MEND#define CALL_HELPER_AND_PASS_EE(HELPER) \ CALL_HELPER_AND_PASS_EE0 HELPER#endif/* * Macro for calling a helper. Sets up the ccee as the first * argument and flushes the pc to the frame and the frame to the * interpreter stack. It also passes the address of the cache or * guess value in a4. */#ifndef __RVCT__#define CALL_HELPER_AND_PASS_CACHE_ADDR(HELPER) \ ldr a1, [sp, #OFFSET_CVMCCExecEnv_ee] ; \ str lr, [JFP, #OFFSET_CVMCompiledFrame_PC] ; \ str JFP, [a1, #OFFSET_CVMExecEnv_interpreterStack+OFFSET_CVMStack_currentFrame] ; \ mov a1, sp ; \ BRANCH_TO_VM_FUNCTION(HELPER)#else MACRO CALL_HELPER_AND_PASS_CACHE_ADDR0 $HELPER IMPORT $HELPER ldr a1, [sp, #OFFSET_CVMCCExecEnv_ee] str lr, [JFP, #OFFSET_CVMCompiledFrame_PC] str JFP, [a1, #OFFSET_CVMExecEnv_interpreterStack+OFFSET_CVMStack_currentFrame] mov a1, sp BRANCH_TO_VM_FUNCTION($HELPER) MEND#define CALL_HELPER_AND_PASS_CACHE_ADDR(HELPER) \ CALL_HELPER_AND_PASS_CACHE_ADDR0 HELPER#endif/* do a gc rendezvous */ ENTRY(CVMCCMruntimeGCRendezvousGlue)ENTRY1 ( CVMCCMruntimeGCRendezvousGlue ) CALL_HELPER_AND_PASS_EE(CVMCCMruntimeGCRendezvous) SET_SIZE(CVMCCMruntimeGCRendezvousGlue)#if defined(CVM_JIT_COPY_CCMCODE_TO_CODECACHE) && defined(CVMJIT_PATCH_BASED_GC_CHECKS) ENTRY(CVMARMruntimeGCRendezvousAdjustRetAddrGlue)ENTRY1 ( CVMARMruntimeGCRendezvousAdjustRetAddrGlue ) /* If we are copying to the code cache, then only one instruction * was needed to call us, so we want to return to it. Otherwise * it may have taken multiple instructions, so the last one is * patched with a nop so we can skip it. */ sub lr, lr, #4 /* we want to return to the patch point */ CALL_HELPER_AND_PASS_EE(CVMCCMruntimeGCRendezvous) SET_SIZE(CVMARMruntimeGCRendezvousAdjustRetAddrGlue)#endif/* Throw various well known exceptions */ ENTRY(CVMCCMruntimeThrowNullPointerExceptionGlue)ENTRY1 ( CVMCCMruntimeThrowNullPointerExceptionGlue ) IMPORT(java_lang_NullPointerException_Classblock) FIXUP_FRAMES(JFP, {lr}, 1) ldr a3, SYMBOL(java_lang_NullPointerException_Classblock) mov a4, #0 /* exception message */ CALL_HELPER_AND_PASS_EE(CVMCCMruntimeThrowClass) SET_SIZE(CVMCCMruntimeThrowNullPointerExceptionGlue) ENTRY(CVMCCMruntimeThrowArrayIndexOutOfBoundsExceptionGlue)ENTRY1 ( CVMCCMruntimeThrowArrayIndexOutOfBoundsExceptionGlue ) IMPORT(java_lang_ArrayIndexOutOfBoundsException_Classblock) FIXUP_FRAMES(JFP, {lr}, 1)#ifdef ARMASM_LONG_SYMBOL_NAME_BUG ldr a3, L1#else ldr a3, SYMBOL(java_lang_ArrayIndexOutOfBoundsException_Classblock)#endif mov a4, #0 /* exception message */ CALL_HELPER_AND_PASS_EE(CVMCCMruntimeThrowClass) SET_SIZE(CVMCCMruntimeThrowArrayIndexOutOfBoundsExceptionGlue)#ifdef ARMASM_LONG_SYMBOL_NAME_BUGL1 DCD java_lang_ArrayIndexOutOfBoundsException_Classblock#endif ENTRY(CVMCCMruntimeThrowDivideByZeroGlue)ENTRY1 ( CVMCCMruntimeThrowDivideByZeroGlue ) IMPORT(java_lang_ArithmeticException_Classblock) FIXUP_FRAMES(JFP, {lr}, 1) adr a4, divideByZeroString /*exception message */ ldr a3, SYMBOL(java_lang_ArithmeticException_Classblock) CALL_HELPER_AND_PASS_EE(CVMCCMruntimeThrowClass)LABEL(divideByZeroString) STRING("/ by zero") SET_SIZE(CVMCCMruntimeThrowDivideByZeroGlue)/* Throw an object */ ENTRY(CVMCCMruntimeThrowObjectGlue)ENTRY1 ( CVMCCMruntimeThrowObjectGlue )#define SAVESET {a3, lr} FIXUP_FRAMES(JFP, SAVESET, 2)#undef SAVESET CALL_HELPER_AND_PASS_EE(CVMCCMruntimeThrowObject)/* do a checkcast */ ENTRY(CVMCCMruntimeCheckCastGlue)ENTRY1 ( CVMCCMruntimeCheckCastGlue ) /* a1 = object to cast * a2 = objectCb #ifdef IAI_CACHEDCONSTANT_INLINING * a3 = castCb * a4 = guess cb address #ifdef IAI_CACHEDCONSTANT * lr = guess cb address #ifndef IAI_CACHEDCONSTANT * cc = eq if a1 is null #ifndef IAI_CACHEDCONSTANT_INLINING */#ifndef IAI_CACHEDCONSTANT_INLINING#ifdef IAI_CACHEDCONSTANT ldrne a2, [a1] /* a2 = object.cb */ ldrne a1, [a4] /* load the guess cb */ bicne a2, a2, #3 /* mask off low bits of object cb */ cmpne a1, a2 /* see if guess is correct */ moveq pc, lr /* return, null or same as last successful cast*/#else ldrne a2, [a1] /* a2 = object.cb */ ldrne a1, [lr] /* load the guess cb */ add lr, lr, #4 /* skip passed the guess addr to the return addr*/ bicne a2, a2, #3 /* mask off low bits of object cb */ cmpne a1, a2 /* see if guess is correct */ moveq pc, lr /* return, null or same as last successful cast*/#endif /* !IAI_CACHEDCONSTANT*/#endif /* IAI_CACHEDCONSTANT_INLINING */#ifndef IAI_CACHEDCONSTANT sub a4, lr, #4 /* load guess cb address */#endif/* IAI - 21 */#if defined(IAI_FAST_ASSIGNABLE_CHECKING) && !defined(CVM_AOT) /* Fast runtime check cast. * Compare the cast cb with current object's class, super class, * super'super class ... till to the super class is NULL. */ mov a1, a2 /* a1 = object.cb */FASTCHECKING1: cmp a3, a1 /* cast cb ?= object.cb */ streq a2, [a4] /* save the matched cb into cache */ moveq pc, lr /* match, so return */ ldr a1, [a1, #OFFSET_CVMClassBlock_superClassCb] /* load super class*/ cmp a1, #0 /* Object class? no super class */ bne FASTCHECKING1#endif /* IAI_FAST_ASSIGNABLE_CHECKING */ /* need to call the helper * a2 = objectCb * a3 = instanceCb * a4 = guess cb address */#define SAVESET {a2, a3, lr} FIXUP_FRAMES(JFP, SAVESET, 3)#undef SAVESET CALL_HELPER_AND_PASS_CACHE_ADDR(CVMCCMruntimeCheckCast)/* do an instanceof check */ ENTRY(CVMCCMruntimeInstanceOfGlue)ENTRY1 ( CVMCCMruntimeInstanceOfGlue ) /* a1 = object to cast * a2 = objectCb #ifdef IAI_CACHEDCONSTANT_INLINING * a3 = instanceofCb * a4 = guess cb address #ifdef IAI_CACHEDCONSTANT * lr = guess cb address #ifndef IAI_CACHEDCONSTANT * cc = eq if a1 is null #ifndef IAI_CACHEDCONSTANT_INLINING */#ifndef IAI_CACHEDCONSTANT_INLINING#ifdef IAI_CACHEDCONSTANT moveq pc, lr /* return FALSE if object is NULL */ ldrne a2, [a1] /* a2 = object.cb */ ldrne a1, [a4] /* load the guess cb */ bicne a2, a2, #3 /* mask off low bits of object cb */ cmpne a1, a2 /* see if guess is correct */ moveq a1, #1 /* return TRUE if equal */ moveq pc, lr /* return, same as last successful cast */#else addeq pc, lr, #4 /* return FALSE if object is NULL */ ldrne a2, [a1] /* a2 = object.cb */ ldrne a1, [lr] /* load the guess cb */ add lr, lr, #4 /* skip passed the guess addr to the return addr*/ bicne a2, a2, #3 /* mask off low bits of object cb */ cmpne a1, a2 /* see if guess is correct */ moveq a1, #1 /* return TRUE if equal */ moveq pc, lr /* return, same as last successful cast */#endif /* !IAI_CACHEDCONSTANT*/#endif /* IAI_CACHEDCONSTANT_INLINING */#ifndef IAI_CACHEDCONSTANT sub a4, lr, #4 /* load guess cb address */#endif/* IAI - 21 */#if defined(IAI_FAST_ASSIGNABLE_CHECKING) && !defined(CVM_AOT) /* Fast runtime instanceOf Test. * Compare the cast cb with current object's class, super class, * super'super class ... till to the super class is NULL. */ mov a1, a2 /* a1 = object.cb */FASTCHECKING2: cmp a3, a1 /* cast cb ?= object.cb */ streq a2, [a4] /* save the matched cb into cache */ moveq a1, #1 moveq pc, lr /* match, so return */ ldr a1, [a1, #OFFSET_CVMClassBlock_superClassCb] /* load super class*/ cmp a1, #0 /* Object class? no super class */ bne FASTCHECKING2#endif /* IAI_FAST_ASSIGNABLE_CHECKING */ /* need to call the helper * a2 = objectCb * a3 = instanceCb * a4 = guess cb address */ CALL_HELPER_AND_PASS_CACHE_ADDR(CVMCCMruntimeInstanceOf)/* check reference array assignment capatibility */ ENTRY(CVMCCMruntimeCheckArrayAssignableGlue)ENTRY1 ( CVMCCMruntimeCheckArrayAssignableGlue ) /* a3 = cb of array object (with low bits still set) */ /* a4 = cb of rhs object (with low bits still set) */ bic a3, a3, #3 /* clear low bits of arraycb */ ldr a3, [a3, #OFFSET_CVMClassBlock_arrayInfoX] /*arraycb->arrayInfo*/ bic a4, a4, #3 /* clear low bits of rhs cb */ ldr a3, [a3, #OFFSET_CVMArrayInfo_elementCb] /* arrayInfo->elemCb*/ cmp a3, a4 /* check if elemClass(arr) == class(rhs) */ moveq pc, lr IMPORT(java_lang_Object_Classblock) ldr a1, SYMBOL(java_lang_Object_Classblock) cmp a3, a1 /* check if elemClass(arr) == Object */ moveq pc, lr /* a3 = element cb of array object (with low bits clear) */ /* a4 = cb of rhs object (with low bits clear) */#define SAVESET {a3, a4, lr} FIXUP_FRAMES(JFP, SAVESET, 3)#undef SAVESET CALL_HELPER_AND_PASS_EE(CVMCCMruntimeCheckArrayAssignable)/* run the clinit of a class */ ENTRY(CVMCCMruntimeRunClassInitializerGlue)ENTRY1 ( CVMCCMruntimeRunClassInitializerGlue ) /* a3 = target cb * lr = return address * setup ccee and ee arguments */ mov a1, sp ldr a2, [sp, #OFFSET_CVMCCExecEnv_ee] /* flush state */ str JSP, [JFP, #OFFSET_CVMFrame_topOfStack] str lr, [JFP, #OFFSET_CVMCompiledFrame_PC] str JFP, [a2, #OFFSET_CVMExecEnv_interpreterStack+OFFSET_CVMStack_currentFrame] /* call the helper. If the clinit has to be run, it will return * directly to the method that called us. */ CALL_VM_FUNCTION(CVMCCMruntimeRunClassInitializer) /* 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 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. */ /* We don't want to patch pre-compiled code through. */#ifdef CVM_MTASK IMPORT(CVMJITcodeCacheDecompileStart) ldr a2, SYMBOL(CVMJITcodeCacheDecompileStart) ldr a2, [a2] ldr a2, [a2] cmp lr, a2 movlo pc, lr#endif#ifdef CVM_AOT IMPORT(CVMJITcodeCacheAOTEnd) IMPORT(CVMJITcodeCacheAOTStart) ldr a2, SYMBOL(CVMJITcodeCacheAOTEnd) ldr a2, [a2] ldr a2, [a2]
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -