1 /* -*- Mode: C++; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 4 -*- */
2 /* vi: set ts=4 sw=4 expandtab: (add to ~/.vimrc: set modeline modelines=5) */
3 /* ***** BEGIN LICENSE BLOCK *****
4 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
6 * The contents of this file are subject to the Mozilla Public License Version
7 * 1.1 (the "License"); you may not use this file except in compliance with
8 * the License. You may obtain a copy of the License at
9 * http://www.mozilla.org/MPL/
11 * Software distributed under the License is distributed on an "AS IS" basis,
12 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
13 * for the specific language governing rights and limitations under the
16 * The Original Code is [Open Source Virtual Machine.].
18 * The Initial Developer of the Original Code is
19 * Adobe System Incorporated.
20 * Portions created by the Initial Developer are Copyright (C) 2004-2006
21 * the Initial Developer. All Rights Reserved.
24 * Adobe AS3 Team. Modified by Shengnan Cong@Intel.
25 * Tamarin. Refactored by Rick Reitmaier
27 * Alternatively, the contents of this file may be used under the terms of
28 * either the GNU General Public License Version 2 or later (the "GPL"), or
29 * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
30 * in which case the provisions of the GPL or the LGPL are applicable instead
31 * of those above. If you wish to allow use of your version of this file only
32 * under the terms of either the GPL or the LGPL, and not to allow others to
33 * use your version of this file under the terms of the MPL, indicate your
34 * decision by deleting the provisions above and replace them with the notice
35 * and other provisions required by the GPL or the LGPL. If you do not delete
36 * the provisions above, a recipient may use your version of this file under
37 * the terms of any one of the MPL, the GPL or the LGPL.
39 * ***** END LICENSE BLOCK ***** */
44 #include "CodegenLIR.h"
48 using namespace avmplus
;
49 static bool vtune_init
= false;
50 static iJIT_IsProfilingActiveFlags vtuneStatus
;
51 static iJIT_Method_Load ML
;
55 void dumpVTuneMethodInfo(iJIT_Method_Load
* ML
)
57 AvmLog("method_id = %d\n", ML
->method_id
);
58 AvmLog("method_name = %s\n", ML
->method_name
);
59 AvmLog("method_load_address = %p\n", ML
->method_load_address
);
60 AvmLog("method_size = %d\n", ML
->method_size
);
61 AvmLog("line_number_size = %d\n", ML
->line_number_size
);
62 AvmLog("line_number_table = %p\n", ML
->line_number_table
);
64 if (ML
->line_number_table
)
66 AvmLog("\tline\toffset\n");
67 LineNumberInfo
* lines
= ML
->line_number_table
;
68 for (int j
= 0; j
< (int) ML
->line_number_size
; j
++) {
69 AvmLog("\t%d\t%d\n", lines
[j
].LineNumber
, lines
[j
].Offset
);
73 AvmLog("class_id = %u\n", ML
->class_id
);
74 AvmLog("class_file_name = '%s'\n", ML
->class_file_name
);
75 AvmLog("source_file_name = '%s'\n", ML
->source_file_name
);
76 AvmLog("user_data = %p\n", ML
->user_data
);
77 AvmLog("user_data_size %u\n", ML
->user_data_size
);
81 static int indexOf(const char *s
, char c
) {
82 const char *found
= strchr(s
, c
);
83 return found
? found
- s
: -1;
85 static int lastIndexOf(const char *s
, char c
) {
86 const char *found
= strrchr(s
, c
);
87 return found
? found
- s
: -1;
91 * parse a given MethodInfo.format() 'ed name and provide
92 * the starting and ending indcies of each
93 * @return true, if a class name exists
95 bool locateNames(const char *name
, int* idx
)
98 VMPI_memset(idx
,0,sizeof(*idx
));
104 if ((idx
[1]=indexOf(name
, '.')) >= 0)
105 hasClass
= false; // match means no class name
106 else if ((idx
[1]=indexOf(name
, '$')) >=0)
108 else if ((idx
[1]=indexOf(name
, '/')) >= 0)
111 hasClass
= false; // nothing looks like a class here
114 if ((idx
[2]=lastIndexOf(name
, '/')) >= 0)
116 else if ((idx
[2]=lastIndexOf(name
, ':')) >= 0)
120 idx
[3] = strlen(name
);
125 static char *substring(const char *str
, int start
, int end
) {
126 int len
= end
- start
;
127 char *s
= (char*) VMPI_alloc(len
+1);
128 strncpy(s
, str
+start
, len
);
133 void vtuneCallback(void *, iJIT_ModeFlags flags
) {
134 printf("XXXXXXXXX mode changed %x\n", flags
);
137 /** initialize vtune interface one time only */
138 void *vtuneInit(avmplus::String
* methodName
) {
140 iJIT_RegisterCallbackEx(0, vtuneCallback
);
142 vtuneStatus
= iJIT_IsProfilingActive();
143 printf("\nVTUNE STATUS %x\n\n", vtuneStatus
);
145 StUTF8String
namebuf(methodName
);
146 const char *name
= namebuf
.c_str();
148 bool hasClass
= locateNames(name
, idx
);
149 AvmAssert(ML
.env
== 0);
150 ML
.env
= iJDE_JittingAPI
;
151 ML
.method_id
= iJIT_GetNewMethodID();
152 ML
.method_name
= substring(name
, idx
[2], idx
[3]);
154 ML
.class_file_name
= substring(name
, idx
[0], idx
[1]);
161 void vtuneCleanup(void*) {
163 if (ML
.class_file_name
)
164 VMPI_free(ML
.class_file_name
);
166 VMPI_free(ML
.method_name
);
167 if (ML
.source_file_name
)
168 VMPI_free(ML
.source_file_name
);
169 if (ML
.line_number_table
)
170 VMPI_free(ML
.line_number_table
);
171 memset(&ML
, 0, sizeof(ML
));
176 // vtune wants lines in sorted order.
177 // fixme: sorted by offset or sorted by line? guessing offset.
178 // table is in order of decreasing offsets. We need to adjust the
179 // offsets relative to start, and put them in increasing order.
180 pLineNumberInfo table
= ML
.line_number_table
;
181 uint32_t count
= ML
.line_number_size
;
182 uint32_t middle
= count
/ 2;
183 uint32_t adj
= ML
.method_size
;
184 for (uint32_t i
=0, j
=count
-1; i
< middle
; i
++, j
--) {
185 table
[i
].Offset
+= adj
;
186 table
[j
].Offset
+= adj
;
187 LineNumberInfo temp
= table
[i
];
192 // odd number of entries, middle entry didn't move or get updated
193 table
[middle
].Offset
+= adj
;
197 /** tell profiler where the method starts */
198 void vtuneStart(void* h
, nanojit::NIns
* start
) {
199 AvmAssert(endAddr
!= 0 && endAddr
> start
);
200 ML
.method_load_address
= start
;
201 ML
.method_size
= (char*)endAddr
- (char*)start
;
204 if (ML
.line_number_size
> 0)
205 dumpVTuneMethodInfo(&ML
); // Uncommented to debug VTune
206 iJIT_NotifyEvent(iJVM_EVENT_TYPE_METHOD_LOAD_FINISHED
, &ML
);
210 void vtuneEnd(void*, NIns
* end
) {
214 void vtuneFile(void*, void* fn
) {
215 StUTF8String
st((String
*)fn
);
216 const char *filename
= st
.c_str();
217 ML
.source_file_name
= substring(filename
, 0, strlen(filename
));
220 void vtuneLine(void*, int line
, NIns
*pos
) {
223 ML
.line_number_table
= (pLineNumberInfo
) VMPI_alloc(line_cap
* sizeof(LineNumberInfo
));
224 } else if (ML
.line_number_size
== line_cap
) {
226 pLineNumberInfo table
= (pLineNumberInfo
) VMPI_alloc(line_cap
* sizeof(LineNumberInfo
));
227 memcpy(table
, ML
.line_number_table
, ML
.line_number_size
*sizeof(LineNumberInfo
));
228 VMPI_free(ML
.line_number_table
);
229 ML
.line_number_table
= table
;
232 // record offset from end for now, will adjust later once we have
233 // the start address.
234 pLineNumberInfo li
= &ML
.line_number_table
[ML
.line_number_size
];
235 ML
.line_number_size
++;
236 li
->LineNumber
= line
;
237 li
->Offset
= (char*)pos
- (char*)endAddr
;
241 #endif /* VMCFG_VTUNE */