After pushing the to-be-executed method frame on the top of stack thread, Dalvik will call the main interpreter to start the interpreting.
-dvmInterpret(Thread* self, const Method* method, JValue* pResult)
1. dvmInterpret()
-arguments:
1: Thread* self --> current thread
2: const Method* method --> current to-be-executed method
3: the returned value
-function work flow
1. Initialize working state
-source
interpState.method = method;
interpState.fp = (u4*) self->curFrame;
interpState.pc = method->insns;
interpState.entryPoint = kInterpEntryInstr;
if (dvmDebuggerOrProfilerActive())
interpState.nextMode = INTERP_DBG;
else
interpState.nextMode = INTERP_STD;
2. Determine execution mode. Typically, Dalvik has two modes of
interpreter to choose (C or Assembly for target platform).
-source
typedef bool (*Interpreter)(Thread*, InterpState*);
Interpreter stdInterp;
if (gDvm.executionMode == kExecutionModeInterpFast)
stdInterp = dvmMterpStd;
#if defined(WITH_JIT)
else if (gDvm.executionMode == kExecutionModeJit)
stdInterp = dvmMterpStd;
#endif
else
stdInterp = dvmInterpretStd;
3. Call the real interpreter with the thread and interpState parameters
change = true;
while (change) {
switch (interpState.nextMode) {
case INTERP_STD:
change = (*stdInterp)(self, &interpState);
break;
#if defined(WITH_PROFILER) || defined(WITH_DEBUGGER) || defined(WITH_JIT)
case INTERP_DBG:
change = dvmInterpretDbg(self, &interpState);
break;
#endif
default:
dvmAbort();
}
}
2010年10月20日 星期三
2010年10月12日 星期二
Thread's Stack Management in Dalvik VM
Thread Setup in Dalvik:
1. dvmThreadStartup() (vm/Thread.c)
-called by dvmStartup()
-This function will setup the thread list and the main
thread's environment
-important codes
thread = allocThread(gDvm.stackSize);
2. allocThread(int interpStackSize)
-Default stack size per stack: 3 * 4k pages
-Important codes
stackBottom = (u1*) malloc(interpStackSize);
thread->interpStackSize = interpStackSize;
thread->interpStackStart = stackBottom + interpStackSize;
thread->interpStackEnd = stackBottom +
STACK_OVERFLOW_RESERVE;(768 bytes)
-The initialized stack in a thread
Stack Push/Pop in Dalvik:
1. At first, dalvik vm main function will invoke
dvmCallMethodV() to interpret the java main
method
2. dvmCallMethodV() will invoke callPrep to push the
stack frame.
-callPrep will invoke dvmPushInterpFrame() to push
the related method frame on the thread's stack.
-The Dalvik vm thread stack frame
1. dvmThreadStartup() (vm/Thread.c)
-called by dvmStartup()
-This function will setup the thread list and the main
thread's environment
-important codes
thread = allocThread(gDvm.stackSize);
2. allocThread(int interpStackSize)
-Default stack size per stack: 3 * 4k pages
-Important codes
stackBottom = (u1*) malloc(interpStackSize);
thread->interpStackSize = interpStackSize;
thread->interpStackStart = stackBottom + interpStackSize;
thread->interpStackEnd = stackBottom +
STACK_OVERFLOW_RESERVE;(768 bytes)
-The initialized stack in a thread
Stack Push/Pop in Dalvik:
1. At first, dalvik vm main function will invoke
dvmCallMethodV() to interpret the java main
method
2. dvmCallMethodV() will invoke callPrep to push the
stack frame.
-callPrep will invoke dvmPushInterpFrame() to push
the related method frame on the thread's stack.
-The Dalvik vm thread stack frame
2010年9月9日 星期四
Dalvik Interpreter (1)
-Let's talk about how Dalvik generate interpreter for different platforms. All interpreter related files exist in dalvik/vm/mterp
1.
There exists a config file for every specific platform, e.g. config-armv5te or config-portstd. The config-portstd is a portable config file for all platforms.
2.
Every config file consists of the information needed by the gen-mterp.py. The gen-mterp.py is a python module which is used to read the platform-specific config file and generate the platform-specific interpreter.
3.
Following are currently supported platforms.
portstd
portdbg
allstubs
armv4t
armv5te
armv5te-vfp
armv7-a
x86
Every platform has its own .c and .S interpreter InterpC-$(TARGET_ARCH_EXT).c and InterpAsm-$(TARGET_ARCH_EXT).S. However, only .S or .c files has the interpreter entry point i.e. only one file is used to do interpreting.
The architecture-specific config files determine what goes into two generated out files (InterpC-$(TARGET_ARCH_EXT).c, InterpAsm- $(TARGET_ARCH_EXT).S). The goal is to make it easy to swap C and assembly sources during initial development and testing, and to provide a way to use architecture-specific versions of some operations (e.g. making use of PLD instructions on ARMv6 or avoiding CLZ on ARMv4T).
(Config file example 1) - config-portstd
# C file header and basic definitions
import c/header.c
# simple def to specify the "standard" interp
import portable/portstd.c
# C pre-processor defines for stub C instructions
import portable/stubdefs.c
# common defs for the C opcodes
import c/opcommon.c
# entry point
# This entry point will tell the Dalvik VM where to enter the interpreter
import portable/entry.c --> InterpC-portstd is the main interpreter file
# opcode list; argument to op-start is default directory
op-start c
# concatenate all C implementations
op-end
# "helper" code
import c/gotoTargets.c
# finish
import portable/enddefs.c
# source for the instruction table stub
asm-stub armv5te/stub.S
# file header and basic definitions
import c/header.c --> This file will be paste in .c
import armv5te/header.S --> This file will be paste in .S
# C pre-processor defines for stub C instructions
import cstubs/stubdefs.c --> This file will be paste in .c
# highly-platform-specific defs
import armv5te/platform.S --> This file will be paste in .S
# common defs for the C helpers; include this before the instruction handlers
import c/opcommon.c --> This file will be paste in .c
# arch-specific entry point to interpreter
# This entry point will tell the Dalvik VM where to enter the interpreter
import armv5te/entry.S --> InterpAsm-armv5te.S is the main interpreter file
# opcode list; argument to op-start is default directory
op-start armv5te
#op OP_FILL_ARRAY_DATA c
op-end
# "helper" code for C; include if you use any of the C stubs (this generates
# object code, so it's normally excluded)
##import c/gotoTargets.c
# end of defs; include this when cstubs/stubdefs.c is included
import cstubs/enddefs.c
# common subroutines for asm
import armv5te/footer.S
import armv5te/debug.c
1.
There exists a config file for every specific platform, e.g. config-armv5te or config-portstd. The config-portstd is a portable config file for all platforms.
2.
Every config file consists of the information needed by the gen-mterp.py. The gen-mterp.py is a python module which is used to read the platform-specific config file and generate the platform-specific interpreter.
3.
Following are currently supported platforms.
portstd
portdbg
allstubs
armv4t
armv5te
armv5te-vfp
armv7-a
x86
Every platform has its own .c and .S interpreter InterpC-$(TARGET_ARCH_EXT).c and InterpAsm-$(TARGET_ARCH_EXT).S. However, only .S or .c files has the interpreter entry point i.e. only one file is used to do interpreting.
The architecture-specific config files determine what goes into two generated out files (InterpC-$(TARGET_ARCH_EXT)
(Config file example 1) - config-portstd
# C file header and basic definitions
import c/header.c
# simple def to specify the "standard" interp
import portable/portstd.c
# C pre-processor defines for stub C instructions
import portable/stubdefs.c
# common defs for the C opcodes
import c/opcommon.c
# entry point
# This entry point will tell the Dalvik VM where to enter the interpreter
import portable/entry.c --> InterpC-portstd is the main interpreter file
# opcode list; argument to op-start is default directory
op-start c
# concatenate all C implementations
op-end
# "helper" code
import c/gotoTargets.c
# finish
import portable/enddefs.c
(Config file example 2) - config-armv5te
handler-size 64# source for the instruction table stub
asm-stub armv5te/stub.S
# file header and basic definitions
import c/header.c --> This file will be paste in .c
import armv5te/header.S --> This file will be paste in .S
# C pre-processor defines for stub C instructions
import cstubs/stubdefs.c --> This file will be paste in .c
# highly-platform-specific defs
import armv5te/platform.S --> This file will be paste in .S
# common defs for the C helpers; include this before the instruction handlers
import c/opcommon.c --> This file will be paste in .c
# arch-specific entry point to interpreter
# This entry point will tell the Dalvik VM where to enter the interpreter
import armv5te/entry.S --> InterpAsm-armv5te.S is the main interpreter file
# opcode list; argument to op-start is default directory
op-start armv5te
#op OP_FILL_ARRAY_DATA c
op-end
# "helper" code for C; include if you use any of the C stubs (this generates
# object code, so it's normally excluded)
##import c/gotoTargets.c
# end of defs; include this when cstubs/stubdefs.c is included
import cstubs/enddefs.c
# common subroutines for asm
import armv5te/footer.S
import armv5te/debug.c
2010年8月18日 星期三
Dalvik Interpreting Workflow (1)
How Dalvik VM execute the .dex file
dalvikvm/Main.c
1. Jni fuction: JNI_CreateJavaVM(JavaVM** p_vm, JNIEnv** p_env, void* vm_args)
JNI_CreateJavaVM will be called to construct a Dalvik virtual machine. JNI_CreateJavaVM is a function defined in Jni.h. The spec of Jni.h can be found on java site [1]. The JNI_CreateJavaVM will create everything needed to execute the .dex file, such as dynamic memory management, thread, bytecode verifier, etc. Then JavaVM and JNIEnv arguments will become the function interfaces to provide supported functions.
2. Jni function: FindClass(JNIEnv* env, const char* name)
This function will be called to find the class by name. Before executing a main method in java program, its class is needed to be found by a specified name.
3. Jni function: GetStaticMethodID(JNIEnv* env, jclass jclazz,
const char* name, const char* sig)
Because the java main function must be a static method, this jni function will be called to get the main method ID.
4. Jni function: CallStaticVoidMethod(JNIEnv* env, jclass jclazz, jmethodID methodID, ...)
This function will start to interprete the .dex file. This function will call the Dalvik interpreter to interprete the .dex file. However, we can't find a direct definition of the function in the directory because the developer of Dalvik VM used a trick to define this function. Things will be explained in the next.
References:
[1]. Jni functions: http://java.sun.com/docs/books/jni/html/functions.html#70415
2010年7月20日 星期二
Dalvik Memory Management (1)
Dalvik vm heap construction
Introduction:
The Dalvik vm has its own heap to allocate/de-allocate memory spaces for the newly created java classes. However, the posix doesn't provide interfaces to malloc/free memory spaces within an already set memory region. Therefore, the Dalvik vm uses the doug lea allocator (dlmalloc) to help it. The dlmalloc provide APIs to create a memory region and manage it. By using the dlmalloc, Dalvik vm has a heap to serve the dynamic memory allocation in Java.
1. At the construction step of Dalvik vm, callee: dvmHeapSourceStartup will be called
- file
-- dalvik/vm/alloc/HeapSource.c
- parameter
-- size_t startSize
= gDvm.heapSizeStart = 2 * 1024 * 1024 = 2MB
-- size_t absoluteMaxSize
= gDvm.heapSizeMax = 16 * 1024 * 1024 = 16MB
- return value
-- GcHeap *
2. Then callee: createMspace will be called by caller: dvmHeapSourceStartup
- file
-- dalvik/vm/alloc/HeapSource.c
- return value
-- static mspace *
- This function will do
Make the name of the need-to-create heap, and then call the API to create a contiguous memory space as the heap.
3. Then callee: create_contiguous_mspace_with_name will be called by caller: createMspace
- file
-- system/core/libcutils/mspace.c
- parameter
-- size_t starting_capacity
= startSize / 2 = gDvm.heapSizeStart / 2 = 1MB
-- size_t max_capacity
= absoluteMaxSize = gDvm.heapSizeMax = 16MB
-- int locked
= false
-- char const * name
= name generated in createMspace
- return value
-- mspace
- This function will do:
(1). max_capacity = (size_t)ALIGN_UP(max_capacity, pagesize);
set the heap's max size align up to page boundary
#define PAGESIZE 4096 = 4KB
#define ALIGN_UP(p, alignment) (((uintptr_t)(p) + (alignment)-1) & ~((alignment)-1))
(2). fd = ashmem_create_region(buf, max_capacity);
Map the /dev/zero to fd
fd = open("/dev/zero", O_RDWR);
(3). base = mmap(NULL, max_capacity, PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, 0);
Do mmap() to map the opened file /dev/zero to the memory with length = max_capacity. On Linux, the mapping will be created at a nearby page boundary.This step will create the needed heap for dynamic memory allocation usage.
(4). The following step will make some installation to the mapped memory in order to manage it as mspace.
local variable: struct mspace_contig_state *cs;
struct mspace_contig_state {
unsigned int magic;
char *brk;
char *top;
mspace m;
};
cs = base;
-This will make the cs point to the starting address of the created memory space, then the header of the memory space is cs.
m = create_mspace_with_base(base + sizeof(*cs), starting_capacity, locked);
-This will create the mspace from the mapped memory space.
cs->brk = m->seg.base + m->seg.size;
-This set the current usable size of the mspace, which is initialized to
m->footprint = m->max_footprint = starting_capacity = 1MB
cs->top = (char *)base + max_capacity;
This set the max usable size of the mspace.
if (cs->brk != cs->top) {
/* mprotect() requires page-aligned arguments, but it's possible
* for cs->brk not to be page-aligned at this point.
*/
char *prot_brk = (char *)ALIGN_UP(cs->brk, pagesize);
if (mprotect(prot_brk, cs->top - prot_brk, PROT_NONE) < 0)
goto error;
}
-This step prevents access to the memory Dalvim VM haven't handed out yet.
(5). return (mspace)m;
This step return the mspace pointer to the caller: createMspace
4. Then callee: mspace_set_max_allowed_footprint will be called by caller: createMspace
- parameter
-- mspace msp
= newly created mspace
-- size_t bytes
= startSize = 1MB
- local variable ms = (mstate)msp
-This function will set the current max_allowed_footprint. ms->max_allowed_footprint will be set to msp->footprint. This function will be called later to increase or decrease the
ms->max_allowed_footprint according to the usage of the Dalvik vm heap. If the Dalvik VM needs to grow its heap size, the ms->max_allowed_footprint will be increased.
Introduction:
The Dalvik vm has its own heap to allocate/de-allocate memory spaces for the newly created java classes. However, the posix doesn't provide interfaces to malloc/free memory spaces within an already set memory region. Therefore, the Dalvik vm uses the doug lea allocator (dlmalloc) to help it. The dlmalloc provide APIs to create a memory region and manage it. By using the dlmalloc, Dalvik vm has a heap to serve the dynamic memory allocation in Java.
1. At the construction step of Dalvik vm, callee: dvmHeapSourceStartup will be called
- file
-- dalvik/vm/alloc/HeapSource.c
- parameter
-- size_t startSize
= gDvm.heapSizeStart = 2 * 1024 * 1024 = 2MB
-- size_t absoluteMaxSize
= gDvm.heapSizeMax = 16 * 1024 * 1024 = 16MB
- return value
-- GcHeap *
2. Then callee: createMspace will be called by caller: dvmHeapSourceStartup
- file
-- dalvik/vm/alloc/HeapSource.c
- parameter
-- size_t startSize
= gDvm.heapSizeStart = 2 * 1024 * 1024 = 2MB
-- size_t absoluteMaxSize
= gDvm.heapSizeMax = 16 * 1024 * 1024 = 16MB
- return value
-- static mspace *
- This function will do
Make the name of the need-to-create heap, and then call the API to create a contiguous memory space as the heap.
3. Then callee: create_contiguous_mspace_with_name will be called by caller: createMspace
- file
-- system/core/libcutils/mspace.c
- parameter
-- size_t starting_capacity
= startSize / 2 = gDvm.heapSizeStart / 2 = 1MB
-- size_t max_capacity
= absoluteMaxSize = gDvm.heapSizeMax = 16MB
-- int locked
= false
-- char const * name
= name generated in createMspace
- return value
-- mspace
- This function will do:
(1). max_capacity = (size_t)ALIGN_UP(max_capacity, pagesize);
set the heap's max size align up to page boundary
#define PAGESIZE 4096 = 4KB
#define ALIGN_UP(p, alignment) (((uintptr_t)(p) + (alignment)-1) & ~((alignment)-1))
(2). fd = ashmem_create_region(buf, max_capacity);
Map the /dev/zero to fd
fd = open("/dev/zero", O_RDWR);
(3). base = mmap(NULL, max_capacity, PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, 0);
Do mmap() to map the opened file /dev/zero to the memory with length = max_capacity. On Linux, the mapping will be created at a nearby page boundary.This step will create the needed heap for dynamic memory allocation usage.
(4). The following step will make some installation to the mapped memory in order to manage it as mspace.
local variable: struct mspace_contig_state *cs;
struct mspace_contig_state {
unsigned int magic;
char *brk;
char *top;
mspace m;
};
cs = base;
-This will make the cs point to the starting address of the created memory space, then the header of the memory space is cs.
m = create_mspace_with_base(base + sizeof(*cs), starting_capacity, locked);
-This will create the mspace from the mapped memory space.
cs->brk = m->seg.base + m->seg.size;
-This set the current usable size of the mspace, which is initialized to
m->footprint = m->max_footprint = starting_capacity = 1MB
This set the max usable size of the mspace.
if (cs->brk != cs->top) {
/* mprotect() requires page-aligned arguments, but it's possible
* for cs->brk not to be page-aligned at this point.
*/
char *prot_brk = (char *)ALIGN_UP(cs->brk, pagesize);
if (mprotect(prot_brk, cs->top - prot_brk, PROT_NONE) < 0)
goto error;
}
-This step prevents access to the memory Dalvim VM haven't handed out yet.
(5). return (mspace)m;
This step return the mspace pointer to the caller: createMspace
4. Then callee: mspace_set_max_allowed_footprint will be called by caller: createMspace
- parameter
-- mspace msp
= newly created mspace
-- size_t bytes
= startSize = 1MB
- local variable ms = (mstate)msp
-This function will set the current max_allowed_footprint. ms->max_allowed_footprint will be set to msp->footprint. This function will be called later to increase or decrease the
ms->max_allowed_footprint according to the usage of the Dalvik vm heap. If the Dalvik VM needs to grow its heap size, the ms->max_allowed_footprint will be increased.
訂閱:
文章 (Atom)