|
1 /* |
|
2 * Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved. |
|
3 * |
|
4 * Redistribution and use in source and binary forms, with or without |
|
5 * modification, are permitted provided that the following conditions |
|
6 * are met: |
|
7 * |
|
8 * - Redistributions of source code must retain the above copyright |
|
9 * notice, this list of conditions and the following disclaimer. |
|
10 * |
|
11 * - Redistributions in binary form must reproduce the above copyright |
|
12 * notice, this list of conditions and the following disclaimer in the |
|
13 * documentation and/or other materials provided with the distribution. |
|
14 * |
|
15 * - Neither the name of Oracle nor the names of its |
|
16 * contributors may be used to endorse or promote products derived |
|
17 * from this software without specific prior written permission. |
|
18 * |
|
19 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS |
|
20 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, |
|
21 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR |
|
22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR |
|
23 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, |
|
24 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, |
|
25 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR |
|
26 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF |
|
27 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING |
|
28 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS |
|
29 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
|
30 */ |
|
31 |
|
32 /* |
|
33 * This source code is provided to illustrate the usage of a given feature |
|
34 * or technique and has been deliberately simplified. Additional steps |
|
35 * required for a production-quality application, such as security checks, |
|
36 * input validation and proper error handling, might not be present in |
|
37 * this sample code. |
|
38 */ |
|
39 |
|
40 |
|
41 /* This file contains support for handling frames, or (method,location) pairs. */ |
|
42 |
|
43 #include "hprof.h" |
|
44 |
|
45 /* |
|
46 * Frames map 1-to-1 to (methodID,location) pairs. |
|
47 * When no line number is known, -1 should be used. |
|
48 * |
|
49 * Frames are mostly used in traces (see hprof_trace.c) and will be marked |
|
50 * with their status flag as they are written out to the hprof output file. |
|
51 * |
|
52 */ |
|
53 |
|
54 enum LinenoState { |
|
55 LINENUM_UNINITIALIZED = 0, |
|
56 LINENUM_AVAILABLE = 1, |
|
57 LINENUM_UNAVAILABLE = 2 |
|
58 }; |
|
59 |
|
60 typedef struct FrameKey { |
|
61 jmethodID method; |
|
62 jlocation location; |
|
63 } FrameKey; |
|
64 |
|
65 typedef struct FrameInfo { |
|
66 unsigned short lineno; |
|
67 unsigned char lineno_state; /* LinenoState */ |
|
68 unsigned char status; |
|
69 SerialNumber serial_num; |
|
70 } FrameInfo; |
|
71 |
|
72 static FrameKey* |
|
73 get_pkey(FrameIndex index) |
|
74 { |
|
75 void *key_ptr; |
|
76 int key_len; |
|
77 |
|
78 table_get_key(gdata->frame_table, index, &key_ptr, &key_len); |
|
79 HPROF_ASSERT(key_len==sizeof(FrameKey)); |
|
80 HPROF_ASSERT(key_ptr!=NULL); |
|
81 return (FrameKey*)key_ptr; |
|
82 } |
|
83 |
|
84 static FrameInfo * |
|
85 get_info(FrameIndex index) |
|
86 { |
|
87 FrameInfo *info; |
|
88 |
|
89 info = (FrameInfo*)table_get_info(gdata->frame_table, index); |
|
90 return info; |
|
91 } |
|
92 |
|
93 static void |
|
94 list_item(TableIndex i, void *key_ptr, int key_len, void *info_ptr, void *arg) |
|
95 { |
|
96 FrameKey key; |
|
97 FrameInfo *info; |
|
98 |
|
99 HPROF_ASSERT(key_ptr!=NULL); |
|
100 HPROF_ASSERT(key_len==sizeof(FrameKey)); |
|
101 HPROF_ASSERT(info_ptr!=NULL); |
|
102 |
|
103 key = *((FrameKey*)key_ptr); |
|
104 info = (FrameInfo*)info_ptr; |
|
105 debug_message( |
|
106 "Frame 0x%08x: method=%p, location=%d, lineno=%d(%d), status=%d \n", |
|
107 i, (void*)key.method, (jint)key.location, |
|
108 info->lineno, info->lineno_state, info->status); |
|
109 } |
|
110 |
|
111 void |
|
112 frame_init(void) |
|
113 { |
|
114 gdata->frame_table = table_initialize("Frame", |
|
115 1024, 1024, 1023, (int)sizeof(FrameInfo)); |
|
116 } |
|
117 |
|
118 FrameIndex |
|
119 frame_find_or_create(jmethodID method, jlocation location) |
|
120 { |
|
121 FrameIndex index; |
|
122 static FrameKey empty_key; |
|
123 FrameKey key; |
|
124 jboolean new_one; |
|
125 |
|
126 key = empty_key; |
|
127 key.method = method; |
|
128 key.location = location; |
|
129 new_one = JNI_FALSE; |
|
130 index = table_find_or_create_entry(gdata->frame_table, |
|
131 &key, (int)sizeof(key), &new_one, NULL); |
|
132 if ( new_one ) { |
|
133 FrameInfo *info; |
|
134 |
|
135 info = get_info(index); |
|
136 info->lineno_state = LINENUM_UNINITIALIZED; |
|
137 if ( location < 0 ) { |
|
138 info->lineno_state = LINENUM_UNAVAILABLE; |
|
139 } |
|
140 info->serial_num = gdata->frame_serial_number_counter++; |
|
141 } |
|
142 return index; |
|
143 } |
|
144 |
|
145 void |
|
146 frame_list(void) |
|
147 { |
|
148 debug_message( |
|
149 "--------------------- Frame Table ------------------------\n"); |
|
150 table_walk_items(gdata->frame_table, &list_item, NULL); |
|
151 debug_message( |
|
152 "----------------------------------------------------------\n"); |
|
153 } |
|
154 |
|
155 void |
|
156 frame_cleanup(void) |
|
157 { |
|
158 table_cleanup(gdata->frame_table, NULL, NULL); |
|
159 gdata->frame_table = NULL; |
|
160 } |
|
161 |
|
162 void |
|
163 frame_set_status(FrameIndex index, jint status) |
|
164 { |
|
165 FrameInfo *info; |
|
166 |
|
167 info = get_info(index); |
|
168 info->status = (unsigned char)status; |
|
169 } |
|
170 |
|
171 void |
|
172 frame_get_location(FrameIndex index, SerialNumber *pserial_num, |
|
173 jmethodID *pmethod, jlocation *plocation, jint *plineno) |
|
174 { |
|
175 FrameKey *pkey; |
|
176 FrameInfo *info; |
|
177 jint lineno; |
|
178 |
|
179 pkey = get_pkey(index); |
|
180 *pmethod = pkey->method; |
|
181 *plocation = pkey->location; |
|
182 info = get_info(index); |
|
183 lineno = (jint)info->lineno; |
|
184 if ( info->lineno_state == LINENUM_UNINITIALIZED ) { |
|
185 info->lineno_state = LINENUM_UNAVAILABLE; |
|
186 if ( gdata->lineno_in_traces ) { |
|
187 if ( pkey->location >= 0 && !isMethodNative(pkey->method) ) { |
|
188 lineno = getLineNumber(pkey->method, pkey->location); |
|
189 if ( lineno >= 0 ) { |
|
190 info->lineno = (unsigned short)lineno; /* save it */ |
|
191 info->lineno_state = LINENUM_AVAILABLE; |
|
192 } |
|
193 } |
|
194 } |
|
195 } |
|
196 if ( info->lineno_state == LINENUM_UNAVAILABLE ) { |
|
197 lineno = -1; |
|
198 } |
|
199 *plineno = lineno; |
|
200 *pserial_num = info->serial_num; |
|
201 } |
|
202 |
|
203 jint |
|
204 frame_get_status(FrameIndex index) |
|
205 { |
|
206 FrameInfo *info; |
|
207 |
|
208 info = get_info(index); |
|
209 return (jint)info->status; |
|
210 } |