/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you 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.
*/ /* * author Tomas Hurka * Ian Formanek * Misha Dmitriev
*/
/** * The Profiler tracks methods on the stack using an ID which is a Java int (jint). * It uses this ID to ask our DLL for the method's name. The JVM tracks methods * by their jmethodid which is the same size as a pointer. * * Conversion of jmethodids to jints: * On a 32-bit JVM this is trivial since they are the same size, * just a cast is needed. * On 64-bit we keep an array of jmethodids seen so far and the integer ID is the * index of the jmethodid in this array. Getting the jmethodid from the ID is an * array lookup. Getting the ID of a jmethod ID would be a linear scan of the array * but we use a hash-table to speed things up. *
*/ #ifdef NEEDS_CONVERSION /* Hash table entry */ struct entry
{
jmethodID id;
jint key;
}; /* Array of IDs */ static jmethodID *ids = NULL; staticint ids_size; /* Hash table */ struct entry *entries = NULL; staticint entries_size; /* Current count of tracked IDs */ staticint id_count; /* Resize table when id_count exceeds this threshold. * i.e. before the table is full.
*/ staticint resize_threshold;
static uint32_t jmethodid_hashcode(jmethodID jmethod)
{ // This is an unsigned version of Long#hashCode
uintptr_t ptr = (intptr_t)jmethod; return (uint32_t)(ptr ^ (ptr >> 32));
}
/** * Increase the size of the hash table. * Copy the old entries across, rehashing everything according * to the new size
*/ staticvoid growTable()
{ int newsize = (entries_size * 2) + 1; // fprintf(stderr, "*** Now growing table from %d to %d\n", entries_size, newsize); int i; struct entry *newentries = calloc(newsize, sizeof(struct entry));
assert(newentries); for (i = 0; i < entries_size; ++i)
{ if (entries[i].id)
{
uint32_t pos = jmethodid_hashcode(entries[i].id) % newsize; while (newentries[pos].id)
{
pos = (pos + 1) % newsize;
}
newentries[pos].id = entries[i].id;
newentries[pos].key = entries[i].key;
}
}
entries_size = newsize;
resize_threshold = newsize * 3 / 4;
free(entries);
entries = newentries;
} /** * Create table with initial size *
*/ staticvoid createTable()
{
assert(ids == NULL);
assert(entries == NULL); // fprintf(stderr, "*** now setting up table\n");
ids_size = entries_size = 97;
id_count = 0;
resize_threshold = entries_size * 3 / 4;
ids = calloc(ids_size, sizeof(jmethodID));
entries = calloc(entries_size, sizeof(struct entry));
} static jint convert_jmethodID_to_jint(jmethodID jmethod)
{ if (entries == NULL)
{
createTable();
assert(entries);
} int pos = jmethodid_hashcode(jmethod) % entries_size;
assert(pos >= 0 && pos < entries_size); /* Starting from the position given by the hashcode, find * the next free slot (id == 0).
*/ while (entries[pos].id)
{ if (entries[pos].id == jmethod)
{ return entries[pos].key;
}
pos = (pos + 1) % entries_size;
} if (id_count < resize_threshold)
{ /* Put into the hash table */
entries[pos].id = jmethod;
entries[pos].key = id_count; // fprintf(stderr, "*** Now convert %p to %d\n", jmethod, id_count); /* and put in the array */ if (id_count >= ids_size)
{
jmethodID *oldids = ids;
ids_size *= 2;
ids = calloc(ids_size, sizeof(jmethodID));
assert(ids);
memcpy(ids, oldids, id_count * sizeof(jmethodID));
free(oldids);
}
ids[id_count] = jmethod;
id_count++; return entries[pos].key;
} else
{ /* If the table is getting full, enlarge it and try again */
growTable(); return convert_jmethodID_to_jint(jmethod);
}
}
staticvoid copy_into_data_array(char *s) { int len = strlen(s); if (dataOfs + len > byteDataLen) {
jbyte *oldByteData = byteData; int newLen = byteDataLen * 2;
/* this one Deallocate call frees all data allocated by GetAllStackTraces */
err = (*_jvmti)->Deallocate(_jvmti, (unsignedchar*)stack_info);
assert(err == JVMTI_ERROR_NONE);
free(state_buffer);
}
¤ Dauer der Verarbeitung: 0.17 Sekunden
(vorverarbeitet)
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung ist noch experimentell.