| /* |
| * 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; |
| } |