<h2><code>access_flags</code> Definitions</h2>
<h4>embedded in <code>class_def_item</code>,
-<code>field_item</code>, <code>method_item</code>, and
+<code>encoded_field</code>, <code>encoded_method</code>, and
<code>InnerClass</code></h4>
<p>Bitfields of these flags are used to indicate the accessibility and
</table>
<h2><code>code_item</code></h2>
-<h4>referenced from <code>method_item</code></h4>
+<h4>referenced from <code>encoded_method</code></h4>
<h4>appears in the <code>data</code> section</h4>
<h4>alignment: 4 bytes</h4>
TypeBearer lastType = sources.get(szSources - 1).getTypeBearer();
- // TODO: Check for reverse subtraction, where first source is constant
if (!lastType.isConstant()) {
- return this;
- }
-
- Constant cst = (Constant) lastType;
-
- RegisterSpecList newSources = sources.withoutLast();
-
- Rop newRop;
- try {
- // Check for constant subtraction and flip them to be addition
- int opcode = getOpcode().getOpcode();
- if (opcode == RegOps.SUB && cst instanceof CstInteger) {
- opcode = RegOps.ADD;
- cst = CstInteger.make(-((CstInteger)cst).getValue());
+ // Check for reverse subtraction, where first source is constant
+ TypeBearer firstType = sources.get(0).getTypeBearer();
+ if (szSources == 2 && firstType.isConstant()) {
+ Constant cst = (Constant) firstType;
+ RegisterSpecList newSources = sources.withoutFirst();
+ Rop newRop = Rops.ropFor(getOpcode().getOpcode(), getResult(),
+ newSources, cst);
+ return new PlainCstInsn(newRop, getPosition(), getResult(),
+ newSources, cst);
}
- newRop = Rops.ropFor(opcode, getResult(), newSources, cst);
- } catch (IllegalArgumentException ex) {
- // There's no rop for this case
return this;
- }
+ } else {
+
+ Constant cst = (Constant) lastType;
+
+ RegisterSpecList newSources = sources.withoutLast();
+
+ Rop newRop;
+ try {
+ // Check for constant subtraction and flip it to be addition
+ int opcode = getOpcode().getOpcode();
+ if (opcode == RegOps.SUB && cst instanceof CstInteger) {
+ opcode = RegOps.ADD;
+ cst = CstInteger.make(-((CstInteger)cst).getValue());
+ }
+ newRop = Rops.ropFor(opcode, getResult(), newSources, cst);
+ } catch (IllegalArgumentException ex) {
+ // There's no rop for this case
+ return this;
+ }
- return new PlainCstInsn(newRop, getPosition(),
- getResult(), newSources, cst);
+ return new PlainCstInsn(newRop, getPosition(),
+ getResult(), newSources, cst);
+ }
}
#include <sys/types.h>
+#ifdef __cplusplus
+extern "C" {
+#endif
+
/*
* System page size. Normally you're expected to get this from
* sysconf(_SC_PAGESIZE) or some system-specific define (usually PAGESIZE
*/
int sysCopyFileToFile(int outFd, int inFd, size_t count);
+#ifdef __cplusplus
+}
+#endif
+
#endif /*_DALVIK_SYSUTIL*/
#ifndef _DALVIK_ALLOCTRACKER
#define _DALVIK_ALLOCTRACKER
+#ifdef __cplusplus
+extern "C" {
+#endif
+
/* initialization */
bool dvmAllocTrackerStartup(void);
void dvmAllocTrackerShutdown(void);
*/
void dvmDumpTrackedAllocations(bool enable);
+#ifdef __cplusplus
+}
+#endif
+
#endif /*_DALVIK_ALLOCTRACKER*/
#include <cutils/atomic.h> /* use common Android atomic ops */
#include <cutils/atomic-inline.h> /* and some uncommon ones */
+#ifdef __cplusplus
+extern "C" {
+#endif
+
/*
* NOTE: Two "quasiatomic" operations on the exact same memory address
* are guaranteed to operate atomically with respect to each other,
int dvmQuasiAtomicCas64(int64_t oldvalue, int64_t newvalue,
volatile int64_t* addr);
+#ifdef __cplusplus
+}
+#endif
+
#endif /*_DALVIK_ATOMIC*/
#ifndef _DALVIK_BITVECTOR
#define _DALVIK_BITVECTOR
+#ifdef __cplusplus
+extern "C" {
+#endif
+
/*
* Expanding bitmap, used for tracking resources. Bits are numbered starting
* from zero.
/* Return the next position set to 1. -1 means end-of-vector reached */
int dvmBitVectorIteratorNext(BitVectorIterator* iterator);
+#ifdef __cplusplus
+}
+#endif
+
#endif /*_DALVIK_BITVECTOR*/
# define LOG_TAG "dalvikvm"
#endif
+#include <stdbool.h>
+#include <stdint.h>
#include <stdio.h>
#include <assert.h>
+#include <endian.h>
+#include "utils/Log.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
#if !defined(NDEBUG) && defined(WITH_DALVIK_ASSERT)
# undef assert
/*
* These match the definitions in the VM specification.
*/
-#ifdef HAVE_STDINT_H
-# include <stdint.h> /* C99 */
typedef uint8_t u1;
typedef uint16_t u2;
typedef uint32_t u4;
typedef int16_t s2;
typedef int32_t s4;
typedef int64_t s8;
-#else
-typedef unsigned char u1;
-typedef unsigned short u2;
-typedef unsigned int u4;
-typedef unsigned long long u8;
-typedef signed char s1;
-typedef signed short s2;
-typedef signed int s4;
-typedef signed long long s8;
-#endif
/*
* Storage for primitive types and object references.
void* l;
} JValue;
-/*
- * The <stdbool.h> definition uses _Bool, a type known to the compiler.
- */
-#ifdef HAVE_STDBOOL_H
-# include <stdbool.h> /* C99 */
-#else
-# ifndef __bool_true_false_are_defined
-typedef enum { false=0, true=!false } bool;
-# define __bool_true_false_are_defined 1
-# endif
-#endif
-
#define NELEM(x) ((int) (sizeof(x) / sizeof((x)[0])))
-
-#if defined(HAVE_ENDIAN_H)
-# include <endian.h>
-#else /*not HAVE_ENDIAN_H*/
-# define __BIG_ENDIAN 4321
-# define __LITTLE_ENDIAN 1234
-# if defined(HAVE_LITTLE_ENDIAN)
-# define __BYTE_ORDER __LITTLE_ENDIAN
-# else
-# define __BYTE_ORDER __BIG_ENDIAN
-# endif
-#endif /*not HAVE_ENDIAN_H*/
-
-
-#if 0
-/*
- * Pretend we have the Android logging macros. These are replaced by the
- * Android logging implementation.
- */
-#define ANDROID_LOG_DEBUG 3
-#define LOGV(...) LOG_PRI(2, 0, __VA_ARGS__)
-#define LOGD(...) LOG_PRI(3, 0, __VA_ARGS__)
-#define LOGI(...) LOG_PRI(4, 0, __VA_ARGS__)
-#define LOGW(...) LOG_PRI(5, 0, __VA_ARGS__)
-#define LOGE(...) LOG_PRI(6, 0, __VA_ARGS__)
-#define MIN_LOG_LEVEL 2
-
-#define LOG_PRI(priority, tag, ...) do { \
- if (priority >= MIN_LOG_LEVEL) { \
- dvmFprintf(stdout, "%s:%-4d ", __FILE__, __LINE__); \
- dvmFprintf(stdout, __VA_ARGS__); \
- } \
- } while(0)
-#else
-# include "utils/Log.h"
+#ifdef __cplusplus
+}
#endif
#endif /*_DALVIK_COMMON*/
#ifndef _DALVIK_DALVIK
#define _DALVIK_DALVIK
-#include <pthread.h>
-
#include "Common.h"
#include "Inlines.h"
#include "Misc.h"
#ifndef _DALVIK_DDM
#define _DALVIK_DDM
+#ifdef __cplusplus
+extern "C" {
+#endif
+
/*
* Handle a packet full of DDM goodness.
*
*/
ArrayObject* dvmDdmGetRecentAllocations(void);
+#ifdef __cplusplus
+}
+#endif
+
#endif /*_DALVIK_DDM*/
#ifndef _DALVIK_DEBUGGER
#define _DALVIK_DEBUGGER
+#include <pthread.h>
#include "Common.h"
#include "Misc.h"
#include "jdwp/Jdwp.h"
-#include <pthread.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
/* fwd decl */
struct Object;
#define CHUNK_TYPE(_name) \
((_name)[0] << 24 | (_name)[1] << 16 | (_name)[2] << 8 | (_name)[3])
+#ifdef __cplusplus
+}
+#endif
+
#endif /*_DALVIK_DEBUGGER*/
Sync.c \
Thread.c \
UtfString.c \
- alloc/Alloc.c \
- alloc/CardTable.c \
- alloc/HeapBitmap.c.arm \
- alloc/HeapDebug.c \
- alloc/Heap.c.arm \
- alloc/DdmHeap.c \
- alloc/Verify.c \
- alloc/Visit.c \
+ alloc/Alloc.cpp \
+ alloc/CardTable.cpp \
+ alloc/HeapBitmap.cpp.arm \
+ alloc/HeapDebug.cpp \
+ alloc/Heap.cpp.arm \
+ alloc/DdmHeap.cpp \
+ alloc/Verify.cpp \
+ alloc/Visit.cpp \
analysis/CodeVerify.c \
analysis/DexPrepare.c \
analysis/DexVerify.c \
analysis/RegisterMap.c \
analysis/VerifySubs.c \
analysis/VfyBasicBlock.c \
- hprof/Hprof.c \
- hprof/HprofClass.c \
- hprof/HprofHeap.c \
- hprof/HprofOutput.c \
- hprof/HprofString.c \
+ hprof/Hprof.cpp \
+ hprof/HprofClass.cpp \
+ hprof/HprofHeap.cpp \
+ hprof/HprofOutput.cpp \
+ hprof/HprofString.cpp \
interp/Interp.c.arm \
interp/Stack.c \
jdwp/ExpandBuf.c \
ifeq ($(WITH_COPYING_GC),true)
LOCAL_CFLAGS += -DWITH_COPYING_GC
LOCAL_SRC_FILES += \
- alloc/Copying.c.arm
+ alloc/Copying.cpp.arm
else
LOCAL_SRC_FILES += \
- alloc/HeapSource.c \
- alloc/MarkSweep.c.arm
+ alloc/HeapSource.cpp \
+ alloc/MarkSweep.cpp.arm
endif
WITH_JIT := $(strip $(WITH_JIT))
#ifndef _DALVIK_DVMDEX
#define _DALVIK_DVMDEX
+#ifdef __cplusplus
+extern "C" {
+#endif
+
#include "libdex/DexFile.h"
/* extern */
pDvmDex->pResFields[fieldIdx] = field;
}
+#ifdef __cplusplus
+}
+#endif
+
#endif /*_DALVIK_DVMDEX*/
#ifndef _DALVIK_EXCEPTION
#define _DALVIK_EXCEPTION
+#ifdef __cplusplus
+extern "C" {
+#endif
+
/*
* Create a Throwable and throw an exception in the current thread (where
* "throwing" just means "set the thread's exception pointer").
*/
void dvmThrowVirtualMachineError(const char* msg);
+#ifdef __cplusplus
+}
+#endif
+
#endif /*_DALVIK_EXCEPTION*/
#include <stdarg.h>
#include <pthread.h>
+#ifdef __cplusplus
+extern "C" {
+#endif
+
#define MAX_BREAKPOINTS 20 /* used for a debugger optimization */
/* private structures */
#endif
+#ifdef __cplusplus
+}
+#endif
+
#endif /*_DALVIK_GLOBALS*/
#ifndef _DALVIK_HASH
#define _DALVIK_HASH
+#ifdef __cplusplus
+extern "C" {
+#endif
+
/* compute the hash of an item with a specific type */
typedef u4 (*HashCompute)(const void* item);
void dvmHashTableProbeCount(HashTable* pHashTable, HashCalcFunc calcFunc,
HashCompareFunc cmpFunc);
+#ifdef __cplusplus
+}
+#endif
+
#endif /*_DALVIK_HASH*/
#ifndef _DALVIK_INDIRECTREFTABLE
#define _DALVIK_INDIRECTREFTABLE
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
/*
* Maintain a table of indirect references. Used for local/global JNI
* references.
*/
void dvmDumpIndirectRefTable(const IndirectRefTable* pRef, const char* descr);
+#ifdef __cplusplus
+}
+#endif
+
#endif /*_DALVIK_INDIRECTREFTABLE*/
#ifndef _DALVIK_INIT
#define _DALVIK_INIT
+#ifdef __cplusplus
+extern "C" {
+#endif
+
/*
* Standard VM initialization, usually invoked through JNI.
*/
#endif
;
+#ifdef __cplusplus
+}
+#endif
+
#endif /*_DALVIK_INIT*/
#ifndef _DALVIK_INLINENATIVE
#define _DALVIK_INLINENATIVE
+#ifdef __cplusplus
+extern "C" {
+#endif
+
/* startup/shutdown */
bool dvmInlineNativeStartup(void);
void dvmInlineNativeShutdown(void);
*/
Method* dvmResolveInlineNative(int opIndex);
+#ifdef __cplusplus
+}
+#endif
+
#endif /*_DALVIK_INLINENATIVE*/
#ifndef _DALVIK_INTERN
#define _DALVIK_INTERN
+#ifdef __cplusplus
+extern "C" {
+#endif
+
bool dvmStringInternStartup(void);
void dvmStringInternShutdown(void);
StringObject* dvmLookupInternedString(StringObject* strObj);
bool dvmIsWeakInternedString(const StringObject* strObj);
void dvmGcDetachDeadInternedStrings(int (*isUnmarkedObject)(void *));
+#ifdef __cplusplus
+}
+#endif
+
#endif /*_DALVIK_INTERN*/
#ifndef _DALVIK_JARFILE
#define _DALVIK_JARFILE
+#ifdef __cplusplus
+extern "C" {
+#endif
+
/*
* This represents an open, scanned Jar file. (It's actually for any Zip
* archive that happens to hold a Dex file.)
*/
DexCacheStatus dvmDexCacheStatus(const char *fileName);
+#ifdef __cplusplus
+}
+#endif
+
#endif /*_DALVIK_JARFILE*/
assert(dvmCheckException(_self));
id = NULL;
} else {
- id = (jfieldID) dvmFindStaticField(clazz, name, sig);
+ id = (jfieldID) dvmFindStaticFieldHier(clazz, name, sig);
if (id == NULL) {
dvmThrowExceptionFmt(gDvm.exNoSuchFieldError,
"no static field with name='%s' signature='%s' in class %s",
#include "jni.h"
+#ifdef __cplusplus
+extern "C" {
+#endif
+
/* system init/shutdown */
bool dvmJniStartup(void);
void dvmJniShutdown(void);
*/
void dvmDumpJniReferenceTables(void);
+#ifdef __cplusplus
+}
+#endif
+
#endif /*_DALVIK_JNIINTERNAL*/
#ifndef _DALVIK_LINEARALLOC
#define _DALVIK_LINEARALLOC
+#ifdef __cplusplus
+extern "C" {
+#endif
+
/*
* If this is set, we create additional data structures and make many
* additional mprotect() calls.
*/
bool dvmLinearAllocContains(const void* start, size_t length);
+#ifdef __cplusplus
+}
+#endif
+
#endif /*_DALVIK_LINEARALLOC*/
#ifndef _DALVIK_MISC
#define _DALVIK_MISC
-#include "Inlines.h"
-
#include <stdio.h>
#include <sys/types.h>
#include <sys/time.h>
+#include "Inlines.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
/*
* Used to shut up the compiler when a parameter isn't used.
*/
const char* dvmPathToAbsolutePortion(const char* path);
+#ifdef __cplusplus
+}
+#endif
+
#endif /*_DALVIK_MISC*/
#ifndef _DALVIK_NATIVE
#define _DALVIK_NATIVE
+#ifdef __cplusplus
+extern "C" {
+#endif
+
/*
* Method description; equivalent to a JNI struct.
*/
void dvmLogNativeMethodExit(const Method* method, struct Thread* self,
const JValue retval);
+#ifdef __cplusplus
+}
+#endif
+
#endif /*_DALVIK_NATIVE*/
#ifndef _DALVIK_POINTERSET
#define _DALVIK_POINTERSET
+#ifdef __cplusplus
+extern "C" {
+#endif
+
struct PointerSet; /* private */
typedef struct PointerSet PointerSet;
*/
void dvmPointerSetDump(const PointerSet* pSet);
+#ifdef __cplusplus
+}
+#endif
+
#endif /*_DALVIK_POINTERSET*/
#include <stdio.h>
+#ifdef __cplusplus
+extern "C" {
+#endif
+
struct Thread; // extern
#define METHOD_ACTION(_method) (((unsigned int)(_method)) & METHOD_ACTION_MASK)
#define METHOD_COMBINE(_method, _action) ((_method) | (_action))
+#ifdef __cplusplus
+}
+#endif
+
#endif /*_DALVIK_PROFILE*/
#ifndef _DALVIK_PROPERTIES
#define _DALVIK_PROPERTIES
+#ifdef __cplusplus
+extern "C" {
+#endif
+
/*
* Initialization.
*/
bool dvmPropertiesStartup(void);
void dvmPropertiesShutdown(void);
+#ifdef __cplusplus
+}
+#endif
+
#endif /*_DALVIK_PROPERTIES*/
#ifndef _DALVIK_RAWDEXFILE
#define _DALVIK_RAWDEXFILE
+#ifdef __cplusplus
+extern "C" {
+#endif
+
/*
* Structure representing a "raw" DEX file, in its unswapped unoptimized
* state.
return pRawDexFile->cacheFileName;
}
+#ifdef __cplusplus
+}
+#endif
+
#endif /*_DALVIK_RAWDEXFILE*/
#ifndef _DALVIK_REFERENCETABLE
#define _DALVIK_REFERENCETABLE
+#ifdef __cplusplus
+extern "C" {
+#endif
+
/*
* Table definition.
*
void dvmDumpReferenceTableContents(Object* const* refs, size_t count,
const char* descr);
+#ifdef __cplusplus
+}
+#endif
+
#endif /*_DALVIK_REFERENCETABLE*/
#ifndef _DALVIK_SIGNALCATCHER
#define _DALVIK_SIGNALCATCHER
+#ifdef __cplusplus
+extern "C" {
+#endif
+
bool dvmSignalCatcherStartup(void);
void dvmSignalCatcherShutdown(void);
+#ifdef __cplusplus
+}
+#endif
+
#endif /*_DALVIK_SIGNALCATCHER*/
#ifndef _DALVIK_STDOUTCONVERTER
#define _DALVIK_STDOUTCONVERTER
+#ifdef __cplusplus
+extern "C" {
+#endif
+
bool dvmStdioConverterStartup(void);
void dvmStdioConverterShutdown(void);
+#ifdef __cplusplus
+}
+#endif
+
#endif /*_DALVIK_STDOUTCONVERTER*/
#ifndef _DALVIK_SYNC
#define _DALVIK_SYNC
+#ifdef __cplusplus
+extern "C" {
+#endif
+
/*
* Monitor shape field. Used to distinguish immediate thin locks from
* indirecting fat locks.
int dvmRelativeCondWait(pthread_cond_t* cond, pthread_mutex_t* mutex,
s8 msec, s4 nsec);
+#ifdef __cplusplus
+}
+#endif
+
#endif /*_DALVIK_SYNC*/
}
char* threadName = dvmGetThreadName(target);
- LOGD("threadid=%d: suspending daemon id=%d name='%s'\n",
+ LOGV("threadid=%d: suspending daemon id=%d name='%s'\n",
threadId, target->threadId, threadName);
free(threadName);
}
if (allSuspended) {
- LOGD("threadid=%d: all daemons have suspended\n", threadId);
+ LOGV("threadid=%d: all daemons have suspended\n", threadId);
break;
} else {
if (!complained) {
#include <errno.h>
#include <cutils/sched_policy.h>
+#ifdef __cplusplus
+extern "C" {
+#endif
#if defined(CHECK_MUTEX) && !defined(__USE_UNIX98)
/* glibc lacks this unless you #define __USE_UNIX98 */
void dvmSlayDaemons(void);
-#define kJniLocalRefMin 32
+#define kJniLocalRefMin 64
#define kJniLocalRefMax 512 /* arbitrary; should be plenty */
#define kInternalRefDefault 32 /* equally arbitrary */
#define kInternalRefMax 4096 /* mainly a sanity check */
*/
void dvmNukeThread(Thread* thread);
+#ifdef __cplusplus
+}
+#endif
+
#endif /*_DALVIK_THREAD*/
#ifndef _DALVIK_STRING
#define _DALVIK_STRING
+#ifdef __cplusplus
+extern "C" {
+#endif
+
/*
* (This is private to UtfString.c, but we cheat a bit and also use it
* for InlineNative.c. Not really worth creating a separate header.)
*/
int dvmHashcmpStrings(const void* vstrObj1, const void* vstrObj2);
+#ifdef __cplusplus
+}
+#endif
+
#endif /*_DALVIK_STRING*/
#include <stddef.h>
+#ifdef __cplusplus
+extern "C" {
+#endif
+
/*
* Initialization.
*/
*/
bool dvmIsHeapAddress(void *address);
+#ifdef __cplusplus
+}
+#endif
+
#endif /*_DALVIK_ALLOC_ALLOC*/
#ifndef _DALVIK_ALLOC_CARDTABLE
#define _DALVIK_ALLOC_CARDTABLE
+#ifdef __cplusplus
+extern "C" {
+#endif
+
#define GC_CARD_SHIFT 7
#define GC_CARD_SIZE (1 << GC_CARD_SHIFT)
#define GC_CARD_CLEAN 0
*/
void dvmVerifyCardTable(void);
+#ifdef __cplusplus
+}
+#endif
+
#endif /*_DALVIK_ALLOC_CARDTABLE*/
*/
#define HPSx_CHUNK_SIZE (16384 - 16)
-void dlmalloc_walk_heap(void(*)(const void*, size_t, const void*, size_t, void*),void*);
+extern "C" void dlmalloc_walk_heap(void(*)(const void*, size_t, const void*, size_t, void*),void*);
static void
walkHeap(bool merge, bool native)
#ifndef _DALVIK_ALLOC_DDMHEAP
#define _DALVIK_ALLOC_DDMHEAP
+#ifdef __cplusplus
+extern "C" {
+#endif
+
/*
* Sends the current heap info to the DDM server.
* Should be called after a GC when gcHeap->ddmHpifWhen
*/
void dvmDdmSendHeapSegments(bool shouldLock, bool native);
+#ifdef __cplusplus
+}
+#endif
+
#endif // _DALVIK_ALLOC_DDMHEAP
static const GcSpec kGcForMallocSpec = {
true, /* isPartial */
false, /* isConcurrent */
- PRESERVE,
+ true, /* doPreserve */
"GC_FOR_ALLOC"
};
static const GcSpec kGcConcurrentSpec = {
true, /* isPartial */
true, /* isConcurrent */
- PRESERVE,
+ true, /* doPreserve */
"GC_CONCURRENT"
};
static const GcSpec kGcExplicitSpec = {
false, /* isPartial */
true, /* isConcurrent */
- PRESERVE,
+ true, /* doPreserve */
"GC_EXPLICIT"
};
static const GcSpec kGcBeforeOomSpec = {
false, /* isPartial */
false, /* isConcurrent */
- CLEAR,
+ false, /* doPreserve */
"GC_BEFORE_OOM"
};
* weakly-reachable objects discovered while tracing.
*/
dvmHeapProcessReferences(&gcHeap->softReferences,
- spec->softReferencePolicy == CLEAR,
+ spec->doPreserve == false,
&gcHeap->weakReferences,
&gcHeap->finalizerReferences,
&gcHeap->phantomReferences);
/* If true, the trace is run concurrently with the mutator. */
bool isConcurrent;
/* Toggles for the soft reference clearing policy. */
- enum { CLEAR, PRESERVE } softReferencePolicy;
+ bool doPreserve;
/* A name for this garbage collection mode. */
const char *reason;
} GcSpec;
#include <limits.h>
#include <stdint.h>
+#ifdef __cplusplus
+extern "C" {
+#endif
+
#define HB_OBJECT_ALIGNMENT 8
#define HB_BITS_PER_WORD (sizeof(unsigned long) * CHAR_BIT)
uintptr_t base, uintptr_t max,
BitmapSweepCallback *callback, void *callbackArg);
+#ifdef __cplusplus
+}
+#endif
+
#endif /* _DALVIK_HEAP_BITMAP */
#ifndef _DALVIK_HEAPDEBUG
#define _DALVIK_HEAPDEBUG
+#ifdef __cplusplus
+extern "C" {
+#endif
+
typedef enum HeapDebugInfoType {
kVirtualHeapSize = 0,
kNativeHeapSize = 1,
*/
int dvmGetHeapDebugInfo(HeapDebugInfoType info);
+#ifdef __cplusplus
+}
+#endif
+
#endif // _DALVIK_HEAPDEBUG
#define LOGD_HEAP(...) LOG(LOG_DEBUG, HEAP_LOG_TAG, __VA_ARGS__)
#endif
#define LOGI_HEAP(...) \
- (!gDvm.zygote ? LOG(LOG_INFO, HEAP_LOG_TAG, __VA_ARGS__) : (void)0)
+ do { \
+ if (!gDvm.zygote) { LOG(LOG_INFO, HEAP_LOG_TAG, __VA_ARGS__); } \
+ } while (0)
+
#define LOGW_HEAP(...) LOG(LOG_WARN, HEAP_LOG_TAG, __VA_ARGS__)
#define LOGE_HEAP(...) LOG(LOG_ERROR, HEAP_LOG_TAG, __VA_ARGS__)
*/
#include <cutils/mspace.h>
-#include <stdint.h> // for SIZE_MAX
+#include <stdint.h>
#include <sys/mman.h>
#include <errno.h>
+#define SIZE_MAX UINT_MAX // TODO: get SIZE_MAX from stdint.h
+
#include "Dalvik.h"
#include "alloc/Heap.h"
#include "alloc/HeapInternal.h"
#include "alloc/HeapBitmapInlines.h"
// TODO: find a real header file for these.
-extern int dlmalloc_trim(size_t);
-extern void dlmalloc_walk_free_pages(void(*)(void*, void*, void*), void*);
+extern "C" int dlmalloc_trim(size_t);
+extern "C" void dlmalloc_walk_free_pages(void(*)(void*, void*, void*), void*);
static void snapIdealFootprint(void);
static void setIdealFootprint(size_t max);
* marking. Marks white objects but does not push them on the mark
* stack.
*/
-static void rootMarkObjectVisitor(void *addr, RootType type, u4 thread,
+static void rootMarkObjectVisitor(void *addr, u4 thread, RootType type,
void *arg)
{
Object *obj;
* Callback applied to root references during root remarking. Marks
* white objects and pushes them on the mark stack.
*/
-static void rootReMarkObjectVisitor(void *addr, RootType type, u4 thread,
+static void rootReMarkObjectVisitor(void *addr, u4 thread, RootType type,
void *arg)
{
Object *obj;
markObject((const Object *)obj->clazz, ctx);
if (IS_CLASS_FLAG_SET(obj->clazz, CLASS_ISOBJECTARRAY)) {
const ArrayObject *array = (const ArrayObject *)obj;
- const Object **contents = (const Object **)array->contents;
+ const Object **contents = (const Object **)(void *)array->contents;
size_t i;
for (i = 0; i < array->length; ++i) {
markObject(contents[i], ctx);
#include "Dalvik.h"
+#ifdef __cplusplus
+extern "C" {
+#endif
+
typedef enum {
ROOT_UNKNOWN = 0,
ROOT_JNI_GLOBAL,
*/
void dvmVisitRoots(RootVisitor *visitor, void *arg);
+#ifdef __cplusplus
+}
+#endif
+
#endif /* _DALVIK_ALLOC_VISIT */
(*visitor)(&obj->clazz, arg);
if (IS_CLASS_FLAG_SET(obj->clazz, CLASS_ISOBJECTARRAY)) {
ArrayObject *array = (ArrayObject *)obj;
- Object **contents = (Object **)array->contents;
+ Object **contents = (Object **)(void *)array->contents;
size_t i;
for (i = 0; i < array->length; ++i) {
(*visitor)(&contents[i], arg);
#ifndef _DALVIK_ALLOC_WRITEBARRIER
#define _DALVIK_ALLOC_WRITEBARRIER
+#ifdef __cplusplus
+extern "C" {
+#endif
+
/*
* Note writes to the heap. These functions must be called if a field
* of an Object in the heap changes, and before any GC safe-point. The
dvmMarkCard((Object *)obj);
}
+#ifdef __cplusplus
+}
+#endif
+
#endif /* _DALVIK_ALLOC_WRITEBARRIER */
#include "analysis/VerifySubs.h"
#include "analysis/VfyBasicBlock.h"
+#ifdef __cplusplus
+extern "C" {
+#endif
/*
* Enumeration for register type values. The "hi" piece of a 64-bit value
*/
bool dvmVerifyCodeFlow(VerifierData* vdata);
+#ifdef __cplusplus
+}
+#endif
+
#endif /*_DALVIK_CODEVERIFY*/
#include "analysis/VerifySubs.h"
#include "analysis/CodeVerify.h"
+#ifdef __cplusplus
+extern "C" {
+#endif
+
/*
* Format enumeration for RegisterMap data area.
*/
/* dump stats gathered during register map creation process */
void dvmRegisterMapDumpStats(void);
+#ifdef __cplusplus
+}
+#endif
+
#endif /*_DALVIK_REGISTERMAP*/
* limitations under the License.
*/
-#include <Thread.h>
-#include <setjmp.h>
-
#ifndef _DALVIK_VM_COMPILER
#define _DALVIK_VM_COMPILER
+#include <setjmp.h>
+#include "Thread.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
/*
* Uncomment the following to enable JIT signature breakpoint
* #define SIGNATURE_BREAKPOINT
JitInstructionSetType dvmCompilerGetInterpretTemplateSet();
u8 dvmGetRegResourceMask(int reg);
void dvmDumpCFG(struct CompilationUnit *cUnit, const char *dirPrefix);
+
+#ifdef __cplusplus
+}
+#endif
+
#endif /* _DALVIK_VM_COMPILER */
bool *fpDef;
} SSARepresentation;
+/*
+ * An induction variable is represented by "m*i + c", where i is a basic
+ * induction variable.
+ */
typedef struct InductionVariableInfo {
int ssaReg;
int basicSSAReg;
- int m;
- int c;
- int inc;
+ int m; // multiplier
+ int c; // constant
+ int inc; // loop incriment
} InductionVariableInfo;
typedef struct ArrayAccessInfo {
}
}
+/* Used for normalized loop exit condition checks */
+static Opcode negateOpcode(Opcode opcode)
+{
+ switch (opcode) {
+ /* reg/reg cmp */
+ case OP_IF_EQ:
+ return OP_IF_NE;
+ case OP_IF_NE:
+ return OP_IF_EQ;
+ case OP_IF_LT:
+ return OP_IF_GE;
+ case OP_IF_GE:
+ return OP_IF_LT;
+ case OP_IF_GT:
+ return OP_IF_LE;
+ case OP_IF_LE:
+ return OP_IF_GT;
+ /* reg/zero cmp */
+ case OP_IF_EQZ:
+ return OP_IF_NEZ;
+ case OP_IF_NEZ:
+ return OP_IF_EQZ;
+ case OP_IF_LTZ:
+ return OP_IF_GEZ;
+ case OP_IF_GEZ:
+ return OP_IF_LTZ;
+ case OP_IF_GTZ:
+ return OP_IF_LEZ;
+ case OP_IF_LEZ:
+ return OP_IF_GTZ;
+ default:
+ LOGE("opcode %d cannot be negated", opcode);
+ dvmAbort();
+ break;
+ }
+ return -1;
+}
+
/*
* A loop is considered optimizable if:
- * 1) It has one basic induction variable
- * 2) The loop back branch compares the BIV with a constant
- * 3) If it is a count-up loop, the condition is GE/GT, or LE/LT/LEZ/LTZ for
- * a count-down loop.
+ * 1) It has one basic induction variable.
+ * 2) The loop back branch compares the BIV with a constant.
+ * 3) We need to normalize the loop exit condition so that the loop is exited
+ * via the taken path.
+ * 4) If it is a count-up loop, the condition is GE/GT. Otherwise it is
+ * LE/LT/LEZ/LTZ for a count-down loop.
*
- * Return false if the loop is not optimizable.
+ * Return false for loops that fail the above tests.
*/
static bool isSimpleCountedLoop(CompilationUnit *cUnit)
{
unsigned int i;
- BasicBlock *loopBranch = findPredecessorBlock(cUnit,
- cUnit->entryBlock->fallThrough);
+ BasicBlock *loopBackBlock = cUnit->entryBlock->fallThrough;
LoopAnalysis *loopAnalysis = cUnit->loopAnalysis;
if (loopAnalysis->numBasicIV != 1) return false;
}
}
- MIR *branch = loopBranch->lastMIRInsn;
+ /* Find the block that ends with a branch to exit the loop */
+ while (true) {
+ loopBackBlock = findPredecessorBlock(cUnit, loopBackBlock);
+ /* Loop structure not recognized as counted blocks */
+ if (loopBackBlock == NULL) {
+ return false;
+ }
+ /* Unconditional goto - continue to trace up the predecessor chain */
+ if (loopBackBlock->taken == NULL) {
+ continue;
+ }
+ break;
+ }
+
+ MIR *branch = loopBackBlock->lastMIRInsn;
Opcode opcode = branch->dalvikInsn.opcode;
- /*
- * If the instruction is not accessing the IV as the first operand, return
- * false.
- */
- if (branch->ssaRep->numUses == 0 || branch->ssaRep->numDefs != 0) {
+ /* Last instruction is not a conditional branch - bail */
+ if (dexGetFlagsFromOpcode(opcode) != (kInstrCanContinue|kInstrCanBranch)) {
return false;
}
- /*
- * If the first operand of the comparison is not the basic induction
- * variable, return false.
- */
- if (branch->ssaRep->uses[0] != loopAnalysis->ssaBIV) {
- return false;
- }
+ int endSSAReg;
+ int endDalvikReg;
- if (loopAnalysis->isCountUpLoop) {
- /*
- * If the condition op is not > or >=, this is not an optimization
- * candidate.
- */
- if (opcode != OP_IF_GT && opcode != OP_IF_GE) {
+ /* reg/reg comparison */
+ if (branch->ssaRep->numUses == 2) {
+ if (branch->ssaRep->uses[0] == loopAnalysis->ssaBIV) {
+ endSSAReg = branch->ssaRep->uses[1];
+ } else if (branch->ssaRep->uses[1] == loopAnalysis->ssaBIV) {
+ endSSAReg = branch->ssaRep->uses[0];
+ opcode = negateOpcode(opcode);
+ } else {
return false;
}
+ endDalvikReg = dvmConvertSSARegToDalvik(cUnit, endSSAReg);
/*
* If the comparison is not between the BIV and a loop invariant,
- * return false. endReg is loop invariant if one of the following is
- * true:
+ * return false. endDalvikReg is loop invariant if one of the
+ * following is true:
* - It is not defined in the loop (ie DECODE_SUB returns 0)
* - It is reloaded with a constant
*/
- int endReg = dvmConvertSSARegToDalvik(cUnit, branch->ssaRep->uses[1]);
- if (DECODE_SUB(endReg) != 0 &&
- !dvmIsBitSet(cUnit->isConstantV, branch->ssaRep->uses[1])) {
+ if ((DECODE_SUB(endDalvikReg) != 0) &&
+ !dvmIsBitSet(cUnit->isConstantV, endSSAReg)) {
return false;
}
- loopAnalysis->endConditionReg = DECODE_REG(endReg);
+ /* Compare against zero */
+ } else if (branch->ssaRep->numUses == 1) {
+ if (branch->ssaRep->uses[0] == loopAnalysis->ssaBIV) {
+ /* Keep the compiler happy */
+ endDalvikReg = -1;
+ } else {
+ return false;
+ }
+ } else {
+ return false;
+ }
+
+ /* Normalize the loop exit check as "if (iv op end) exit;" */
+ if (loopBackBlock->taken->blockType == kDalvikByteCode) {
+ opcode = negateOpcode(opcode);
+ }
+
+ if (loopAnalysis->isCountUpLoop) {
+ /*
+ * If the normalized condition op is not > or >=, this is not an
+ * optimization candidate.
+ */
+ switch (opcode) {
+ case OP_IF_GT:
+ case OP_IF_GE:
+ break;
+ default:
+ return false;
+ }
+ loopAnalysis->endConditionReg = DECODE_REG(endDalvikReg);
} else {
/*
- * If the condition op is not < or <=, this is not an optimization
- * candidate.
+ * If the normalized condition op is not < or <=, this is not an
+ * optimization candidate.
*/
- if (opcode == OP_IF_LT || opcode == OP_IF_LE) {
- /*
- * If the comparison is not between the BIV and a loop invariant,
- * return false.
- */
- int endReg = dvmConvertSSARegToDalvik(cUnit,
- branch->ssaRep->uses[1]);
-
- if (DECODE_SUB(endReg) != 0) {
+ switch (opcode) {
+ case OP_IF_LT:
+ case OP_IF_LE:
+ loopAnalysis->endConditionReg = DECODE_REG(endDalvikReg);
+ break;
+ case OP_IF_LTZ:
+ case OP_IF_LEZ:
+ break;
+ default:
return false;
- }
- loopAnalysis->endConditionReg = DECODE_REG(endReg);
- } else if (opcode != OP_IF_LTZ && opcode != OP_IF_LEZ) {
- return false;
}
}
+ /*
+ * Remember the normalized opcode, which will be used to determine the end
+ * value used for the yanked range checks.
+ */
loopAnalysis->loopBranchOpcode = opcode;
return true;
}
dvmCompilerAbort(cUnit);
}
}
-
}
}
#include "Dalvik.h"
+#ifdef __cplusplus
+extern "C" {
+#endif
+
#define HPROF_ID_SIZE (sizeof (u4))
#define UNIQUE_ERROR() \
/*
- * HprofString.c functions
+ * HprofString.cpp functions
*/
hprof_string_id hprofLookupStringId(const char *str);
/*
- * HprofClass.c functions
+ * HprofClass.cpp functions
*/
hprof_class_object_id hprofLookupClassId(const ClassObject *clazz);
/*
- * HprofHeap.c functions
+ * HprofHeap.cpp functions
*/
int hprofStartHeapDump(hprof_context_t *ctx);
int hprofDumpHeapObject(hprof_context_t *ctx, const Object *obj);
/*
- * HprofOutput.c functions
+ * HprofOutput.cpp functions
*/
void hprofContextInit(hprof_context_t *ctx, char *fileName, int fd,
hprofAddU4ListToRecord((rec), (const u4 *)(values), (numValues))
/*
- * Hprof.c functions
+ * Hprof.cpp functions
*/
hprof_context_t* hprofStartup(const char *outputFileName, int fd,
bool directToDdms);
bool hprofShutdown(hprof_context_t *ctx);
void hprofFreeContext(hprof_context_t *ctx);
-
-/*
- * HprofVisit.c functions
- */
-
int hprofDumpHeap(const char* fileName, int fd, bool directToDdms);
+#ifdef __cplusplus
+}
+#endif
+
#endif // _DALVIK_HPROF_HPROF
{
hprof_record_t *rec = &ctx->curRec;
int err;
- hprof_heap_tag_t heapTag = ctx->gcScanState;
+ hprof_heap_tag_t heapTag = (hprof_heap_tag_t)ctx->gcScanState;
if (heapTag == 0) {
return 0;
/* Dump the elements, which are always objects or NULL.
*/
hprofAddIdListToRecord(rec,
- (const hprof_object_id *)aobj->contents, length);
+ (const hprof_object_id *)(void *)aobj->contents, length);
} else {
hprof_basic_type t;
size_t size;
hprofAddU1ListToRecord(rec, (const u1 *)aobj->contents,
length);
} else if (size == 2) {
- hprofAddU2ListToRecord(rec, (const u2 *)aobj->contents,
+ hprofAddU2ListToRecord(rec, (const u2 *)(void *)aobj->contents,
length);
} else if (size == 4) {
- hprofAddU4ListToRecord(rec, (const u4 *)aobj->contents,
+ hprofAddU4ListToRecord(rec, (const u4 *)(void *)aobj->contents,
length);
} else if (size == 8) {
hprofAddU8ListToRecord(rec, (const u8 *)aobj->contents,
#include "InterpDefs.h"
#include "mterp/common/jit-config.h"
+#ifdef __cplusplus
+extern "C" {
+#endif
+
#define JIT_MAX_TRACE_LEN 100
#if defined (WITH_SELF_VERIFICATION)
void dvmJitUpdateThreadStateAll(void);
void dvmJitResumeTranslation(Thread* self, const u2* pc, const u4* fp);
+#ifdef __cplusplus
+}
+#endif
+
#endif /*_DALVIK_INTERP_JIT*/
#include "jni.h"
#include <stdarg.h>
+#ifdef __cplusplus
+extern "C" {
+#endif
/*
Stack layout
void dvmDumpThreadStack(const DebugOutputTarget* target, Thread* thread);
void dvmDumpRunningThreadStack(const DebugOutputTarget* target, Thread* thread);
+#ifdef __cplusplus
+}
+#endif
+
#endif /*_DALVIK_INTERP_STACK*/
#ifndef _DALVIK_NATIVE_INTERNALNATIVE
#define _DALVIK_NATIVE_INTERNALNATIVE
+#ifdef __cplusplus
+extern "C" {
+#endif
+
/*
* Some setup for internal native functions.
*/
/* exception-throwing stub for abstract methods (DalvikNativeFunc) */
void dvmAbstractMethodStub(const u4* args, JValue* pResult);
+#ifdef __cplusplus
+}
+#endif
+
#endif /*_DALVIK_NATIVE_INTERNALNATIVE*/
#ifndef _DALVIK_NATIVE_INTERNALNATIVEPRIV
#define _DALVIK_NATIVE_INTERNALNATIVEPRIV
+#ifdef __cplusplus
+extern "C" {
+#endif
+
/*
* Return macros. Note we use "->i" instead of "->z" for boolean; this
* is because the interpreter expects everything to be a 32-bit value.
extern const DalvikNativeMethod dvm_org_apache_harmony_dalvik_NativeTestTarget[];
extern const DalvikNativeMethod dvm_sun_misc_Unsafe[];
+#ifdef __cplusplus
+}
+#endif
+
#endif /*_DALVIK_NATIVE_INTERNALNATIVEPRIV*/
#ifndef _DALVIK_OO_ACCESSCHECK
#define _DALVIK_OO_ACCESSCHECK
+#ifdef __cplusplus
+extern "C" {
+#endif
+
/*
* Determine whether the "accessFrom" class is allowed to get at "clazz".
*/
*/
bool dvmInSamePackage(const ClassObject* class1, const ClassObject* class2);
+#ifdef __cplusplus
+}
+#endif
+
#endif /*_DALVIK_OO_ACCESSCHECK*/
#ifndef _DALVIK_OO_ARRAY
#define _DALVIK_OO_ARRAY
+#ifdef __cplusplus
+extern "C" {
+#endif
+
/* width of an object reference, for arrays of objects */
#define kObjectArrayRefWidth sizeof(Object*)
*/
size_t dvmArrayClassElementWidth(const ClassObject* clazz);
+#ifdef __cplusplus
+}
+#endif
+
#endif /*_DALVIK_OO_ARRAY*/
#ifndef _DALVIK_OO_CLASS
#define _DALVIK_OO_CLASS
+#ifdef __cplusplus
+extern "C" {
+#endif
+
/*
* The classpath and bootclasspath differ in that only the latter is
* consulted when looking for classes needed by the VM. When searching
*/
size_t dvmClassObjectSize(const ClassObject *clazz);
+#ifdef __cplusplus
+}
+#endif
+
#endif /*_DALVIK_OO_CLASS*/
#ifndef _DALVIK_OO_OBJECT
#define _DALVIK_OO_OBJECT
-#include <Atomic.h>
-
#include <stddef.h>
+#include "Atomic.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
/* fwd decl */
struct DataObject;
/* debugging */
void dvmDumpObject(const Object* obj);
+#ifdef __cplusplus
+}
+#endif
+
#endif /*_DALVIK_OO_OBJECT*/
#ifndef _DALVIK_OO_OBJECTINLINES
#define _DALVIK_OO_OBJECTINLINES
+#ifdef __cplusplus
+extern "C" {
+#endif
+
/*
* Store a single value in the array, and if the value isn't null,
* note in the write barrier.
}
}
+#ifdef __cplusplus
+}
+#endif
+
#endif /*_DALVIK_OO_OBJECTINLINES*/
#ifndef _DALVIK_OO_RESOLVE
#define _DALVIK_OO_RESOLVE
+#ifdef __cplusplus
+extern "C" {
+#endif
+
/*
* "Direct" and "virtual" methods are stored independently. The type of call
* used to invoke the method determines which list we search, and whether
*/
const char* dvmMethodTypeStr(MethodType methodType);
+#ifdef __cplusplus
+}
+#endif
+
#endif /*_DALVIK_OO_RESOLVE*/
#ifndef _DALVIK_OO_TYPECHECK
#define _DALVIK_OO_TYPECHECK
+#ifdef __cplusplus
+extern "C" {
+#endif
+
/* VM startup/shutdown */
bool dvmInstanceofStartup(void);
void dvmInstanceofShutdown(void);
bool dvmCanPutArrayElement(const ClassObject* elemClass,
const ClassObject* arrayClass);
+#ifdef __cplusplus
+}
+#endif
+
#endif /*_DALVIK_OO_TYPECHECK*/