//////// is key file for dalvik interpreter.
The general way to interpreting vm code is "switch-case" statement, like:
- while(true)
- {
- switch opcode:
- case 0x1: /*move op-code*/
- doMove();
- break;
- case 0x2: /*load data from memory*/
- doLoadFromMemory();
- break;
- ...
- opcode = nextInstruction();
- }
Dalvik improves the switch-case way by using "goto" way. The basic ideas is to limit the size of executable code for dalvik code to less than 64bytes. That is, the begin address of each executable code for dalvik code start from (64*op-code + base_addr). VM can go to special the executable code for respective dalvik code by calculating (op-code<<6 + opcode_base_addr). For example, dalvik code is
mov r2, r3
The dalvik interpreter get 1st dalvik code 0x2 and make calculation (0x2<<6+opcode_base_addr). The code on that address exactly define how to execute dalvik code(0x1)-move operation. When this op-code is done, next op-code address is calculated in same way.
Obviously, the "goto" way has less jmp instructions than ones in "switch-case" way.
invoke opcode:0x70
1) Find out Method struct according to ClassObject, methodID, methodType, detail in:
- Method* dvmResolveMethod(const ClassObject* referrer, u4 methodIdx, MethodType methodType)
- {
- ....
- }
2) If method is native,
- 26827 .LinvokeNative:
- 26828 @ Prep for the native call
- 26829 @ r0=methodToCall, r1=newFp, r10=newSaveArea
- 26830 ldrh lr, [rSELF, #offThread_subMode]
- 26831 ldr r9, [rSELF, #offThread_jniLocal_topCookie]@r9<-thread->localRef->...
- 26832 str r1, [rSELF, #offThread_curFrame] @ curFrame = newFp
- 26833 str r9, [r10, #offStackSaveArea_localRefCookie] @newFp->localRefCookie=top
- 26834 mov r2, r0 @ r2<- methodToCall
- 26835 mov r0, r1 @ r0<- newFp (points to args)
- 26836 add r1, rSELF, #offThread_retval @ r1<- &retval
- 26837 mov r3, rSELF @ arg3<- self
- 26838 ....
- 26852 mov lr, pc @ set return addr
- 26853 ldr pc, [r2, #offMethod_nativeFunc] @ pc<- methodToCall->nativeFunc
- 26856 @ native return; r10=newSaveArea
- 26857 @ equivalent to dvmPopJniLocals
- 26858 ldr r0, [r10, #offStackSaveArea_localRefCookie] @ r0<- saved top
- 26859 ldr r1, [rSELF, #offThread_exception] @ check for exception
- 26860 str rFP, [rSELF, #offThread_curFrame] @ curFrame = fp
- 26861 cmp r1, #0 @ null?
- 26862 str r0, [rSELF, #offThread_jniLocal_topCookie] @ new top <- old top
- 26863 bne common_exceptionThrown @ no, handle exception
- 26864
- 26865 FETCH_ADVANCE_INST(3) @ advance rPC, load rINST
- 26866 GET_INST_OPCODE(ip) @ extract opcode from rINST
- 26867 GOTO_OPCODE(ip) @ jump to next instruction
Line 26833 setup new local reference top index. Line 26862 restore the old cookie top index. This make all the local reference located in called function became invalid.
Line 26867 jump to next op-code;
Actually, the native function call by line 26853 is not real jni function, which is or . Please refer to
- 834 void dvmUseJNIBridge(Method* method, void* func) {
- 835 method->shouldTrace = shouldTrace(method);
- 836 ....
- 847 DalvikBridgeFunc bridge = gDvmJni.useCheckJni ? dvmCheckCallJNIMethod : dvmCallJNIMethod;
- 848 dvmSetNativeFunc(method, bridge, (const u2*) func);
- 849 }
In dvmCallJNIMethod,
- 1177 ThreadStatus oldStatus = dvmChangeStatus(self, THREAD_NATIVE);
- 1178
- 1179 ANDROID_MEMBAR_FULL(); /* guarantee ordering on method->insns */
- 1180 assert(method->insns != NULL);
- 1181
- 1182 JNIEnv* env = self->jniEnv;
- 1183 COMPUTE_STACK_SUM(self);
- 1184 dvmPlatformInvoke(env,
- 1185 (ClassObject*) staticMethodClass,
- 1186 method->jniArgInfo, method->insSize, modArgs, method->shorty,
- 1187 (void*) method->insns, pResult);
- 1188 CHECK_STACK_SUM(self);
- 1189
- 1190 dvmChangeStatus(self, oldStatus);
Line 1184 make the real jni call.
3) If method is java code, and it has no JIT translation code.
- 26488 common_updateProfile:
- 26489 eor r3,rPC,rPC,lsr #12 @ cheap, but fast hash function
- 26490 lsl r3,r3,#(32 - JIT_PROF_SIZE_LOG_2) @ shift out excess bits
- 26491 ldrb r1,[r0,r3,lsr #(32 - JIT_PROF_SIZE_LOG_2)] @ get counter
- 26492 GET_INST_OPCODE(ip)
- 26493 subs r1,r1,#1 @ decrement counter
- 26494 strb r1,[r0,r3,lsr #(32 - JIT_PROF_SIZE_LOG_2)] @ and store it
- 26495 GOTO_OPCODE_IFNE(ip) @ if not threshold, fallthrough otherwise */
Line 26495 go into java function.
if it has JIT translation code, interpreter call () to get translation code, and jmp to it.
阅读(2139) | 评论(0) | 转发(0) |