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 * Heap object dump
18f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
19f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#include "Hprof.h"
20f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
21f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#include "alloc/HeapInternal.h"
22f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#include "alloc/HeapSource.h"
23f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
24f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/* Set DUMP_PRIM_DATA to 1 if you want to include the contents
25f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * of primitive arrays (byte arrays, character arrays, etc.)
26f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * in heap dumps.  This can be a large amount of data.
27f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
28f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#define DUMP_PRIM_DATA 1
29f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
30f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#define OBJECTS_PER_SEGMENT     ((size_t)128)
31f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#define BYTES_PER_SEGMENT       ((size_t)4096)
32f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3303aa70ae413c6c5fb2ee4424afd30608bfb465eeBarry Hayes/* The static field-name for the synthetic object generated to account
3403aa70ae413c6c5fb2ee4424afd30608bfb465eeBarry Hayes * for class Static overhead.
3503aa70ae413c6c5fb2ee4424afd30608bfb465eeBarry Hayes */
3603aa70ae413c6c5fb2ee4424afd30608bfb465eeBarry Hayes#define STATIC_OVERHEAD_NAME    "$staticOverhead"
3703aa70ae413c6c5fb2ee4424afd30608bfb465eeBarry Hayes/* The ID for the synthetic object generated to account for class
3803aa70ae413c6c5fb2ee4424afd30608bfb465eeBarry Hayes * Static overhead.
3903aa70ae413c6c5fb2ee4424afd30608bfb465eeBarry Hayes */
4003aa70ae413c6c5fb2ee4424afd30608bfb465eeBarry Hayes#define CLASS_STATICS_ID(clazz) ((hprof_object_id)(((u4)(clazz)) | 1))
4103aa70ae413c6c5fb2ee4424afd30608bfb465eeBarry Hayes
42f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectint
43f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source ProjecthprofStartHeapDump(hprof_context_t *ctx)
44f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
45f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    UNUSED_PARAMETER(ctx);
46f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
47f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    ctx->objectsInSegment = OBJECTS_PER_SEGMENT;
48f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    ctx->currentHeap = HPROF_HEAP_DEFAULT;
49f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    return 0;
50f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
51f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
52f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectint
53f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source ProjecthprofFinishHeapDump(hprof_context_t *ctx)
54f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
55f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    return hprofStartNewRecord(ctx, HPROF_TAG_HEAP_DUMP_END, HPROF_TIME);
56f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
57f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
58f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectint
59f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source ProjecthprofSetGcScanState(hprof_context_t *ctx,
60f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    hprof_heap_tag_t state, u4 threadSerialNumber)
61f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
62f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /* Used by hprofMarkRootObject()
63f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
64f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    ctx->gcScanState = state;
65f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    ctx->gcThreadSerialNumber = threadSerialNumber;
66f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    return 0;
67f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
68f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
69f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic hprof_basic_type
70f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source ProjectsignatureToBasicTypeAndSize(const char *sig, size_t *sizeOut)
71f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
72f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    char c = sig[0];
73f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    hprof_basic_type ret;
74f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    size_t size;
75f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
76f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    switch (c) {
77f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    case '[':
78f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    case 'L': ret = hprof_basic_object;  size = 4; break;
79f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    case 'Z': ret = hprof_basic_boolean; size = 1; break;
80f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    case 'C': ret = hprof_basic_char;    size = 2; break;
81f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    case 'F': ret = hprof_basic_float;   size = 4; break;
82f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    case 'D': ret = hprof_basic_double;  size = 8; break;
83f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    case 'B': ret = hprof_basic_byte;    size = 1; break;
84f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    case 'S': ret = hprof_basic_short;   size = 2; break;
85f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    default: assert(false);
86f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    case 'I': ret = hprof_basic_int;     size = 4; break;
87f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    case 'J': ret = hprof_basic_long;    size = 8; break;
88f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
89f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
90f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (sizeOut != NULL) {
91f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        *sizeOut = size;
92f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
93f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
94f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    return ret;
95f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
96f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
97f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic hprof_basic_type
98f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source ProjectprimitiveToBasicTypeAndSize(PrimitiveType prim, size_t *sizeOut)
99f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
100f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    hprof_basic_type ret;
101f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    size_t size;
102f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
103f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    switch (prim) {
104f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    case PRIM_BOOLEAN: ret = hprof_basic_boolean; size = 1; break;
105f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    case PRIM_CHAR:    ret = hprof_basic_char;    size = 2; break;
106f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    case PRIM_FLOAT:   ret = hprof_basic_float;   size = 4; break;
107f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    case PRIM_DOUBLE:  ret = hprof_basic_double;  size = 8; break;
108f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    case PRIM_BYTE:    ret = hprof_basic_byte;    size = 1; break;
109f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    case PRIM_SHORT:   ret = hprof_basic_short;   size = 2; break;
110f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    default: assert(false);
111f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    case PRIM_INT:     ret = hprof_basic_int;     size = 4; break;
112f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    case PRIM_LONG:    ret = hprof_basic_long;    size = 8; break;
113f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
114f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
115f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (sizeOut != NULL) {
116f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        *sizeOut = size;
117f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
118f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
119f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    return ret;
120f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
121f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
122f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/* Always called when marking objects, but only does
123f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * something when ctx->gcScanState is non-zero, which is usually
124f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * only true when marking the root set or unreachable
125f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * objects.  Used to add rootset references to obj.
126f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
127f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectint
128f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source ProjecthprofMarkRootObject(hprof_context_t *ctx, const Object *obj, jobject jniObj)
129f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
130f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    hprof_record_t *rec = &ctx->curRec;
131f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    int err;
132f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    hprof_heap_tag_t heapTag = ctx->gcScanState;
133f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
134f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (heapTag == 0) {
135f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return 0;
136f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
137f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
138f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (ctx->objectsInSegment >= OBJECTS_PER_SEGMENT ||
139f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        rec->length >= BYTES_PER_SEGMENT)
140f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    {
141f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /* This flushes the old segment and starts a new one.
142f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         */
143f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        hprofStartNewRecord(ctx, HPROF_TAG_HEAP_DUMP_SEGMENT, HPROF_TIME);
144f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        ctx->objectsInSegment = 0;
145f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
146f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
147f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    switch (heapTag) {
148f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /* ID: object ID
149f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
150f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    case HPROF_ROOT_UNKNOWN:
151f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    case HPROF_ROOT_STICKY_CLASS:
152f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    case HPROF_ROOT_MONITOR_USED:
153f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    case HPROF_ROOT_INTERNED_STRING:
154f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    case HPROF_ROOT_FINALIZING:
155f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    case HPROF_ROOT_DEBUGGER:
156f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    case HPROF_ROOT_REFERENCE_CLEANUP:
157f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    case HPROF_ROOT_VM_INTERNAL:
158f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        hprofAddU1ToRecord(rec, heapTag);
159f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        hprofAddIdToRecord(rec, (hprof_object_id)obj);
160f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        break;
161f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
162f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /* ID: object ID
163f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * ID: JNI global ref ID
164f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
165f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    case HPROF_ROOT_JNI_GLOBAL:
166f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        hprofAddU1ToRecord(rec, heapTag);
167f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        hprofAddIdToRecord(rec, (hprof_object_id)obj);
168f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        hprofAddIdToRecord(rec, (hprof_id)jniObj);
169f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        break;
170f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
171f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /* ID: object ID
172f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * u4: thread serial number
173f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * u4: frame number in stack trace (-1 for empty)
174f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
175f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    case HPROF_ROOT_JNI_LOCAL:
176f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    case HPROF_ROOT_JNI_MONITOR:
177f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    case HPROF_ROOT_JAVA_FRAME:
178f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        hprofAddU1ToRecord(rec, heapTag);
179f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        hprofAddIdToRecord(rec, (hprof_object_id)obj);
180f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        hprofAddU4ToRecord(rec, ctx->gcThreadSerialNumber);
181f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        hprofAddU4ToRecord(rec, (u4)-1);
182f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        break;
183f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
184f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /* ID: object ID
185f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * u4: thread serial number
186f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
187f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    case HPROF_ROOT_NATIVE_STACK:
188f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    case HPROF_ROOT_THREAD_BLOCK:
189f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        hprofAddU1ToRecord(rec, heapTag);
190f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        hprofAddIdToRecord(rec, (hprof_object_id)obj);
191f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        hprofAddU4ToRecord(rec, ctx->gcThreadSerialNumber);
192f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        break;
193f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
194f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /* ID: thread object ID
195f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * u4: thread serial number
196f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * u4: stack trace serial number
197f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
198f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    case HPROF_ROOT_THREAD_OBJECT:
199f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        hprofAddU1ToRecord(rec, heapTag);
200f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        hprofAddIdToRecord(rec, (hprof_object_id)obj);
201f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        hprofAddU4ToRecord(rec, ctx->gcThreadSerialNumber);
202f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        hprofAddU4ToRecord(rec, (u4)-1);    //xxx
203f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        break;
204f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
205f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    default:
206f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        err = 0;
207f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        break;
208f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
209f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
210f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    ctx->objectsInSegment++;
211f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
212f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    return err;
213f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
214f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
215f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic int
216f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source ProjectstackTraceSerialNumber(const void *obj)
217f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
218f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
219f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#if WITH_HPROF_STACK
220f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    DvmHeapChunk *chunk = ptr2chunk(obj);
221f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    return chunk->stackTraceSerialNumber;
222f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#else
223f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    return HPROF_NULL_STACK_TRACE;
224f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#endif
225f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
226f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
227f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectint
228f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source ProjecthprofDumpHeapObject(hprof_context_t *ctx, const Object *obj)
229f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
230f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    const ClassObject *clazz;
231f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    hprof_record_t *rec = &ctx->curRec;
232f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    HprofHeapId desiredHeap;
233f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
234de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro    desiredHeap =
2356343bd071555458d0cb071f2eaf15b59b36771bfCarl Shapiro            dvmHeapSourceGetPtrFlag(obj, HS_ALLOCATED_IN_ZYGOTE) ?
236f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            HPROF_HEAP_ZYGOTE : HPROF_HEAP_APP;
237de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro
238f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (ctx->objectsInSegment >= OBJECTS_PER_SEGMENT ||
239f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        rec->length >= BYTES_PER_SEGMENT)
240f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    {
241f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /* This flushes the old segment and starts a new one.
242f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         */
243f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        hprofStartNewRecord(ctx, HPROF_TAG_HEAP_DUMP_SEGMENT, HPROF_TIME);
244f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        ctx->objectsInSegment = 0;
245f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
246f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /* Starting a new HEAP_DUMP resets the heap to default.
247f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         */
248f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        ctx->currentHeap = HPROF_HEAP_DEFAULT;
249f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
250f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
251f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (desiredHeap != ctx->currentHeap) {
252f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        hprof_string_id nameId;
253f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
254f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /* This object is in a different heap than the current one.
255f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * Emit a HEAP_DUMP_INFO tag to change heaps.
256f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         */
257f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        hprofAddU1ToRecord(rec, HPROF_HEAP_DUMP_INFO);
258f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        hprofAddU4ToRecord(rec, (u4)desiredHeap);   // u4: heap id
259f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        switch (desiredHeap) {
260f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        case HPROF_HEAP_APP:
261f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            nameId = hprofLookupStringId("app");
262f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            break;
263f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        case HPROF_HEAP_ZYGOTE:
264f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            nameId = hprofLookupStringId("zygote");
265f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            break;
266f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        default:
267f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            /* Internal error. */
268f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            assert(!"Unexpected desiredHeap");
269f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            nameId = hprofLookupStringId("<ILLEGAL>");
270f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            break;
271f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
272f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        hprofAddIdToRecord(rec, nameId);
273f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        ctx->currentHeap = desiredHeap;
274f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
275f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
276f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    clazz = obj->clazz;
277f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
278f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (clazz == NULL) {
279b4bad121113179f15934d0f97a613232158bc559Barry Hayes        /* This object will bother HprofReader, because it has a NULL
280b4bad121113179f15934d0f97a613232158bc559Barry Hayes         * class, so just don't dump it. It could be
281b4bad121113179f15934d0f97a613232158bc559Barry Hayes         * gDvm.unlinkedJavaLangClass or it could be an object just
282b4bad121113179f15934d0f97a613232158bc559Barry Hayes         * allocated which hasn't been initialized yet.
283f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         */
284f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    } else {
285f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        hprof_class_object_id clazzId;
286f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
287f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        clazzId = hprofLookupClassId(clazz);
288f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
289f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (clazz == gDvm.classJavaLangClass) {
290f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            const ClassObject *thisClass = (const ClassObject *)obj;
29103aa70ae413c6c5fb2ee4424afd30608bfb465eeBarry Hayes            int i, sFieldCount, iFieldCount;
292f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            /* obj is a ClassObject.
293f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             */
29403aa70ae413c6c5fb2ee4424afd30608bfb465eeBarry Hayes            sFieldCount = thisClass->sfieldCount;
29503aa70ae413c6c5fb2ee4424afd30608bfb465eeBarry Hayes            if (sFieldCount != 0) {
29603aa70ae413c6c5fb2ee4424afd30608bfb465eeBarry Hayes                int byteLength = sFieldCount*sizeof(StaticField);
29703aa70ae413c6c5fb2ee4424afd30608bfb465eeBarry Hayes                /* Create a byte array to reflect the allocation of the
29803aa70ae413c6c5fb2ee4424afd30608bfb465eeBarry Hayes                 * StaticField array at the end of this class.
29903aa70ae413c6c5fb2ee4424afd30608bfb465eeBarry Hayes                 */
30003aa70ae413c6c5fb2ee4424afd30608bfb465eeBarry Hayes                hprofAddU1ToRecord(rec, HPROF_PRIMITIVE_ARRAY_DUMP);
30103aa70ae413c6c5fb2ee4424afd30608bfb465eeBarry Hayes                hprofAddIdToRecord(rec, CLASS_STATICS_ID(obj));
30203aa70ae413c6c5fb2ee4424afd30608bfb465eeBarry Hayes                hprofAddU4ToRecord(rec, stackTraceSerialNumber(obj));
30303aa70ae413c6c5fb2ee4424afd30608bfb465eeBarry Hayes                hprofAddU4ToRecord(rec, byteLength);
30403aa70ae413c6c5fb2ee4424afd30608bfb465eeBarry Hayes                hprofAddU1ToRecord(rec, hprof_basic_byte);
30503aa70ae413c6c5fb2ee4424afd30608bfb465eeBarry Hayes                for (i = 0; i < byteLength; i++) {
30603aa70ae413c6c5fb2ee4424afd30608bfb465eeBarry Hayes                    hprofAddU1ToRecord(rec, 0);
30703aa70ae413c6c5fb2ee4424afd30608bfb465eeBarry Hayes                }
30803aa70ae413c6c5fb2ee4424afd30608bfb465eeBarry Hayes            }
309f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
31003aa70ae413c6c5fb2ee4424afd30608bfb465eeBarry Hayes            hprofAddU1ToRecord(rec, HPROF_CLASS_DUMP);
311f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            hprofAddIdToRecord(rec, hprofLookupClassId(thisClass));
312f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            hprofAddU4ToRecord(rec, stackTraceSerialNumber(thisClass));
313f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            hprofAddIdToRecord(rec, hprofLookupClassId(thisClass->super));
314f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            hprofAddIdToRecord(rec, (hprof_object_id)thisClass->classLoader);
315f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            hprofAddIdToRecord(rec, (hprof_object_id)0);    // no signer
316f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            hprofAddIdToRecord(rec, (hprof_object_id)0);    // no prot domain
317f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            hprofAddIdToRecord(rec, (hprof_id)0);           // reserved
318f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            hprofAddIdToRecord(rec, (hprof_id)0);           // reserved
319f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (obj == (Object *)gDvm.classJavaLangClass) {
32003aa70ae413c6c5fb2ee4424afd30608bfb465eeBarry Hayes                // ClassObjects have their static fields appended, so
32103aa70ae413c6c5fb2ee4424afd30608bfb465eeBarry Hayes                // aren't all the same size. But they're at least this
32203aa70ae413c6c5fb2ee4424afd30608bfb465eeBarry Hayes                // size.
323f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                hprofAddU4ToRecord(rec, sizeof(ClassObject)); // instance size
324f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            } else {
325f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                hprofAddU4ToRecord(rec, thisClass->objectSize); // instance size
326f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
327f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
328f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            hprofAddU2ToRecord(rec, 0);                     // empty const pool
329f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
330f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            /* Static fields
331f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             */
33203aa70ae413c6c5fb2ee4424afd30608bfb465eeBarry Hayes            if (sFieldCount == 0) {
33303aa70ae413c6c5fb2ee4424afd30608bfb465eeBarry Hayes                hprofAddU2ToRecord(rec, (u2)0);
33403aa70ae413c6c5fb2ee4424afd30608bfb465eeBarry Hayes            } else {
33503aa70ae413c6c5fb2ee4424afd30608bfb465eeBarry Hayes                hprofAddU2ToRecord(rec, (u2)(sFieldCount+1));
33603aa70ae413c6c5fb2ee4424afd30608bfb465eeBarry Hayes                hprofAddIdToRecord(rec,
33703aa70ae413c6c5fb2ee4424afd30608bfb465eeBarry Hayes                                   hprofLookupStringId(STATIC_OVERHEAD_NAME));
33803aa70ae413c6c5fb2ee4424afd30608bfb465eeBarry Hayes                hprofAddU1ToRecord(rec, hprof_basic_object);
33903aa70ae413c6c5fb2ee4424afd30608bfb465eeBarry Hayes                hprofAddIdToRecord(rec, CLASS_STATICS_ID(obj));
34003aa70ae413c6c5fb2ee4424afd30608bfb465eeBarry Hayes                for (i = 0; i < sFieldCount; i++) {
34103aa70ae413c6c5fb2ee4424afd30608bfb465eeBarry Hayes                    hprof_basic_type t;
34203aa70ae413c6c5fb2ee4424afd30608bfb465eeBarry Hayes                    size_t size;
34303aa70ae413c6c5fb2ee4424afd30608bfb465eeBarry Hayes                    const StaticField *f = &thisClass->sfields[i];
34403aa70ae413c6c5fb2ee4424afd30608bfb465eeBarry Hayes
34503aa70ae413c6c5fb2ee4424afd30608bfb465eeBarry Hayes                    t = signatureToBasicTypeAndSize(f->field.signature, &size);
34603aa70ae413c6c5fb2ee4424afd30608bfb465eeBarry Hayes                    hprofAddIdToRecord(rec, hprofLookupStringId(f->field.name));
34703aa70ae413c6c5fb2ee4424afd30608bfb465eeBarry Hayes                    hprofAddU1ToRecord(rec, t);
34803aa70ae413c6c5fb2ee4424afd30608bfb465eeBarry Hayes                    if (size == 1) {
34903aa70ae413c6c5fb2ee4424afd30608bfb465eeBarry Hayes                        hprofAddU1ToRecord(rec, (u1)f->value.b);
35003aa70ae413c6c5fb2ee4424afd30608bfb465eeBarry Hayes                    } else if (size == 2) {
35103aa70ae413c6c5fb2ee4424afd30608bfb465eeBarry Hayes                        hprofAddU2ToRecord(rec, (u2)f->value.c);
35203aa70ae413c6c5fb2ee4424afd30608bfb465eeBarry Hayes                    } else if (size == 4) {
35303aa70ae413c6c5fb2ee4424afd30608bfb465eeBarry Hayes                        hprofAddU4ToRecord(rec, (u4)f->value.i);
35403aa70ae413c6c5fb2ee4424afd30608bfb465eeBarry Hayes                    } else if (size == 8) {
35503aa70ae413c6c5fb2ee4424afd30608bfb465eeBarry Hayes                        hprofAddU8ToRecord(rec, (u8)f->value.j);
35603aa70ae413c6c5fb2ee4424afd30608bfb465eeBarry Hayes                    } else {
35703aa70ae413c6c5fb2ee4424afd30608bfb465eeBarry Hayes                        assert(false);
35803aa70ae413c6c5fb2ee4424afd30608bfb465eeBarry Hayes                    }
359f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                }
360f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
361f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
362f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            /* Instance fields for this class (no superclass fields)
363f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             */
36403aa70ae413c6c5fb2ee4424afd30608bfb465eeBarry Hayes            iFieldCount = thisClass->ifieldCount;
36503aa70ae413c6c5fb2ee4424afd30608bfb465eeBarry Hayes            hprofAddU2ToRecord(rec, (u2)iFieldCount);
36603aa70ae413c6c5fb2ee4424afd30608bfb465eeBarry Hayes            for (i = 0; i < iFieldCount; i++) {
367f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                const InstField *f = &thisClass->ifields[i];
368f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                hprof_basic_type t;
369f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
370f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                t = signatureToBasicTypeAndSize(f->field.signature, NULL);
371f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                hprofAddIdToRecord(rec, hprofLookupStringId(f->field.name));
372f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                hprofAddU1ToRecord(rec, t);
373f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
374f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        } else if (IS_CLASS_FLAG_SET(clazz, CLASS_ISARRAY)) {
375f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            const ArrayObject *aobj = (const ArrayObject *)obj;
376f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            u4 length = aobj->length;
377f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
378f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (IS_CLASS_FLAG_SET(clazz, CLASS_ISOBJECTARRAY)) {
379f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                /* obj is an object array.
380f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                 */
381f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                hprofAddU1ToRecord(rec, HPROF_OBJECT_ARRAY_DUMP);
382f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
383f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                hprofAddIdToRecord(rec, (hprof_object_id)obj);
384f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                hprofAddU4ToRecord(rec, stackTraceSerialNumber(obj));
385f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                hprofAddU4ToRecord(rec, length);
386f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                hprofAddIdToRecord(rec, hprofLookupClassId(clazz));
387f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
388f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                /* Dump the elements, which are always objects or NULL.
389f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                 */
390f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                hprofAddIdListToRecord(rec,
391f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                        (const hprof_object_id *)aobj->contents, length);
392f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            } else {
393f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                hprof_basic_type t;
394f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                size_t size;
395f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
396f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                t = primitiveToBasicTypeAndSize(clazz->elementClass->
397f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                                                primitiveType, &size);
398f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
399f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                /* obj is a primitive array.
400f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                 */
401f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#if DUMP_PRIM_DATA
402f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                hprofAddU1ToRecord(rec, HPROF_PRIMITIVE_ARRAY_DUMP);
403f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#else
404f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                hprofAddU1ToRecord(rec, HPROF_PRIMITIVE_ARRAY_NODATA_DUMP);
405f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#endif
406f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
407f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                hprofAddIdToRecord(rec, (hprof_object_id)obj);
408f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                hprofAddU4ToRecord(rec, stackTraceSerialNumber(obj));
409f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                hprofAddU4ToRecord(rec, length);
410f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                hprofAddU1ToRecord(rec, t);
411f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
412f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#if DUMP_PRIM_DATA
413f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                /* Dump the raw, packed element values.
414f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                 */
415f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                if (size == 1) {
416f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    hprofAddU1ListToRecord(rec, (const u1 *)aobj->contents,
417f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                            length);
418f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                } else if (size == 2) {
419f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    hprofAddU2ListToRecord(rec, (const u2 *)aobj->contents,
420f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                            length);
421f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                } else if (size == 4) {
422f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    hprofAddU4ListToRecord(rec, (const u4 *)aobj->contents,
423f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                            length);
424f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                } else if (size == 8) {
425f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    hprofAddU8ListToRecord(rec, (const u8 *)aobj->contents,
426f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                            length);
427f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                }
428f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#endif
429f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
430f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        } else {
431f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            const ClassObject *sclass;
432f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            size_t sizePatchOffset, savedLen;
433f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
434f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            /* obj is an instance object.
435f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             */
436f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            hprofAddU1ToRecord(rec, HPROF_INSTANCE_DUMP);
437f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            hprofAddIdToRecord(rec, (hprof_object_id)obj);
438f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            hprofAddU4ToRecord(rec, stackTraceSerialNumber(obj));
439f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            hprofAddIdToRecord(rec, hprofLookupClassId(clazz));
440f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
441f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            /* Reserve some space for the length of the instance
442f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * data, which we won't know until we're done writing
443f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * it.
444f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             */
445f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            sizePatchOffset = rec->length;
446f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            hprofAddU4ToRecord(rec, 0x77777777);
447f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
448f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            /* Write the instance data;  fields for this
449f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * class, followed by super class fields, and so on.
450f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             */
451f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            sclass = clazz;
452f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            while (sclass != NULL) {
453f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                int i, ifieldCount;
454f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
455f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                ifieldCount = sclass->ifieldCount;
456f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                for (i = 0; i < ifieldCount; i++) {
457f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    const InstField *f = &sclass->ifields[i];
458f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    hprof_basic_type t;
459f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    size_t size;
460f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
461f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    t = signatureToBasicTypeAndSize(f->field.signature, &size);
462f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    if (size == 1) {
463f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                        hprofAddU1ToRecord(rec,
464f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                                (u1)dvmGetFieldByte(obj, f->byteOffset));
465f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    } else if (size == 2) {
466f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                        hprofAddU2ToRecord(rec,
467f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                                (u2)dvmGetFieldChar(obj, f->byteOffset));
468f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    } else if (size == 4) {
469f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                        hprofAddU4ToRecord(rec,
470f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                                (u4)dvmGetFieldInt(obj, f->byteOffset));
471f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    } else if (size == 8) {
472f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                        hprofAddU8ToRecord(rec,
473f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                                (u8)dvmGetFieldLong(obj, f->byteOffset));
474f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    } else {
475f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                        assert(false);
476f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    }
477f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                }
478f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
479f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                sclass = sclass->super;
480f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
481f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
482f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            /* Patch the instance field length.
483f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             */
484f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            savedLen = rec->length;
485f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            rec->length = sizePatchOffset;
486f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            hprofAddU4ToRecord(rec, savedLen - (sizePatchOffset + 4));
487f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            rec->length = savedLen;
488f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
489f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
490f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
491f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    ctx->objectsInSegment++;
492f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
493f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    return 0;
494f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
495