Merge remote-tracking branch 'redux/master' into sh4-pool
[tamarin-stm.git] / platform / win32 / Vtune.cpp
blobffe1a9a8dec7306026950997aa4a2ca15213ec7b
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
14 * License.
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.
23 * Contributor(s):
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 ***** */
40 #include "avmplus.h"
43 #ifdef VMCFG_VTUNE
44 #include "CodegenLIR.h"
46 namespace vtune
48 using namespace avmplus;
49 static bool vtune_init = false;
50 static iJIT_IsProfilingActiveFlags vtuneStatus;
51 static iJIT_Method_Load ML;
52 static NIns *endAddr;
53 uint32_t line_cap;
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);
78 AvmLog("\n");
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;
90 /**
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)
97 bool hasClass = true;
98 VMPI_memset(idx,0,sizeof(*idx));
99 if (!name)
100 return false;
102 // class
103 // idx[0] = 0;
104 if ((idx[1]=indexOf(name, '.')) >= 0)
105 hasClass = false; // match means no class name
106 else if ((idx[1]=indexOf(name, '$')) >=0)
107 idx[1]; // match
108 else if ((idx[1]=indexOf(name, '/')) >= 0)
109 idx[1]; // match
110 else
111 hasClass = false; // nothing looks like a class here
113 // method
114 if ((idx[2]=lastIndexOf(name, '/')) >= 0)
115 idx[2]++; // match
116 else if ((idx[2]=lastIndexOf(name, ':')) >= 0)
117 idx[2]++; // match
118 else
119 ; // idx[2] = 0;
120 idx[3] = strlen(name);
122 return hasClass;
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);
129 s[len] = 0;
130 return s;
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) {
139 if (!vtune_init) {
140 iJIT_RegisterCallbackEx(0, vtuneCallback);
141 vtune_init = true;
142 vtuneStatus = iJIT_IsProfilingActive();
143 printf("\nVTUNE STATUS %x\n\n", vtuneStatus);
145 StUTF8String namebuf(methodName);
146 const char *name = namebuf.c_str();
147 int idx[4];
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]);
153 if (hasClass) {
154 ML.class_file_name = substring(name, idx[0], idx[1]);
156 line_cap = 0;
157 return &ML;
160 // free stuff
161 void vtuneCleanup(void*) {
162 if (ML.env) {
163 if (ML.class_file_name)
164 VMPI_free(ML.class_file_name);
165 if (ML.method_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));
175 void fixupLines() {
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];
188 table[i] = table[j];
189 table[j] = temp;
191 if (count & 1) {
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;
203 fixupLines();
204 if (ML.line_number_size > 0)
205 dumpVTuneMethodInfo(&ML); // Uncommented to debug VTune
206 iJIT_NotifyEvent(iJVM_EVENT_TYPE_METHOD_LOAD_FINISHED, &ML);
207 vtuneCleanup(h);
210 void vtuneEnd(void*, NIns* end) {
211 endAddr = 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) {
221 if (!line_cap) {
222 line_cap = 4;
223 ML.line_number_table = (pLineNumberInfo) VMPI_alloc(line_cap * sizeof(LineNumberInfo));
224 } else if (ML.line_number_size == line_cap) {
225 line_cap *= 2;
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 */