DdmHeap.cpp revision df9f08b877ecfd8ebadea822bb9e066ee7d30433
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"
26f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#include "alloc/HeapSource.h"
27f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
28f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#define DEFAULT_HEAP_ID  1
29f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
30f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectenum HpifWhen {
31f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    HPIF_WHEN_NEVER = 0,
32f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    HPIF_WHEN_NOW = 1,
33f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    HPIF_WHEN_NEXT_GC = 2,
34f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    HPIF_WHEN_EVERY_GC = 3
35f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project};
36f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
37f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
38f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Chunk HPIF (client --> server)
39de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro *
40f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Heap Info. General information about the heap,
41f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * suitable for a summary display.
42de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro *
43f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *   [u4]: number of heaps
44de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro *
45f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *   For each heap:
46f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *     [u4]: heap ID
47f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *     [u8]: timestamp in ms since Unix epoch
48f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *     [u1]: capture reason (same as 'when' value from server)
49f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *     [u4]: max heap size in bytes (-Xmx)
50f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *     [u4]: current heap size in bytes
51f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *     [u4]: current number of bytes allocated
52f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *     [u4]: current number of objects allocated
53f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
54f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#define HPIF_SIZE(numHeaps) \
55f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        (sizeof(u4) + (numHeaps) * (5 * sizeof(u4) + sizeof(u1) + sizeof(u8)))
56f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectvoid
57f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source ProjectdvmDdmSendHeapInfo(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()) {
73f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            LOGW("%s(): can't lock heap to clear when\n", __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
126f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectbool
127f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source ProjectdvmDdmHandleHpifChunk(int when)
128f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
129f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    switch (when) {
130f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    case HPIF_WHEN_NOW:
131f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        dvmDdmSendHeapInfo(when, true);
132f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        break;
133f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    case HPIF_WHEN_NEVER:
134f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    case HPIF_WHEN_NEXT_GC:
135f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    case HPIF_WHEN_EVERY_GC:
136f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (dvmLockHeap()) {
137f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            gDvm.gcHeap->ddmHpifWhen = when;
138f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            dvmUnlockHeap();
139f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        } else {
140f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            LOGI("%s(): can't lock heap to set when\n", __func__);
141f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            return false;
142f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
143f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        break;
144f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    default:
145f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        LOGI("%s(): bad when value 0x%08x\n", __func__, when);
146f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return false;
147f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
148f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
149f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    return true;
150f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
151f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
152f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectenum HpsgSolidity {
153f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    SOLIDITY_FREE = 0,
154f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    SOLIDITY_HARD = 1,
155f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    SOLIDITY_SOFT = 2,
156f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    SOLIDITY_WEAK = 3,
157f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    SOLIDITY_PHANTOM = 4,
158f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    SOLIDITY_FINALIZABLE = 5,
159f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    SOLIDITY_SWEEP = 6,
160f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project};
161f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
162f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectenum HpsgKind {
163f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    KIND_OBJECT = 0,
164f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    KIND_CLASS_OBJECT = 1,
165f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    KIND_ARRAY_1 = 2,
166f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    KIND_ARRAY_2 = 3,
167f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    KIND_ARRAY_4 = 4,
168f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    KIND_ARRAY_8 = 5,
169f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    KIND_UNKNOWN = 6,
170f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    KIND_NATIVE = 7,
171f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project};
172f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
173f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#define HPSG_PARTIAL (1<<7)
174f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#define HPSG_STATE(solidity, kind) \
175f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    ((u1)((((kind) & 0x7) << 3) | ((solidity) & 0x7)))
176f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
177f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projecttypedef struct HeapChunkContext {
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;
186f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project} HeapChunkContext;
187f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
188f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#define ALLOCATION_UNIT_SIZE 8
189f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
190f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic void
191f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectflush_hpsg_chunk(HeapChunkContext *ctx)
192f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
193f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /* Patch the "length of piece" field.
194f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
195f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    assert(ctx->buf <= ctx->pieceLenField &&
196f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            ctx->pieceLenField <= ctx->p);
197f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    set4BE(ctx->pieceLenField, ctx->totalAllocationUnits);
198f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
199f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /* Send the chunk.
200f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
201f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    dvmDbgDdmSendChunk(ctx->type, ctx->p - ctx->buf, ctx->buf);
202f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
203f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /* Reset the context.
204f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
205f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    ctx->p = ctx->buf;
206f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    ctx->totalAllocationUnits = 0;
207f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    ctx->needHeader = true;
208f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    ctx->pieceLenField = NULL;
209f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
210f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
211f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic void
212f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectheap_chunk_callback(const void *chunkptr, size_t chunklen,
213f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    const void *userptr, size_t userlen, void *arg)
214f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
215f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    HeapChunkContext *ctx = (HeapChunkContext *)arg;
216f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    u1 state;
217f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
218f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    UNUSED_PARAMETER(userlen);
219f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
220f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    assert((chunklen & (ALLOCATION_UNIT_SIZE-1)) == 0);
221f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
222f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /* Make sure there's enough room left in the buffer.
223f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * We need to use two bytes for every fractional 256
224f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * allocation units used by the chunk.
225f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
226f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    {
22734f33c5e531650dda8d5159ebf34178bb770c828Andy McFadden        size_t needed = (((chunklen/ALLOCATION_UNIT_SIZE + 255) / 256) * 2);
228f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        size_t bytesLeft = ctx->bufLen - (size_t)(ctx->p - ctx->buf);
22934f33c5e531650dda8d5159ebf34178bb770c828Andy McFadden        if (bytesLeft < needed) {
230f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            flush_hpsg_chunk(ctx);
231f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
23234f33c5e531650dda8d5159ebf34178bb770c828Andy McFadden
23334f33c5e531650dda8d5159ebf34178bb770c828Andy McFadden        bytesLeft = ctx->bufLen - (size_t)(ctx->p - ctx->buf);
23434f33c5e531650dda8d5159ebf34178bb770c828Andy McFadden        if (bytesLeft < needed) {
23534f33c5e531650dda8d5159ebf34178bb770c828Andy McFadden            LOGW("chunk is too big to transmit (chunklen=%zd, %zd bytes)\n",
23634f33c5e531650dda8d5159ebf34178bb770c828Andy McFadden                chunklen, needed);
23734f33c5e531650dda8d5159ebf34178bb770c828Andy McFadden            return;
23834f33c5e531650dda8d5159ebf34178bb770c828Andy McFadden        }
239f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
240f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
241f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project//TODO: notice when there's a gap and start a new heap, or at least a new range.
242f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (ctx->needHeader) {
243f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /*
244f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * Start a new HPSx chunk.
245f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         */
246f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
247f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /* [u4]: heap ID */
248f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        set4BE(ctx->p, DEFAULT_HEAP_ID); ctx->p += 4;
249f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
250f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /* [u1]: size of allocation unit, in bytes */
251f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        *ctx->p++ = 8;
252f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
253f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /* [u4]: virtual address of segment start */
254f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        set4BE(ctx->p, (uintptr_t)chunkptr); ctx->p += 4;
255f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
256f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /* [u4]: offset of this piece (relative to the virtual address) */
257f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        set4BE(ctx->p, 0); ctx->p += 4;
258f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
259f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /* [u4]: length of piece, in allocation units
260f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * We won't know this until we're done, so save the offset
261f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * and stuff in a dummy value.
262f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         */
263f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        ctx->pieceLenField = ctx->p;
264f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        set4BE(ctx->p, 0x55555555); ctx->p += 4;
265f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
266f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        ctx->needHeader = false;
267f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
268f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
269f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /* Determine the type of this chunk.
270f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
271f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (userptr == NULL) {
272f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /* It's a free chunk.
273f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         */
274f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        state = HPSG_STATE(SOLIDITY_FREE, 0);
275f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    } else {
2766343bd071555458d0cb071f2eaf15b59b36771bfCarl Shapiro        const Object *obj = userptr;
277de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro        /* If we're looking at the native heap, we'll just return
278f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * (SOLIDITY_HARD, KIND_NATIVE) for all allocated chunks
279f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         */
280f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        bool native = ctx->type == CHUNK_TYPE("NHSG");
281f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
282f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /* It's an allocated chunk.  Figure out what it is.
283f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         */
284f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project//TODO: if ctx.merge, see if this chunk is different from the last chunk.
285f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project//      If it's the same, we should combine them.
286f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (!native && dvmIsValidObject(obj)) {
287f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            ClassObject *clazz = obj->clazz;
288f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (clazz == NULL) {
289f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                /* The object was probably just created
290f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                 * but hasn't been initialized yet.
291f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                 */
292f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                state = HPSG_STATE(SOLIDITY_HARD, KIND_OBJECT);
293c49db8554956f8d43eb487709bc1dccfe0496ad2Barry Hayes            } else if (clazz == gDvm.classJavaLangClass) {
294f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                state = HPSG_STATE(SOLIDITY_HARD, KIND_CLASS_OBJECT);
295f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            } else if (IS_CLASS_FLAG_SET(clazz, CLASS_ISARRAY)) {
296f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                if (IS_CLASS_FLAG_SET(clazz, CLASS_ISOBJECTARRAY)) {
297f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    state = HPSG_STATE(SOLIDITY_HARD, KIND_ARRAY_4);
298f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                } else {
299f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    switch (clazz->elementClass->primitiveType) {
300f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    case PRIM_BOOLEAN:
301f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    case PRIM_BYTE:
302f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                        state = HPSG_STATE(SOLIDITY_HARD, KIND_ARRAY_1);
303f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                        break;
304f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    case PRIM_CHAR:
305f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    case PRIM_SHORT:
306f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                        state = HPSG_STATE(SOLIDITY_HARD, KIND_ARRAY_2);
307f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                        break;
308f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    case PRIM_INT:
309f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    case PRIM_FLOAT:
310f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                        state = HPSG_STATE(SOLIDITY_HARD, KIND_ARRAY_4);
311f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                        break;
312f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    case PRIM_DOUBLE:
313f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    case PRIM_LONG:
314f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                        state = HPSG_STATE(SOLIDITY_HARD, KIND_ARRAY_8);
315f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                        break;
316f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    default:
317f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                        assert(!"Unknown GC heap object type");
318f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                        state = HPSG_STATE(SOLIDITY_HARD, KIND_UNKNOWN);
319f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                        break;
320f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    }
321f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                }
322f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            } else {
323f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                state = HPSG_STATE(SOLIDITY_HARD, KIND_OBJECT);
324f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
325f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        } else {
326f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            obj = NULL; // it's not actually an object
327f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            state = HPSG_STATE(SOLIDITY_HARD, KIND_NATIVE);
328f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
329f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
330f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
331f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /* Write out the chunk description.
332f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
333f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    chunklen /= ALLOCATION_UNIT_SIZE;   // convert to allocation units
334f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    ctx->totalAllocationUnits += chunklen;
335f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    while (chunklen > 256) {
336f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        *ctx->p++ = state | HPSG_PARTIAL;
337f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        *ctx->p++ = 255;     // length - 1
338f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        chunklen -= 256;
339f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
340f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    *ctx->p++ = state;
341f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    *ctx->p++ = chunklen - 1;
342f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
343f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
344f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectenum HpsgWhen {
345f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    HPSG_WHEN_NEVER = 0,
346f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    HPSG_WHEN_EVERY_GC = 1,
347f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project};
348f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectenum HpsgWhat {
349f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    HPSG_WHAT_MERGED_OBJECTS = 0,
350f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    HPSG_WHAT_DISTINCT_OBJECTS = 1,
351f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project};
352f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
35334f33c5e531650dda8d5159ebf34178bb770c828Andy McFadden/*
35434f33c5e531650dda8d5159ebf34178bb770c828Andy McFadden * Maximum chunk size.  Obtain this from the formula:
35534f33c5e531650dda8d5159ebf34178bb770c828Andy McFadden *
35634f33c5e531650dda8d5159ebf34178bb770c828Andy McFadden * (((maximum_heap_size / ALLOCATION_UNIT_SIZE) + 255) / 256) * 2
35734f33c5e531650dda8d5159ebf34178bb770c828Andy McFadden */
35834f33c5e531650dda8d5159ebf34178bb770c828Andy McFadden#define HPSx_CHUNK_SIZE (16384 - 16)
359f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
360f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectvoid dlmalloc_walk_heap(void(*)(const void*, size_t, const void*, size_t, void*),void*);
361f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
362f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic void
363f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source ProjectwalkHeap(bool merge, bool native)
364f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
365f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    HeapChunkContext ctx;
366de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro
367f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    memset(&ctx, 0, sizeof(ctx));
368f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    ctx.bufLen = HPSx_CHUNK_SIZE;
369f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    ctx.buf = (u1 *)malloc(ctx.bufLen);
370f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (ctx.buf == NULL) {
371f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return;
372f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
373f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
374f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    ctx.merge = merge;
375f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (native) {
376f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        ctx.type = CHUNK_TYPE("NHSG");
377f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    } else {
378f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (ctx.merge) {
379f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            ctx.type = CHUNK_TYPE("HPSG");
380f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        } else {
381f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            ctx.type = CHUNK_TYPE("HPSO");
382f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
383f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
384f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
385f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    ctx.p = ctx.buf;
386f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    ctx.needHeader = true;
387f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (native) {
388f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        dlmalloc_walk_heap(heap_chunk_callback, (void *)&ctx);
389f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    } else {
390f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        dvmHeapSourceWalk(heap_chunk_callback, (void *)&ctx);
391f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
392f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (ctx.p > ctx.buf) {
393f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        flush_hpsg_chunk(&ctx);
394f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
395f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
396f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    free(ctx.buf);
397f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
398f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
399f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectvoid
400f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source ProjectdvmDdmSendHeapSegments(bool shouldLock, bool native)
401f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
402f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    u1 heapId[sizeof(u4)];
403f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    GcHeap *gcHeap = gDvm.gcHeap;
404f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    int when, what;
405f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    bool merge;
406f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
407f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /* Don't even grab the lock if there's nothing to do when we're called.
408f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
409f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (!native) {
410f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        when = gcHeap->ddmHpsgWhen;
411f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        what = gcHeap->ddmHpsgWhat;
412f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (when == HPSG_WHEN_NEVER) {
413f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            return;
414f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
415f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    } else {
416f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        when = gcHeap->ddmNhsgWhen;
417f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        what = gcHeap->ddmNhsgWhat;
418f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (when == HPSG_WHEN_NEVER) {
419f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            return;
420f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
421f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
422f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (shouldLock && !dvmLockHeap()) {
423f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        LOGW("Can't lock heap for DDM HPSx dump\n");
424f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return;
425f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
426f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
427f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /* Figure out what kind of chunks we'll be sending.
428f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
429f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (what == HPSG_WHAT_MERGED_OBJECTS) {
430f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        merge = true;
431f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    } else if (what == HPSG_WHAT_DISTINCT_OBJECTS) {
432f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        merge = false;
433f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    } else {
434f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        assert(!"bad HPSG.what value");
435f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return;
436f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
437f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
438f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /* First, send a heap start chunk.
439f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
440f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    set4BE(heapId, DEFAULT_HEAP_ID);
441f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    dvmDbgDdmSendChunk(native ? CHUNK_TYPE("NHST") : CHUNK_TYPE("HPST"),
442f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        sizeof(u4), heapId);
443f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
444f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /* Send a series of heap segment chunks.
445f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
446f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    walkHeap(merge, native);
447f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
448f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /* Finally, send a heap end chunk.
449f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
450f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    dvmDbgDdmSendChunk(native ? CHUNK_TYPE("NHEN") : CHUNK_TYPE("HPEN"),
451f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        sizeof(u4), heapId);
452f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
453f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (shouldLock) {
454f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        dvmUnlockHeap();
455f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
456f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
457f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
458f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectbool
459f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source ProjectdvmDdmHandleHpsgNhsgChunk(int when, int what, bool native)
460f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
461f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    LOGI("dvmDdmHandleHpsgChunk(when %d, what %d, heap %d)\n", when, what,
462f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         native);
463f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    switch (when) {
464f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    case HPSG_WHEN_NEVER:
465f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    case HPSG_WHEN_EVERY_GC:
466f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        break;
467f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    default:
468f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        LOGI("%s(): bad when value 0x%08x\n", __func__, when);
469f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return false;
470f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
471f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
472f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    switch (what) {
473f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    case HPSG_WHAT_MERGED_OBJECTS:
474f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    case HPSG_WHAT_DISTINCT_OBJECTS:
475f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        break;
476f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    default:
477f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        LOGI("%s(): bad what value 0x%08x\n", __func__, what);
478f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return false;
479f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
480f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
481f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (dvmLockHeap()) {
482f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (!native) {
483f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            gDvm.gcHeap->ddmHpsgWhen = when;
484f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            gDvm.gcHeap->ddmHpsgWhat = what;
485f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        } else {
486f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            gDvm.gcHeap->ddmNhsgWhen = when;
487f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            gDvm.gcHeap->ddmNhsgWhat = what;
488f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
489f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project//TODO: if what says we should dump immediately, signal (or do) it from here
490f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        dvmUnlockHeap();
491f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    } else {
492f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        LOGI("%s(): can't lock heap to set when/what\n", __func__);
493f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return false;
494f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
495f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
496f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    return true;
497f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
498