blob: 23a1606654841d52fafafac0c5ddaaffb376732a [file] [log] [blame]
/*
* Copyright (c) 2003, 2004, Oracle and/or its affiliates. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* - Neither the name of Oracle nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/* This file contains support for handling frames, or (method,location) pairs. */
#include "hprof.h"
/*
* Frames map 1-to-1 to (methodID,location) pairs.
* When no line number is known, -1 should be used.
*
* Frames are mostly used in traces (see hprof_trace.c) and will be marked
* with their status flag as they are written out to the hprof output file.
*
*/
enum LinenoState {
LINENUM_UNINITIALIZED = 0,
LINENUM_AVAILABLE = 1,
LINENUM_UNAVAILABLE = 2
};
typedef struct FrameKey {
jmethodID method;
jlocation location;
} FrameKey;
typedef struct FrameInfo {
unsigned short lineno;
unsigned char lineno_state; /* LinenoState */
unsigned char status;
SerialNumber serial_num;
} FrameInfo;
static FrameKey*
get_pkey(FrameIndex index)
{
void *key_ptr;
int key_len;
table_get_key(gdata->frame_table, index, &key_ptr, &key_len);
HPROF_ASSERT(key_len==sizeof(FrameKey));
HPROF_ASSERT(key_ptr!=NULL);
return (FrameKey*)key_ptr;
}
static FrameInfo *
get_info(FrameIndex index)
{
FrameInfo *info;
info = (FrameInfo*)table_get_info(gdata->frame_table, index);
return info;
}
static void
list_item(TableIndex i, void *key_ptr, int key_len, void *info_ptr, void *arg)
{
FrameKey key;
FrameInfo *info;
HPROF_ASSERT(key_ptr!=NULL);
HPROF_ASSERT(key_len==sizeof(FrameKey));
HPROF_ASSERT(info_ptr!=NULL);
key = *((FrameKey*)key_ptr);
info = (FrameInfo*)info_ptr;
debug_message(
"Frame 0x%08x: method=%p, location=%d, lineno=%d(%d), status=%d \n",
i, (void*)key.method, (jint)key.location,
info->lineno, info->lineno_state, info->status);
}
void
frame_init(void)
{
gdata->frame_table = table_initialize("Frame",
1024, 1024, 1023, (int)sizeof(FrameInfo));
}
FrameIndex
frame_find_or_create(jmethodID method, jlocation location)
{
FrameIndex index;
static FrameKey empty_key;
FrameKey key;
jboolean new_one;
key = empty_key;
key.method = method;
key.location = location;
new_one = JNI_FALSE;
index = table_find_or_create_entry(gdata->frame_table,
&key, (int)sizeof(key), &new_one, NULL);
if ( new_one ) {
FrameInfo *info;
info = get_info(index);
info->lineno_state = LINENUM_UNINITIALIZED;
if ( location < 0 ) {
info->lineno_state = LINENUM_UNAVAILABLE;
}
info->serial_num = gdata->frame_serial_number_counter++;
}
return index;
}
void
frame_list(void)
{
debug_message(
"--------------------- Frame Table ------------------------\n");
table_walk_items(gdata->frame_table, &list_item, NULL);
debug_message(
"----------------------------------------------------------\n");
}
void
frame_cleanup(void)
{
table_cleanup(gdata->frame_table, NULL, NULL);
gdata->frame_table = NULL;
}
void
frame_set_status(FrameIndex index, jint status)
{
FrameInfo *info;
info = get_info(index);
info->status = (unsigned char)status;
}
void
frame_get_location(FrameIndex index, SerialNumber *pserial_num,
jmethodID *pmethod, jlocation *plocation, jint *plineno)
{
FrameKey *pkey;
FrameInfo *info;
jint lineno;
pkey = get_pkey(index);
*pmethod = pkey->method;
*plocation = pkey->location;
info = get_info(index);
lineno = (jint)info->lineno;
if ( info->lineno_state == LINENUM_UNINITIALIZED ) {
info->lineno_state = LINENUM_UNAVAILABLE;
if ( gdata->lineno_in_traces ) {
if ( pkey->location >= 0 && !isMethodNative(pkey->method) ) {
lineno = getLineNumber(pkey->method, pkey->location);
if ( lineno >= 0 ) {
info->lineno = (unsigned short)lineno; /* save it */
info->lineno_state = LINENUM_AVAILABLE;
}
}
}
}
if ( info->lineno_state == LINENUM_UNAVAILABLE ) {
lineno = -1;
}
*plineno = lineno;
*pserial_num = info->serial_num;
}
jint
frame_get_status(FrameIndex index)
{
FrameInfo *info;
info = get_info(index);
return (jint)info->status;
}