1f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
2f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Copyright (C) 2008 The Android Open Source Project
3f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
4f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Licensed under the Apache License, Version 2.0 (the "License");
5f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * you may not use this file except in compliance with the License.
6f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * You may obtain a copy of the License at
7f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
8f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *      http://www.apache.org/licenses/LICENSE-2.0
9f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
10f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Unless required by applicable law or agreed to in writing, software
11f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS,
12f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * See the License for the specific language governing permissions and
14f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * limitations under the License.
15f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
16f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
17f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * DDM-related heap functions
18f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
19f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#include <sys/time.h>
20f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#include <time.h>
21f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
22f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#include "Dalvik.h"
23f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#include "alloc/Heap.h"
24f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#include "alloc/HeapInternal.h"
25f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#include "alloc/DdmHeap.h"
26808a7c0e7e39b7ca3c7db1366e6e4089166052bbIan Rogers#include "alloc/DlMalloc.h"
27f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#include "alloc/HeapSource.h"
28f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
29f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#define DEFAULT_HEAP_ID  1
30f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
31f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectenum HpifWhen {
32f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    HPIF_WHEN_NEVER = 0,
33f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    HPIF_WHEN_NOW = 1,
34f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    HPIF_WHEN_NEXT_GC = 2,
35f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    HPIF_WHEN_EVERY_GC = 3
36f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project};
37f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
38f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
39f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Chunk HPIF (client --> server)
40de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro *
41f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Heap Info. General information about the heap,
42f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * suitable for a summary display.
43de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro *
44f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *   [u4]: number of heaps
45de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro *
46f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *   For each heap:
47f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *     [u4]: heap ID
48f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *     [u8]: timestamp in ms since Unix epoch
49f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *     [u1]: capture reason (same as 'when' value from server)
50f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *     [u4]: max heap size in bytes (-Xmx)
51f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *     [u4]: current heap size in bytes
52f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *     [u4]: current number of bytes allocated
53f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *     [u4]: current number of objects allocated
54f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
55f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#define HPIF_SIZE(numHeaps) \
56f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        (sizeof(u4) + (numHeaps) * (5 * sizeof(u4) + sizeof(u1) + sizeof(u8)))
5706f120f6092185003bc9b70e06eb44866e9676f8Carl Shapirovoid dvmDdmSendHeapInfo(int reason, bool shouldLock)
58f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
59f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    struct timeval now;
60f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    u8 nowMs;
61f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    u1 *buf, *b;
62f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
63f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    buf = (u1 *)malloc(HPIF_SIZE(1));
64f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (buf == NULL) {
65f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return;
66f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
67f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    b = buf;
68f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
69f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /* If there's a one-shot 'when', reset it.
70f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
71f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (reason == gDvm.gcHeap->ddmHpifWhen) {
72f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (shouldLock && ! dvmLockHeap()) {
73e8e1ddccd616e8226b7cc1e4e9fdb327429249e8Steve Block            ALOGW("%s(): can't lock heap to clear when", __func__);
74f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            goto skip_when;
75f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
76f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (reason == gDvm.gcHeap->ddmHpifWhen) {
77f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (gDvm.gcHeap->ddmHpifWhen == HPIF_WHEN_NEXT_GC) {
78f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                gDvm.gcHeap->ddmHpifWhen = HPIF_WHEN_NEVER;
79f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
80f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
81f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (shouldLock) {
82f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            dvmUnlockHeap();
83f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
84f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
85f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectskip_when:
86f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
87f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /* The current time, in milliseconds since 0:00 GMT, 1/1/70.
88f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
89f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (gettimeofday(&now, NULL) < 0) {
90f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        nowMs = 0;
91f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    } else {
92f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        nowMs = (u8)now.tv_sec * 1000 + now.tv_usec / 1000;
93f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
94f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
95f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /* number of heaps */
96f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    set4BE(b, 1); b += 4;
97f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
98f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /* For each heap (of which there is one) */
99f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    {
100f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /* heap ID */
101f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        set4BE(b, DEFAULT_HEAP_ID); b += 4;
102f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
103f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /* timestamp */
104f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        set8BE(b, nowMs); b += 8;
105f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
106f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /* 'when' value */
107f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        *b++ = (u1)reason;
108f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
109f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /* max allowed heap size in bytes */
110df9f08b877ecfd8ebadea822bb9e066ee7d30433Carl Shapiro        set4BE(b, dvmHeapSourceGetMaximumSize()); b += 4;
111f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
112f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /* current heap size in bytes */
113f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        set4BE(b, dvmHeapSourceGetValue(HS_FOOTPRINT, NULL, 0)); b += 4;
114f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
115f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /* number of bytes allocated */
116f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        set4BE(b, dvmHeapSourceGetValue(HS_BYTES_ALLOCATED, NULL, 0)); b += 4;
117f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
118f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /* number of objects allocated */
119f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        set4BE(b, dvmHeapSourceGetValue(HS_OBJECTS_ALLOCATED, NULL, 0)); b += 4;
120f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
121f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    assert((intptr_t)b == (intptr_t)buf + (intptr_t)HPIF_SIZE(1));
122f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
123f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    dvmDbgDdmSendChunk(CHUNK_TYPE("HPIF"), b - buf, buf);
124f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
125f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
12606f120f6092185003bc9b70e06eb44866e9676f8Carl Shapirobool dvmDdmHandleHpifChunk(int when)
127f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
128f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    switch (when) {
129f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    case HPIF_WHEN_NOW:
130f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        dvmDdmSendHeapInfo(when, true);
131f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        break;
132f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    case HPIF_WHEN_NEVER:
133f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    case HPIF_WHEN_NEXT_GC:
134f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    case HPIF_WHEN_EVERY_GC:
135f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (dvmLockHeap()) {
136f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            gDvm.gcHeap->ddmHpifWhen = when;
137f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            dvmUnlockHeap();
138f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        } else {
1394308417beec548c2b2c06ecec4f7f4a965b09fb2Steve Block            ALOGI("%s(): can't lock heap to set when", __func__);
140f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            return false;
141f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
142f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        break;
143f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    default:
1444308417beec548c2b2c06ecec4f7f4a965b09fb2Steve Block        ALOGI("%s(): bad when value 0x%08x", __func__, when);
145f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return false;
146f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
147f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
148f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    return true;
149f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
150f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
151f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectenum HpsgSolidity {
152f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    SOLIDITY_FREE = 0,
153f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    SOLIDITY_HARD = 1,
154f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    SOLIDITY_SOFT = 2,
155f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    SOLIDITY_WEAK = 3,
156f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    SOLIDITY_PHANTOM = 4,
157f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    SOLIDITY_FINALIZABLE = 5,
158f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    SOLIDITY_SWEEP = 6,
159f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project};
160f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
161f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectenum HpsgKind {
162f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    KIND_OBJECT = 0,
163f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    KIND_CLASS_OBJECT = 1,
164f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    KIND_ARRAY_1 = 2,
165f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    KIND_ARRAY_2 = 3,
166f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    KIND_ARRAY_4 = 4,
167f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    KIND_ARRAY_8 = 5,
168f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    KIND_UNKNOWN = 6,
169f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    KIND_NATIVE = 7,
170f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project};
171f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
172f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#define HPSG_PARTIAL (1<<7)
173f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#define HPSG_STATE(solidity, kind) \
174f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    ((u1)((((kind) & 0x7) << 3) | ((solidity) & 0x7)))
175f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
17650e5fd5984c9b0a6f0927ed5ddf13bde40e338c7Carl Shapirostruct HeapChunkContext {
177808a7c0e7e39b7ca3c7db1366e6e4089166052bbIan Rogers    void* startOfNextMemoryChunk;
178f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    u1 *buf;
179f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    u1 *p;
180f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    u1 *pieceLenField;
181f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    size_t bufLen;
182f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    size_t totalAllocationUnits;
183f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    int type;
184f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    bool merge;
185f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    bool needHeader;
18650e5fd5984c9b0a6f0927ed5ddf13bde40e338c7Carl Shapiro};
187f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
188f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#define ALLOCATION_UNIT_SIZE 8
189f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
19006f120f6092185003bc9b70e06eb44866e9676f8Carl Shapirostatic void flush_hpsg_chunk(HeapChunkContext *ctx)
191f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
19222d8dba8ae5be7aecb07322a410712206896fa15Tim Murray    if (ctx->pieceLenField == NULL && ctx->needHeader) {
19322d8dba8ae5be7aecb07322a410712206896fa15Tim Murray        /* Already flushed */
19422d8dba8ae5be7aecb07322a410712206896fa15Tim Murray        return;
19522d8dba8ae5be7aecb07322a410712206896fa15Tim Murray    }
196f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /* Patch the "length of piece" field.
197f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
198f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    assert(ctx->buf <= ctx->pieceLenField &&
199f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            ctx->pieceLenField <= ctx->p);
200f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    set4BE(ctx->pieceLenField, ctx->totalAllocationUnits);
201f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
202f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /* Send the chunk.
203f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
204f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    dvmDbgDdmSendChunk(ctx->type, ctx->p - ctx->buf, ctx->buf);
205f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
206f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /* Reset the context.
207f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
208f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    ctx->p = ctx->buf;
209f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    ctx->totalAllocationUnits = 0;
210f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    ctx->needHeader = true;
211f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    ctx->pieceLenField = NULL;
212f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
213f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
214808a7c0e7e39b7ca3c7db1366e6e4089166052bbIan Rogersstatic void append_chunk(HeapChunkContext *ctx, u1 state, void* ptr, size_t length) {
215f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /* Make sure there's enough room left in the buffer.
216f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * We need to use two bytes for every fractional 256
217808a7c0e7e39b7ca3c7db1366e6e4089166052bbIan Rogers     * allocation units used by the chunk and 17 bytes for
218808a7c0e7e39b7ca3c7db1366e6e4089166052bbIan Rogers     * any header.
219f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
220f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    {
221808a7c0e7e39b7ca3c7db1366e6e4089166052bbIan Rogers        size_t needed = (((length/ALLOCATION_UNIT_SIZE + 255) / 256) * 2) + 17;
222f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        size_t bytesLeft = ctx->bufLen - (size_t)(ctx->p - ctx->buf);
22334f33c5e531650dda8d5159ebf34178bb770c828Andy McFadden        if (bytesLeft < needed) {
224f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            flush_hpsg_chunk(ctx);
225f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
22634f33c5e531650dda8d5159ebf34178bb770c828Andy McFadden        bytesLeft = ctx->bufLen - (size_t)(ctx->p - ctx->buf);
22734f33c5e531650dda8d5159ebf34178bb770c828Andy McFadden        if (bytesLeft < needed) {
228808a7c0e7e39b7ca3c7db1366e6e4089166052bbIan Rogers            ALOGW("chunk is too big to transmit (length=%zd, %zd bytes)",
229808a7c0e7e39b7ca3c7db1366e6e4089166052bbIan Rogers                  length, needed);
23034f33c5e531650dda8d5159ebf34178bb770c828Andy McFadden            return;
23134f33c5e531650dda8d5159ebf34178bb770c828Andy McFadden        }
232f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
233f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (ctx->needHeader) {
234f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /*
235f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * Start a new HPSx chunk.
236f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         */
237f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
238f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /* [u4]: heap ID */
239f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        set4BE(ctx->p, DEFAULT_HEAP_ID); ctx->p += 4;
240f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
241f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /* [u1]: size of allocation unit, in bytes */
242f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        *ctx->p++ = 8;
243f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
244f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /* [u4]: virtual address of segment start */
245808a7c0e7e39b7ca3c7db1366e6e4089166052bbIan Rogers        set4BE(ctx->p, (uintptr_t)ptr); ctx->p += 4;
246f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
247f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /* [u4]: offset of this piece (relative to the virtual address) */
248f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        set4BE(ctx->p, 0); ctx->p += 4;
249f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
250f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /* [u4]: length of piece, in allocation units
251f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * We won't know this until we're done, so save the offset
252f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * and stuff in a dummy value.
253f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         */
254f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        ctx->pieceLenField = ctx->p;
255f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        set4BE(ctx->p, 0x55555555); ctx->p += 4;
256f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
257f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        ctx->needHeader = false;
258f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
259808a7c0e7e39b7ca3c7db1366e6e4089166052bbIan Rogers    /* Write out the chunk description.
260808a7c0e7e39b7ca3c7db1366e6e4089166052bbIan Rogers     */
261808a7c0e7e39b7ca3c7db1366e6e4089166052bbIan Rogers    length /= ALLOCATION_UNIT_SIZE;   // convert to allocation units
262808a7c0e7e39b7ca3c7db1366e6e4089166052bbIan Rogers    ctx->totalAllocationUnits += length;
263808a7c0e7e39b7ca3c7db1366e6e4089166052bbIan Rogers    while (length > 256) {
264808a7c0e7e39b7ca3c7db1366e6e4089166052bbIan Rogers        *ctx->p++ = state | HPSG_PARTIAL;
265808a7c0e7e39b7ca3c7db1366e6e4089166052bbIan Rogers        *ctx->p++ = 255;     // length - 1
266808a7c0e7e39b7ca3c7db1366e6e4089166052bbIan Rogers        length -= 256;
267808a7c0e7e39b7ca3c7db1366e6e4089166052bbIan Rogers    }
268808a7c0e7e39b7ca3c7db1366e6e4089166052bbIan Rogers    *ctx->p++ = state;
269808a7c0e7e39b7ca3c7db1366e6e4089166052bbIan Rogers    *ctx->p++ = length - 1;
270808a7c0e7e39b7ca3c7db1366e6e4089166052bbIan Rogers}
271808a7c0e7e39b7ca3c7db1366e6e4089166052bbIan Rogers
272808a7c0e7e39b7ca3c7db1366e6e4089166052bbIan Rogers/*
273808a7c0e7e39b7ca3c7db1366e6e4089166052bbIan Rogers * Called by dlmalloc_inspect_all. If used_bytes != 0 then start is
274808a7c0e7e39b7ca3c7db1366e6e4089166052bbIan Rogers * the start of a malloc-ed piece of memory of size used_bytes. If
275808a7c0e7e39b7ca3c7db1366e6e4089166052bbIan Rogers * start is 0 then start is the beginning of any free space not
276808a7c0e7e39b7ca3c7db1366e6e4089166052bbIan Rogers * including dlmalloc's book keeping and end the start of the next
277808a7c0e7e39b7ca3c7db1366e6e4089166052bbIan Rogers * dlmalloc chunk. Regions purely containing book keeping don't
278808a7c0e7e39b7ca3c7db1366e6e4089166052bbIan Rogers * callback.
279808a7c0e7e39b7ca3c7db1366e6e4089166052bbIan Rogers */
280808a7c0e7e39b7ca3c7db1366e6e4089166052bbIan Rogersstatic void heap_chunk_callback(void* start, void* end, size_t used_bytes,
281808a7c0e7e39b7ca3c7db1366e6e4089166052bbIan Rogers                                void* arg)
282808a7c0e7e39b7ca3c7db1366e6e4089166052bbIan Rogers{
283808a7c0e7e39b7ca3c7db1366e6e4089166052bbIan Rogers    u1 state;
284808a7c0e7e39b7ca3c7db1366e6e4089166052bbIan Rogers    HeapChunkContext *ctx = (HeapChunkContext *)arg;
285808a7c0e7e39b7ca3c7db1366e6e4089166052bbIan Rogers    UNUSED_PARAMETER(end);
286f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
287808a7c0e7e39b7ca3c7db1366e6e4089166052bbIan Rogers    if (used_bytes == 0) {
288808a7c0e7e39b7ca3c7db1366e6e4089166052bbIan Rogers        if (start == NULL) {
289808a7c0e7e39b7ca3c7db1366e6e4089166052bbIan Rogers            // Reset for start of new heap.
290808a7c0e7e39b7ca3c7db1366e6e4089166052bbIan Rogers            ctx->startOfNextMemoryChunk = NULL;
291808a7c0e7e39b7ca3c7db1366e6e4089166052bbIan Rogers            flush_hpsg_chunk(ctx);
292808a7c0e7e39b7ca3c7db1366e6e4089166052bbIan Rogers        }
293808a7c0e7e39b7ca3c7db1366e6e4089166052bbIan Rogers        // Only process in use memory so that free region information
294808a7c0e7e39b7ca3c7db1366e6e4089166052bbIan Rogers        // also includes dlmalloc book keeping.
295808a7c0e7e39b7ca3c7db1366e6e4089166052bbIan Rogers        return;
296808a7c0e7e39b7ca3c7db1366e6e4089166052bbIan Rogers    }
297808a7c0e7e39b7ca3c7db1366e6e4089166052bbIan Rogers
298808a7c0e7e39b7ca3c7db1366e6e4089166052bbIan Rogers    /* If we're looking at the native heap, we'll just return
299808a7c0e7e39b7ca3c7db1366e6e4089166052bbIan Rogers     * (SOLIDITY_HARD, KIND_NATIVE) for all allocated chunks
300f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
301808a7c0e7e39b7ca3c7db1366e6e4089166052bbIan Rogers    bool native = ctx->type == CHUNK_TYPE("NHSG");
302808a7c0e7e39b7ca3c7db1366e6e4089166052bbIan Rogers
303808a7c0e7e39b7ca3c7db1366e6e4089166052bbIan Rogers    if (ctx->startOfNextMemoryChunk != NULL) {
304808a7c0e7e39b7ca3c7db1366e6e4089166052bbIan Rogers        // Transmit any pending free memory. Native free memory of
305808a7c0e7e39b7ca3c7db1366e6e4089166052bbIan Rogers        // over kMaxFreeLen could be because of the use of mmaps, so
306808a7c0e7e39b7ca3c7db1366e6e4089166052bbIan Rogers        // don't report. If not free memory then start a new segment.
307808a7c0e7e39b7ca3c7db1366e6e4089166052bbIan Rogers        bool flush = true;
308808a7c0e7e39b7ca3c7db1366e6e4089166052bbIan Rogers        if (start > ctx->startOfNextMemoryChunk) {
309808a7c0e7e39b7ca3c7db1366e6e4089166052bbIan Rogers            const size_t kMaxFreeLen = 2 * SYSTEM_PAGE_SIZE;
310808a7c0e7e39b7ca3c7db1366e6e4089166052bbIan Rogers            void* freeStart = ctx->startOfNextMemoryChunk;
311808a7c0e7e39b7ca3c7db1366e6e4089166052bbIan Rogers            void* freeEnd = start;
312808a7c0e7e39b7ca3c7db1366e6e4089166052bbIan Rogers            size_t freeLen = (char*)freeEnd - (char*)freeStart;
313808a7c0e7e39b7ca3c7db1366e6e4089166052bbIan Rogers            if (!native || freeLen < kMaxFreeLen) {
314808a7c0e7e39b7ca3c7db1366e6e4089166052bbIan Rogers                append_chunk(ctx, HPSG_STATE(SOLIDITY_FREE, 0),
315808a7c0e7e39b7ca3c7db1366e6e4089166052bbIan Rogers                             freeStart, freeLen);
316808a7c0e7e39b7ca3c7db1366e6e4089166052bbIan Rogers                flush = false;
317808a7c0e7e39b7ca3c7db1366e6e4089166052bbIan Rogers            }
318808a7c0e7e39b7ca3c7db1366e6e4089166052bbIan Rogers        }
319808a7c0e7e39b7ca3c7db1366e6e4089166052bbIan Rogers        if (flush) {
320808a7c0e7e39b7ca3c7db1366e6e4089166052bbIan Rogers            ctx->startOfNextMemoryChunk = NULL;
321808a7c0e7e39b7ca3c7db1366e6e4089166052bbIan Rogers            flush_hpsg_chunk(ctx);
322808a7c0e7e39b7ca3c7db1366e6e4089166052bbIan Rogers        }
323808a7c0e7e39b7ca3c7db1366e6e4089166052bbIan Rogers    }
324808a7c0e7e39b7ca3c7db1366e6e4089166052bbIan Rogers    const Object *obj = (const Object *)start;
325f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
326808a7c0e7e39b7ca3c7db1366e6e4089166052bbIan Rogers    /* It's an allocated chunk.  Figure out what it is.
327808a7c0e7e39b7ca3c7db1366e6e4089166052bbIan Rogers     */
328f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project//TODO: if ctx.merge, see if this chunk is different from the last chunk.
329f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project//      If it's the same, we should combine them.
330808a7c0e7e39b7ca3c7db1366e6e4089166052bbIan Rogers    if (!native && dvmIsValidObject(obj)) {
331808a7c0e7e39b7ca3c7db1366e6e4089166052bbIan Rogers        ClassObject *clazz = obj->clazz;
332808a7c0e7e39b7ca3c7db1366e6e4089166052bbIan Rogers        if (clazz == NULL) {
333808a7c0e7e39b7ca3c7db1366e6e4089166052bbIan Rogers            /* The object was probably just created
334808a7c0e7e39b7ca3c7db1366e6e4089166052bbIan Rogers             * but hasn't been initialized yet.
335808a7c0e7e39b7ca3c7db1366e6e4089166052bbIan Rogers             */
336808a7c0e7e39b7ca3c7db1366e6e4089166052bbIan Rogers            state = HPSG_STATE(SOLIDITY_HARD, KIND_OBJECT);
337808a7c0e7e39b7ca3c7db1366e6e4089166052bbIan Rogers        } else if (dvmIsTheClassClass(clazz)) {
338808a7c0e7e39b7ca3c7db1366e6e4089166052bbIan Rogers            state = HPSG_STATE(SOLIDITY_HARD, KIND_CLASS_OBJECT);
339808a7c0e7e39b7ca3c7db1366e6e4089166052bbIan Rogers        } else if (IS_CLASS_FLAG_SET(clazz, CLASS_ISARRAY)) {
340808a7c0e7e39b7ca3c7db1366e6e4089166052bbIan Rogers            if (IS_CLASS_FLAG_SET(clazz, CLASS_ISOBJECTARRAY)) {
341808a7c0e7e39b7ca3c7db1366e6e4089166052bbIan Rogers                state = HPSG_STATE(SOLIDITY_HARD, KIND_ARRAY_4);
342808a7c0e7e39b7ca3c7db1366e6e4089166052bbIan Rogers            } else {
343808a7c0e7e39b7ca3c7db1366e6e4089166052bbIan Rogers                switch (clazz->elementClass->primitiveType) {
344808a7c0e7e39b7ca3c7db1366e6e4089166052bbIan Rogers                case PRIM_BOOLEAN:
345808a7c0e7e39b7ca3c7db1366e6e4089166052bbIan Rogers                case PRIM_BYTE:
346808a7c0e7e39b7ca3c7db1366e6e4089166052bbIan Rogers                    state = HPSG_STATE(SOLIDITY_HARD, KIND_ARRAY_1);
347808a7c0e7e39b7ca3c7db1366e6e4089166052bbIan Rogers                    break;
348808a7c0e7e39b7ca3c7db1366e6e4089166052bbIan Rogers                case PRIM_CHAR:
349808a7c0e7e39b7ca3c7db1366e6e4089166052bbIan Rogers                case PRIM_SHORT:
350808a7c0e7e39b7ca3c7db1366e6e4089166052bbIan Rogers                    state = HPSG_STATE(SOLIDITY_HARD, KIND_ARRAY_2);
351808a7c0e7e39b7ca3c7db1366e6e4089166052bbIan Rogers                    break;
352808a7c0e7e39b7ca3c7db1366e6e4089166052bbIan Rogers                case PRIM_INT:
353808a7c0e7e39b7ca3c7db1366e6e4089166052bbIan Rogers                case PRIM_FLOAT:
354f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    state = HPSG_STATE(SOLIDITY_HARD, KIND_ARRAY_4);
355808a7c0e7e39b7ca3c7db1366e6e4089166052bbIan Rogers                    break;
356808a7c0e7e39b7ca3c7db1366e6e4089166052bbIan Rogers                case PRIM_DOUBLE:
357808a7c0e7e39b7ca3c7db1366e6e4089166052bbIan Rogers                case PRIM_LONG:
358808a7c0e7e39b7ca3c7db1366e6e4089166052bbIan Rogers                    state = HPSG_STATE(SOLIDITY_HARD, KIND_ARRAY_8);
359808a7c0e7e39b7ca3c7db1366e6e4089166052bbIan Rogers                    break;
360808a7c0e7e39b7ca3c7db1366e6e4089166052bbIan Rogers                default:
361808a7c0e7e39b7ca3c7db1366e6e4089166052bbIan Rogers                    assert(!"Unknown GC heap object type");
362808a7c0e7e39b7ca3c7db1366e6e4089166052bbIan Rogers                    state = HPSG_STATE(SOLIDITY_HARD, KIND_UNKNOWN);
363808a7c0e7e39b7ca3c7db1366e6e4089166052bbIan Rogers                    break;
364f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                }
365f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
366f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        } else {
367808a7c0e7e39b7ca3c7db1366e6e4089166052bbIan Rogers            state = HPSG_STATE(SOLIDITY_HARD, KIND_OBJECT);
368f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
369808a7c0e7e39b7ca3c7db1366e6e4089166052bbIan Rogers    } else {
370808a7c0e7e39b7ca3c7db1366e6e4089166052bbIan Rogers        obj = NULL; // it's not actually an object
371808a7c0e7e39b7ca3c7db1366e6e4089166052bbIan Rogers        state = HPSG_STATE(SOLIDITY_HARD, KIND_NATIVE);
372f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
373808a7c0e7e39b7ca3c7db1366e6e4089166052bbIan Rogers    append_chunk(ctx, state, start, used_bytes + HEAP_SOURCE_CHUNK_OVERHEAD);
374808a7c0e7e39b7ca3c7db1366e6e4089166052bbIan Rogers    ctx->startOfNextMemoryChunk =
375808a7c0e7e39b7ca3c7db1366e6e4089166052bbIan Rogers        (char*)start + used_bytes + HEAP_SOURCE_CHUNK_OVERHEAD;
376f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
377f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
378f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectenum HpsgWhen {
379f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    HPSG_WHEN_NEVER = 0,
380f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    HPSG_WHEN_EVERY_GC = 1,
381f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project};
382f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectenum HpsgWhat {
383f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    HPSG_WHAT_MERGED_OBJECTS = 0,
384f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    HPSG_WHAT_DISTINCT_OBJECTS = 1,
385f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project};
386f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
38734f33c5e531650dda8d5159ebf34178bb770c828Andy McFadden/*
38834f33c5e531650dda8d5159ebf34178bb770c828Andy McFadden * Maximum chunk size.  Obtain this from the formula:
38934f33c5e531650dda8d5159ebf34178bb770c828Andy McFadden *
39034f33c5e531650dda8d5159ebf34178bb770c828Andy McFadden * (((maximum_heap_size / ALLOCATION_UNIT_SIZE) + 255) / 256) * 2
39134f33c5e531650dda8d5159ebf34178bb770c828Andy McFadden */
39234f33c5e531650dda8d5159ebf34178bb770c828Andy McFadden#define HPSx_CHUNK_SIZE (16384 - 16)
393f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
39406f120f6092185003bc9b70e06eb44866e9676f8Carl Shapirostatic void walkHeap(bool merge, bool native)
395f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
396f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    HeapChunkContext ctx;
397de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro
398f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    memset(&ctx, 0, sizeof(ctx));
399f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    ctx.bufLen = HPSx_CHUNK_SIZE;
400f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    ctx.buf = (u1 *)malloc(ctx.bufLen);
401f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (ctx.buf == NULL) {
402f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return;
403f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
404f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
405f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    ctx.merge = merge;
406f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (native) {
407f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        ctx.type = CHUNK_TYPE("NHSG");
408f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    } else {
409f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (ctx.merge) {
410f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            ctx.type = CHUNK_TYPE("HPSG");
411f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        } else {
412f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            ctx.type = CHUNK_TYPE("HPSO");
413f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
414f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
415f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
416f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    ctx.p = ctx.buf;
417f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    ctx.needHeader = true;
418f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (native) {
419808a7c0e7e39b7ca3c7db1366e6e4089166052bbIan Rogers        dlmalloc_inspect_all(heap_chunk_callback, (void*)&ctx);
420f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    } else {
421f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        dvmHeapSourceWalk(heap_chunk_callback, (void *)&ctx);
422f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
423f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (ctx.p > ctx.buf) {
424f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        flush_hpsg_chunk(&ctx);
425f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
426f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
427f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    free(ctx.buf);
428f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
429f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
43006f120f6092185003bc9b70e06eb44866e9676f8Carl Shapirovoid dvmDdmSendHeapSegments(bool shouldLock, bool native)
431f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
432f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    u1 heapId[sizeof(u4)];
433f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    GcHeap *gcHeap = gDvm.gcHeap;
434f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    int when, what;
435f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    bool merge;
436f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
437f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /* Don't even grab the lock if there's nothing to do when we're called.
438f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
439f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (!native) {
440f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        when = gcHeap->ddmHpsgWhen;
441f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        what = gcHeap->ddmHpsgWhat;
442f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (when == HPSG_WHEN_NEVER) {
443f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            return;
444f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
445f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    } else {
446f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        when = gcHeap->ddmNhsgWhen;
447f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        what = gcHeap->ddmNhsgWhat;
448f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (when == HPSG_WHEN_NEVER) {
449f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            return;
450f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
451f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
452f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (shouldLock && !dvmLockHeap()) {
453e8e1ddccd616e8226b7cc1e4e9fdb327429249e8Steve Block        ALOGW("Can't lock heap for DDM HPSx dump");
454f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return;
455f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
456f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
457f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /* Figure out what kind of chunks we'll be sending.
458f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
459f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (what == HPSG_WHAT_MERGED_OBJECTS) {
460f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        merge = true;
461f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    } else if (what == HPSG_WHAT_DISTINCT_OBJECTS) {
462f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        merge = false;
463f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    } else {
464f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        assert(!"bad HPSG.what value");
465f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return;
466f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
467f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
468f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /* First, send a heap start chunk.
469f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
470f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    set4BE(heapId, DEFAULT_HEAP_ID);
471f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    dvmDbgDdmSendChunk(native ? CHUNK_TYPE("NHST") : CHUNK_TYPE("HPST"),
472f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        sizeof(u4), heapId);
473f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
474f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /* Send a series of heap segment chunks.
475f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
476f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    walkHeap(merge, native);
477f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
478f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /* Finally, send a heap end chunk.
479f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
480f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    dvmDbgDdmSendChunk(native ? CHUNK_TYPE("NHEN") : CHUNK_TYPE("HPEN"),
481f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        sizeof(u4), heapId);
482f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
483f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (shouldLock) {
484f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        dvmUnlockHeap();
485f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
486f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
487f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
48806f120f6092185003bc9b70e06eb44866e9676f8Carl Shapirobool dvmDdmHandleHpsgNhsgChunk(int when, int what, bool native)
489f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
4904308417beec548c2b2c06ecec4f7f4a965b09fb2Steve Block    ALOGI("dvmDdmHandleHpsgChunk(when %d, what %d, heap %d)", when, what,
491f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         native);
492f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    switch (when) {
493f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    case HPSG_WHEN_NEVER:
494f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    case HPSG_WHEN_EVERY_GC:
495f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        break;
496f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    default:
4974308417beec548c2b2c06ecec4f7f4a965b09fb2Steve Block        ALOGI("%s(): bad when value 0x%08x", __func__, when);
498f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return false;
499f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
500f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
501f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    switch (what) {
502f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    case HPSG_WHAT_MERGED_OBJECTS:
503f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    case HPSG_WHAT_DISTINCT_OBJECTS:
504f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        break;
505f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    default:
5064308417beec548c2b2c06ecec4f7f4a965b09fb2Steve Block        ALOGI("%s(): bad what value 0x%08x", __func__, what);
507f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return false;
508f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
509f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
510f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (dvmLockHeap()) {
511f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (!native) {
512f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            gDvm.gcHeap->ddmHpsgWhen = when;
513f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            gDvm.gcHeap->ddmHpsgWhat = what;
514f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        } else {
515f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            gDvm.gcHeap->ddmNhsgWhen = when;
516f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            gDvm.gcHeap->ddmNhsgWhat = what;
517f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
518f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project//TODO: if what says we should dump immediately, signal (or do) it from here
519f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        dvmUnlockHeap();
520f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    } else {
5214308417beec548c2b2c06ecec4f7f4a965b09fb2Steve Block        ALOGI("%s(): can't lock heap to set when/what", __func__);
522f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return false;
523f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
524f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
525f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    return true;
526f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
527