1/*
2 * Copyright (C) 2008 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16/*
17 * Common string pool for the profiler
18 */
19#include "Hprof.h"
20
21static HashTable *gStringHashTable;
22
23int hprofStartup_String()
24{
25    gStringHashTable = dvmHashTableCreate(512, free);
26    if (gStringHashTable == NULL) {
27        return UNIQUE_ERROR();
28    }
29    return 0;
30}
31
32int hprofShutdown_String()
33{
34    dvmHashTableFree(gStringHashTable);
35    return 0;
36}
37
38static u4 computeUtf8Hash(const char *str)
39{
40    u4 hash = 0;
41    const char *cp;
42    char c;
43
44    cp = str;
45    while ((c = *cp++) != '\0') {
46        hash = hash * 31 + c;
47    }
48
49    return hash;
50}
51
52hprof_string_id hprofLookupStringId(const char *str)
53{
54    void *val;
55    u4 hashValue;
56
57    dvmHashTableLock(gStringHashTable);
58
59    hashValue = computeUtf8Hash(str);
60    val = dvmHashTableLookup(gStringHashTable, hashValue, (void *)str,
61            (HashCompareFunc)strcmp, false);
62    if (val == NULL) {
63        const char *newStr;
64
65        newStr = strdup(str);
66        val = dvmHashTableLookup(gStringHashTable, hashValue, (void *)newStr,
67                (HashCompareFunc)strcmp, true);
68        assert(val != NULL);
69    }
70
71    dvmHashTableUnlock(gStringHashTable);
72
73    return (hprof_string_id)val;
74}
75
76int hprofDumpStrings(hprof_context_t *ctx)
77{
78    HashIter iter;
79    hprof_record_t *rec = &ctx->curRec;
80    int err;
81
82    dvmHashTableLock(gStringHashTable);
83
84    for (err = 0, dvmHashIterBegin(gStringHashTable, &iter);
85         err == 0 && !dvmHashIterDone(&iter);
86         dvmHashIterNext(&iter))
87    {
88        err = hprofStartNewRecord(ctx, HPROF_TAG_STRING, HPROF_TIME);
89        if (err == 0) {
90            const char *str;
91
92            str = (const char *)dvmHashIterData(&iter);
93            assert(str != NULL);
94
95            /* STRING format:
96             *
97             * ID:     ID for this string
98             * [u1]*:  UTF8 characters for string (NOT NULL terminated)
99             *         (the record format encodes the length)
100             *
101             * We use the address of the string data as its ID.
102             */
103            err = hprofAddU4ToRecord(rec, (u4)str);
104            if (err == 0) {
105                err = hprofAddUtf8StringToRecord(rec, str);
106            }
107        }
108    }
109
110    dvmHashTableUnlock(gStringHashTable);
111
112    return err;
113}
114