Permalink
Browse files

Revert "Revert "Upgrade to dlmalloc 2.8.5.""

This reverts commit 729eebb.
  • Loading branch information...
1 parent a78e89c commit 808a7c0e7e39b7ca3c7db1366e6e4089166052bb @captain5050 captain5050 committed Aug 28, 2012
Showing with 317 additions and 202 deletions.
  1. +1 −0 vm/Dvm.mk
  2. +2 −3 vm/alloc/Copying.cpp
  3. +116 −84 vm/alloc/DdmHeap.cpp
  4. +51 −0 vm/alloc/DlMalloc.cpp
  5. +42 −0 vm/alloc/DlMalloc.h
  6. +0 −12 vm/alloc/Heap.cpp
  7. +103 −99 vm/alloc/HeapSource.cpp
  8. +2 −4 vm/alloc/HeapSource.h
View
@@ -199,6 +199,7 @@ ifeq ($(WITH_COPYING_GC),true)
alloc/Copying.cpp.arm
else
LOCAL_SRC_FILES += \
+ alloc/DlMalloc.cpp \
alloc/HeapSource.cpp \
alloc/MarkSweep.cpp.arm
endif
View
@@ -731,9 +731,8 @@ void dvmHeapSourceGrowForUtilization()
/* do nothing */
}
-void dvmHeapSourceWalk(void (*callback)(const void *chunkptr, size_t chunklen,
- const void *userptr, size_t userlen,
- void *arg),
+void dvmHeapSourceWalk(void(*callback)(void* start, void* end,
+ size_t used_bytes, void* arg),
void *arg)
{
assert(!"implemented");
View
@@ -23,6 +23,7 @@
#include "alloc/Heap.h"
#include "alloc/HeapInternal.h"
#include "alloc/DdmHeap.h"
+#include "alloc/DlMalloc.h"
#include "alloc/HeapSource.h"
#define DEFAULT_HEAP_ID 1
@@ -173,6 +174,7 @@ enum HpsgKind {
((u1)((((kind) & 0x7) << 3) | ((solidity) & 0x7)))
struct HeapChunkContext {
+ void* startOfNextMemoryChunk;
u1 *buf;
u1 *p;
u1 *pieceLenField;
@@ -205,36 +207,25 @@ static void flush_hpsg_chunk(HeapChunkContext *ctx)
ctx->pieceLenField = NULL;
}
-static void heap_chunk_callback(const void *chunkptr, size_t chunklen,
- const void *userptr, size_t userlen, void *arg)
-{
- HeapChunkContext *ctx = (HeapChunkContext *)arg;
- u1 state;
-
- UNUSED_PARAMETER(userlen);
-
- assert((chunklen & (ALLOCATION_UNIT_SIZE-1)) == 0);
-
+static void append_chunk(HeapChunkContext *ctx, u1 state, void* ptr, size_t length) {
/* Make sure there's enough room left in the buffer.
* We need to use two bytes for every fractional 256
- * allocation units used by the chunk.
+ * allocation units used by the chunk and 17 bytes for
+ * any header.
*/
{
- size_t needed = (((chunklen/ALLOCATION_UNIT_SIZE + 255) / 256) * 2);
+ size_t needed = (((length/ALLOCATION_UNIT_SIZE + 255) / 256) * 2) + 17;
size_t bytesLeft = ctx->bufLen - (size_t)(ctx->p - ctx->buf);
if (bytesLeft < needed) {
flush_hpsg_chunk(ctx);
}
-
bytesLeft = ctx->bufLen - (size_t)(ctx->p - ctx->buf);
if (bytesLeft < needed) {
- ALOGW("chunk is too big to transmit (chunklen=%zd, %zd bytes)",
- chunklen, needed);
+ ALOGW("chunk is too big to transmit (length=%zd, %zd bytes)",
+ length, needed);
return;
}
}
-
-//TODO: notice when there's a gap and start a new heap, or at least a new range.
if (ctx->needHeader) {
/*
* Start a new HPSx chunk.
@@ -247,7 +238,7 @@ static void heap_chunk_callback(const void *chunkptr, size_t chunklen,
*ctx->p++ = 8;
/* [u4]: virtual address of segment start */
- set4BE(ctx->p, (uintptr_t)chunkptr); ctx->p += 4;
+ set4BE(ctx->p, (uintptr_t)ptr); ctx->p += 4;
/* [u4]: offset of this piece (relative to the virtual address) */
set4BE(ctx->p, 0); ctx->p += 4;
@@ -261,80 +252,123 @@ static void heap_chunk_callback(const void *chunkptr, size_t chunklen,
ctx->needHeader = false;
}
+ /* Write out the chunk description.
+ */
+ length /= ALLOCATION_UNIT_SIZE; // convert to allocation units
+ ctx->totalAllocationUnits += length;
+ while (length > 256) {
+ *ctx->p++ = state | HPSG_PARTIAL;
+ *ctx->p++ = 255; // length - 1
+ length -= 256;
+ }
+ *ctx->p++ = state;
+ *ctx->p++ = length - 1;
+}
+
+/*
+ * Called by dlmalloc_inspect_all. If used_bytes != 0 then start is
+ * the start of a malloc-ed piece of memory of size used_bytes. If
+ * start is 0 then start is the beginning of any free space not
+ * including dlmalloc's book keeping and end the start of the next
+ * dlmalloc chunk. Regions purely containing book keeping don't
+ * callback.
+ */
+static void heap_chunk_callback(void* start, void* end, size_t used_bytes,
+ void* arg)
+{
+ u1 state;
+ HeapChunkContext *ctx = (HeapChunkContext *)arg;
+ UNUSED_PARAMETER(end);
- /* Determine the type of this chunk.
+ if (used_bytes == 0) {
+ if (start == NULL) {
+ // Reset for start of new heap.
+ ctx->startOfNextMemoryChunk = NULL;
+ flush_hpsg_chunk(ctx);
+ }
+ // Only process in use memory so that free region information
+ // also includes dlmalloc book keeping.
+ return;
+ }
+
+ /* If we're looking at the native heap, we'll just return
+ * (SOLIDITY_HARD, KIND_NATIVE) for all allocated chunks
*/
- if (userptr == NULL) {
- /* It's a free chunk.
- */
- state = HPSG_STATE(SOLIDITY_FREE, 0);
- } else {
- const Object *obj = (const Object *)userptr;
- /* If we're looking at the native heap, we'll just return
- * (SOLIDITY_HARD, KIND_NATIVE) for all allocated chunks
- */
- bool native = ctx->type == CHUNK_TYPE("NHSG");
+ bool native = ctx->type == CHUNK_TYPE("NHSG");
+
+ if (ctx->startOfNextMemoryChunk != NULL) {
+ // Transmit any pending free memory. Native free memory of
+ // over kMaxFreeLen could be because of the use of mmaps, so
+ // don't report. If not free memory then start a new segment.
+ bool flush = true;
+ if (start > ctx->startOfNextMemoryChunk) {
+ const size_t kMaxFreeLen = 2 * SYSTEM_PAGE_SIZE;
+ void* freeStart = ctx->startOfNextMemoryChunk;
+ void* freeEnd = start;
+ size_t freeLen = (char*)freeEnd - (char*)freeStart;
+ if (!native || freeLen < kMaxFreeLen) {
+ append_chunk(ctx, HPSG_STATE(SOLIDITY_FREE, 0),
+ freeStart, freeLen);
+ flush = false;
+ }
+ }
+ if (flush) {
+ ctx->startOfNextMemoryChunk = NULL;
+ flush_hpsg_chunk(ctx);
+ }
+ }
+ const Object *obj = (const Object *)start;
- /* It's an allocated chunk. Figure out what it is.
- */
+ /* It's an allocated chunk. Figure out what it is.
+ */
//TODO: if ctx.merge, see if this chunk is different from the last chunk.
// If it's the same, we should combine them.
- if (!native && dvmIsValidObject(obj)) {
- ClassObject *clazz = obj->clazz;
- if (clazz == NULL) {
- /* The object was probably just created
- * but hasn't been initialized yet.
- */
- state = HPSG_STATE(SOLIDITY_HARD, KIND_OBJECT);
- } else if (dvmIsTheClassClass(clazz)) {
- state = HPSG_STATE(SOLIDITY_HARD, KIND_CLASS_OBJECT);
- } else if (IS_CLASS_FLAG_SET(clazz, CLASS_ISARRAY)) {
- if (IS_CLASS_FLAG_SET(clazz, CLASS_ISOBJECTARRAY)) {
+ if (!native && dvmIsValidObject(obj)) {
+ ClassObject *clazz = obj->clazz;
+ if (clazz == NULL) {
+ /* The object was probably just created
+ * but hasn't been initialized yet.
+ */
+ state = HPSG_STATE(SOLIDITY_HARD, KIND_OBJECT);
+ } else if (dvmIsTheClassClass(clazz)) {
+ state = HPSG_STATE(SOLIDITY_HARD, KIND_CLASS_OBJECT);
+ } else if (IS_CLASS_FLAG_SET(clazz, CLASS_ISARRAY)) {
+ if (IS_CLASS_FLAG_SET(clazz, CLASS_ISOBJECTARRAY)) {
+ state = HPSG_STATE(SOLIDITY_HARD, KIND_ARRAY_4);
+ } else {
+ switch (clazz->elementClass->primitiveType) {
+ case PRIM_BOOLEAN:
+ case PRIM_BYTE:
+ state = HPSG_STATE(SOLIDITY_HARD, KIND_ARRAY_1);
+ break;
+ case PRIM_CHAR:
+ case PRIM_SHORT:
+ state = HPSG_STATE(SOLIDITY_HARD, KIND_ARRAY_2);
+ break;
+ case PRIM_INT:
+ case PRIM_FLOAT:
state = HPSG_STATE(SOLIDITY_HARD, KIND_ARRAY_4);
- } else {
- switch (clazz->elementClass->primitiveType) {
- case PRIM_BOOLEAN:
- case PRIM_BYTE:
- state = HPSG_STATE(SOLIDITY_HARD, KIND_ARRAY_1);
- break;
- case PRIM_CHAR:
- case PRIM_SHORT:
- state = HPSG_STATE(SOLIDITY_HARD, KIND_ARRAY_2);
- break;
- case PRIM_INT:
- case PRIM_FLOAT:
- state = HPSG_STATE(SOLIDITY_HARD, KIND_ARRAY_4);
- break;
- case PRIM_DOUBLE:
- case PRIM_LONG:
- state = HPSG_STATE(SOLIDITY_HARD, KIND_ARRAY_8);
- break;
- default:
- assert(!"Unknown GC heap object type");
- state = HPSG_STATE(SOLIDITY_HARD, KIND_UNKNOWN);
- break;
- }
+ break;
+ case PRIM_DOUBLE:
+ case PRIM_LONG:
+ state = HPSG_STATE(SOLIDITY_HARD, KIND_ARRAY_8);
+ break;
+ default:
+ assert(!"Unknown GC heap object type");
+ state = HPSG_STATE(SOLIDITY_HARD, KIND_UNKNOWN);
+ break;
}
- } else {
- state = HPSG_STATE(SOLIDITY_HARD, KIND_OBJECT);
}
} else {
- obj = NULL; // it's not actually an object
- state = HPSG_STATE(SOLIDITY_HARD, KIND_NATIVE);
+ state = HPSG_STATE(SOLIDITY_HARD, KIND_OBJECT);
}
+ } else {
+ obj = NULL; // it's not actually an object
+ state = HPSG_STATE(SOLIDITY_HARD, KIND_NATIVE);
}
-
- /* Write out the chunk description.
- */
- chunklen /= ALLOCATION_UNIT_SIZE; // convert to allocation units
- ctx->totalAllocationUnits += chunklen;
- while (chunklen > 256) {
- *ctx->p++ = state | HPSG_PARTIAL;
- *ctx->p++ = 255; // length - 1
- chunklen -= 256;
- }
- *ctx->p++ = state;
- *ctx->p++ = chunklen - 1;
+ append_chunk(ctx, state, start, used_bytes + HEAP_SOURCE_CHUNK_OVERHEAD);
+ ctx->startOfNextMemoryChunk =
+ (char*)start + used_bytes + HEAP_SOURCE_CHUNK_OVERHEAD;
}
enum HpsgWhen {
@@ -353,8 +387,6 @@ enum HpsgWhat {
*/
#define HPSx_CHUNK_SIZE (16384 - 16)
-extern "C" void dlmalloc_walk_heap(void(*)(const void*, size_t, const void*, size_t, void*),void*);
-
static void walkHeap(bool merge, bool native)
{
HeapChunkContext ctx;
@@ -380,7 +412,7 @@ static void walkHeap(bool merge, bool native)
ctx.p = ctx.buf;
ctx.needHeader = true;
if (native) {
- dlmalloc_walk_heap(heap_chunk_callback, (void *)&ctx);
+ dlmalloc_inspect_all(heap_chunk_callback, (void*)&ctx);
} else {
dvmHeapSourceWalk(heap_chunk_callback, (void *)&ctx);
}
View
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "DlMalloc.h"
+
+#include <stdint.h>
+#include "Common.h"
+
+/* Dalvik specific morecore implementation defined in HeapSource.cpp. */
+#define MORECORE(x) dvmHeapSourceMorecore(m, x)
+extern void* dvmHeapSourceMorecore(void* mspace, intptr_t increment);
+
+/* Custom heap error handling. */
+#define PROCEED_ON_ERROR 0
+static void heap_error(const char* msg, const char* function, void* p);
+#define CORRUPTION_ERROR_ACTION(m) \
+ heap_error("HEAP MEMORY CORRUPTION", __FUNCTION__, NULL)
+#define USAGE_ERROR_ACTION(m,p) \
+ heap_error("ARGUMENT IS INVALID HEAP ADDRESS", __FUNCTION__, p)
+
+/*
+ * Ugly inclusion of C file so that Dalvik specific #defines configure
+ * dlmalloc for our use for mspaces (regular dlmalloc is still declared
+ * in bionic).
+ */
+#pragma GCC diagnostic ignored "-Wempty-body"
+#pragma GCC diagnostic ignored "-Wstrict-aliasing"
+#include "../../../bionic/libc/upstream-dlmalloc/malloc.c"
+#pragma GCC diagnostic warning "-Wstrict-aliasing"
+#pragma GCC diagnostic warning "-Wempty-body"
+
+
+static void heap_error(const char* msg, const char* function, void* p) {
+ ALOG(LOG_FATAL, LOG_TAG, "@@@ ABORTING: DALVIK: %s IN %s addr=%p", msg,
+ function, p);
+ /* So that we can get a memory dump around p */
+ *((int **) 0xdeadbaad) = (int *) p;
+}
View
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef DALVIK_VM_ALLOC_DLMALLOC_H_
+#define DALVIK_VM_ALLOC_DLMALLOC_H_
+
+/* Configure dlmalloc for mspaces. */
+#define HAVE_MMAP 0
+#define HAVE_MREMAP 0
+#define HAVE_MORECORE 1
+#define MSPACES 1
+#define NO_MALLINFO 1
+#define ONLY_MSPACES 1
+#define USE_DL_PREFIX 1
+#define MALLOC_INSPECT_ALL 1
+
+/* Include the proper definitions. */
+#include "../../../bionic/libc/upstream-dlmalloc/malloc.h"
+
+/*
+ * Define dlmalloc routines from bionic that cannot be included
+ * directly because of redefining symbols from the include above.
+ */
+extern "C" void dlmalloc_inspect_all(void(*handler)(void*, void *, size_t, void*),
+ void* arg);
+extern "C" int dlmalloc_trim(size_t);
+extern "C" void* dlmem2chunk(void* mem);
+
+#endif // DALVIK_VM_ALLOC_DLMALLOC_H_
Oops, something went wrong.

0 comments on commit 808a7c0

Please sign in to comment.