V8 API Reference, 7.2.502.16 (for Deno 0.2.4)
vtune-jit.cc
1 /*
2  This file is provided under a dual BSD/GPLv2 license. When using or
3  redistributing this file, you may do so under either license.
4 
5  GPL LICENSE SUMMARY
6 
7  Copyright(c) 2005-2012 Intel Corporation. All rights reserved.
8 
9  This program is free software; you can redistribute it and/or modify
10  it under the terms of version 2 of the GNU General Public License as
11  published by the Free Software Foundation.
12 
13  This program is distributed in the hope that it will be useful, but
14  WITHOUT ANY WARRANTY; without even the implied warranty of
15  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16  General Public License for more details.
17 
18  You should have received a copy of the GNU General Public License
19  along with this program; if not, write to the Free Software
20  Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
21  The full GNU General Public License is included in this distribution
22  in the file called LICENSE.GPL.
23 
24  Contact Information:
25  http://software.intel.com/en-us/articles/intel-vtune-amplifier-xe/
26 
27  BSD LICENSE
28 
29  Copyright(c) 2005-2012 Intel Corporation. All rights reserved.
30  All rights reserved.
31 
32  Redistribution and use in source and binary forms, with or without
33  modification, are permitted provided that the following conditions
34  are met:
35 
36  * Redistributions of source code must retain the above copyright
37  notice, this list of conditions and the following disclaimer.
38  * Redistributions in binary form must reproduce the above copyright
39  notice, this list of conditions and the following disclaimer in
40  the documentation and/or other materials provided with the
41  distribution.
42  * Neither the name of Intel Corporation nor the names of its
43  contributors may be used to endorse or promote products derived
44  from this software without specific prior written permission.
45 
46  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
47  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
48  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
49  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
50  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
51  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
52  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
53  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
54  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
55  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
56  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
57 */
58 
59 #include <stdlib.h>
60 #include <string.h>
61 
62 #include <list>
63 #include <unordered_map>
64 
65 #include "v8-vtune.h"
66 #include "vtune-jit.h"
67 
68 namespace vTune {
69 namespace internal {
70 
71 
72 // This class is used to record the JITted code position info for JIT
73 // code profiling.
75  public:
76  JITCodeLineInfo() { }
77 
78  void SetPosition(intptr_t pc, int pos) {
79  AddCodeLineInfo(LineNumInfo(pc, pos));
80  }
81 
82  struct LineNumInfo {
83  LineNumInfo(intptr_t pc, int pos)
84  : pc_(pc), pos_(pos) { }
85 
86  intptr_t pc_;
87  int pos_;
88  };
89 
90  std::list<LineNumInfo>* GetLineNumInfo() {
91  return &line_num_info_;
92  }
93 
94  private:
95  void AddCodeLineInfo(const LineNumInfo& line_info) {
96  line_num_info_.push_back(line_info);
97  }
98  std::list<LineNumInfo> line_num_info_;
99 };
100 
102  bool operator () (void* key1, void* key2) const {
103  return key1 == key2;
104  }
105 };
106 
108  uint32_t operator () (void* code) const {
109  static const uintptr_t kGoldenRatio = 2654435761u;
110  uintptr_t hash = reinterpret_cast<uintptr_t>(code);
111  return static_cast<uint32_t>(hash * kGoldenRatio);
112  }
113 };
114 
115 typedef std::unordered_map<void*, void*, HashForCodeObject, SameCodeObjects>
116  JitInfoMap;
117 
118 static JitInfoMap* GetEntries() {
119  static JitInfoMap* entries;
120  if (entries == NULL) {
121  entries = new JitInfoMap();
122  }
123  return entries;
124 }
125 
126 static bool IsLineInfoTagged(void* ptr) {
127  return 0 != (reinterpret_cast<intptr_t>(ptr));
128 }
129 
130 static JITCodeLineInfo* UntagLineInfo(void* ptr) {
131  return reinterpret_cast<JITCodeLineInfo*>(
132  reinterpret_cast<intptr_t>(ptr));
133 }
134 
135 // The parameter str is a mixed pattern which contains the
136 // function name and some other info. It comes from all the
137 // Logger::CodeCreateEvent(...) function. This function get the
138 // pure function name from the input parameter.
139 static char* GetFunctionNameFromMixedName(const char* str, int length) {
140  int index = 0;
141  int count = 0;
142  char* start_ptr = NULL;
143 
144  while (str[index++] != ':' && (index < length)) {}
145 
146  if (str[index] == '*' || str[index] == '~' ) index++;
147  if (index >= length) return NULL;
148 
149  start_ptr = const_cast<char*>(str + index);
150 
151  while (index < length && str[index++] != ' ') {
152  count++;
153  }
154 
155  char* result = new char[count + 1];
156  memcpy(result, start_ptr, count);
157  result[count] = '\0';
158 
159  return result;
160 }
161 
162 // The JitCodeEventHandler for Vtune.
163 void VTUNEJITInterface::event_handler(const v8::JitCodeEvent* event) {
164  if (VTUNERUNNING && event != NULL) {
165  switch (event->type) {
166  case v8::JitCodeEvent::CODE_ADDED: {
167  char* temp_file_name = NULL;
168  char* temp_method_name =
169  GetFunctionNameFromMixedName(event->name.str,
170  static_cast<int>(event->name.len));
171  iJIT_Method_Load jmethod;
172  memset(&jmethod, 0, sizeof jmethod);
173  jmethod.method_id = iJIT_GetNewMethodID();
174  jmethod.method_load_address = event->code_start;
175  jmethod.method_size = static_cast<unsigned int>(event->code_len);
176  jmethod.method_name = temp_method_name;
177 
178  Local<UnboundScript> script = event->script;
179 
180  if (*script != NULL) {
181  // Get the source file name and set it to jmethod.source_file_name
182  if ((*script->GetScriptName())->IsString()) {
183  Local<String> script_name =
184  Local<String>::Cast(script->GetScriptName());
185  temp_file_name =
186  new char[script_name->Utf8Length(event->isolate) + 1];
187  script_name->WriteUtf8(event->isolate, temp_file_name);
188  jmethod.source_file_name = temp_file_name;
189  }
190 
191  JitInfoMap::iterator entry =
192  GetEntries()->find(event->code_start);
193  if (entry != GetEntries()->end() && IsLineInfoTagged(entry->first)) {
194  JITCodeLineInfo* line_info = UntagLineInfo(entry->second);
195  // Get the line_num_info and set it to jmethod.line_number_table
196  std::list<JITCodeLineInfo::LineNumInfo>* vtunelineinfo =
197  line_info->GetLineNumInfo();
198 
199  jmethod.line_number_size = (unsigned int)vtunelineinfo->size();
200  jmethod.line_number_table =
201  reinterpret_cast<LineNumberInfo*>(
202  malloc(sizeof(LineNumberInfo)*jmethod.line_number_size));
203 
204  std::list<JITCodeLineInfo::LineNumInfo>::iterator Iter;
205  int index = 0;
206  for (Iter = vtunelineinfo->begin();
207  Iter != vtunelineinfo->end();
208  Iter++) {
209  jmethod.line_number_table[index].Offset =
210  static_cast<unsigned int>(Iter->pc_);
211  jmethod.line_number_table[index++].LineNumber =
212  script->GetLineNumber(Iter->pos_) + 1;
213  }
214  GetEntries()->erase(event->code_start);
215  }
216  }
217 
218  iJIT_NotifyEvent(iJVM_EVENT_TYPE_METHOD_LOAD_FINISHED,
219  reinterpret_cast<void*>(&jmethod));
220  if (temp_method_name)
221  delete []temp_method_name;
222  if (temp_file_name)
223  delete []temp_file_name;
224  break;
225  }
226  // TODO(chunyang.dai@intel.com): code_move will be supported.
227  case v8::JitCodeEvent::CODE_MOVED:
228  break;
229  // Currently the CODE_REMOVED event is not issued.
230  case v8::JitCodeEvent::CODE_REMOVED:
231  break;
232  case v8::JitCodeEvent::CODE_ADD_LINE_POS_INFO: {
233  JITCodeLineInfo* line_info =
234  reinterpret_cast<JITCodeLineInfo*>(event->user_data);
235  if (line_info != NULL) {
236  line_info->SetPosition(static_cast<intptr_t>(event->line_info.offset),
237  static_cast<int>(event->line_info.pos));
238  }
239  break;
240  }
241  case v8::JitCodeEvent::CODE_START_LINE_INFO_RECORDING: {
242  v8::JitCodeEvent* temp_event = const_cast<v8::JitCodeEvent*>(event);
243  temp_event->user_data = new JITCodeLineInfo();
244  break;
245  }
246  case v8::JitCodeEvent::CODE_END_LINE_INFO_RECORDING: {
247  GetEntries()->insert(std::pair <void*, void*>(event->code_start, event->user_data));
248  break;
249  }
250  default:
251  break;
252  }
253  }
254  return;
255 }
256 
257 } // namespace internal
258 
259 v8::JitCodeEventHandler GetVtuneCodeEventHandler() {
260  v8::V8::SetFlagsFromString("--nocompact_code_space",
261  (int)strlen("--nocompact_code_space"));
262  return vTune::internal::VTUNEJITInterface::event_handler;
263 }
264 
265 } // namespace vTune
static V8_INLINE Local< T > Cast(Local< S > that)
Definition: v8.h:251
Definition: v8-vtune.h:63