| /* |
| * Copyright (C) 2008 The Android Open Source Project |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| /* |
| * Common string pool for the profiler |
| */ |
| #include "Hprof.h" |
| |
| static HashTable *gStringHashTable; |
| |
| int hprofStartup_String() |
| { |
| gStringHashTable = dvmHashTableCreate(512, free); |
| if (gStringHashTable == NULL) { |
| return UNIQUE_ERROR(); |
| } |
| return 0; |
| } |
| |
| int hprofShutdown_String() |
| { |
| dvmHashTableFree(gStringHashTable); |
| return 0; |
| } |
| |
| static u4 computeUtf8Hash(const char *str) |
| { |
| u4 hash = 0; |
| const char *cp; |
| char c; |
| |
| cp = str; |
| while ((c = *cp++) != '\0') { |
| hash = hash * 31 + c; |
| } |
| |
| return hash; |
| } |
| |
| hprof_string_id hprofLookupStringId(const char *str) |
| { |
| void *val; |
| u4 hashValue; |
| |
| dvmHashTableLock(gStringHashTable); |
| |
| hashValue = computeUtf8Hash(str); |
| val = dvmHashTableLookup(gStringHashTable, hashValue, (void *)str, |
| (HashCompareFunc)strcmp, false); |
| if (val == NULL) { |
| const char *newStr; |
| |
| newStr = strdup(str); |
| val = dvmHashTableLookup(gStringHashTable, hashValue, (void *)newStr, |
| (HashCompareFunc)strcmp, true); |
| assert(val != NULL); |
| } |
| |
| dvmHashTableUnlock(gStringHashTable); |
| |
| return (hprof_string_id)val; |
| } |
| |
| int hprofDumpStrings(hprof_context_t *ctx) |
| { |
| HashIter iter; |
| hprof_record_t *rec = &ctx->curRec; |
| int err; |
| |
| dvmHashTableLock(gStringHashTable); |
| |
| for (err = 0, dvmHashIterBegin(gStringHashTable, &iter); |
| err == 0 && !dvmHashIterDone(&iter); |
| dvmHashIterNext(&iter)) |
| { |
| err = hprofStartNewRecord(ctx, HPROF_TAG_STRING, HPROF_TIME); |
| if (err == 0) { |
| const char *str; |
| |
| str = (const char *)dvmHashIterData(&iter); |
| assert(str != NULL); |
| |
| /* STRING format: |
| * |
| * ID: ID for this string |
| * [u1]*: UTF8 characters for string (NOT NULL terminated) |
| * (the record format encodes the length) |
| * |
| * We use the address of the string data as its ID. |
| */ |
| err = hprofAddU4ToRecord(rec, (u4)str); |
| if (err == 0) { |
| err = hprofAddUtf8StringToRecord(rec, str); |
| } |
| } |
| } |
| |
| dvmHashTableUnlock(gStringHashTable); |
| |
| return err; |
| } |