Reland "Support Intel VTune ITT API"

This is a reland of 5f5b4b0407

Original change's description:
> Support Intel VTune ITT API
> 
> Add VTune domain support extension to use VTune Domain/Task API and
> tagging trace data for particular JS code block.
> 
> How to use:
> 1. Set `"checkout_ittapi" = True` in the custom_vars section of .gclient
> file to download intel/ittapi by 'gclient sync'
> 2. Build d8 with gn build flag 'v8_enable_vtunetracemark = true'
> 3. Run d8 with flag '--enable-vtune-domain-support'
> 
> The Vtune Domain/Task API can be invoked from JS to mark JS code block.
> You can mark the start of a JS task by
>     vtunedomainmark(domain_name, task_name, "start")
> and the end of a task by
>     vtunedomainmark(domain_name, task_name, "end")
> Tasks can nest.
> 
> The VTune API (ittapi) is integrated as an external third party library
> while the v8_vtune_jit also relies on the VTune ittapi. We have another
> patch almost ready which refactors the v8_vtune_jit related code to
> depend on the third_party/ittapi. We will submit the refactored v8_vtune_jit
> code after this patch stabilized and landed.
> 
> 
> Contributed by fanchen.kong@intel.com
> 
> Change-Id: I0ecc9dd4e1ea52545f1b6932fcdadfa7c1a6d2b2
> Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/1938490
> Commit-Queue: Shiyu Zhang <shiyu.zhang@intel.com>
> Reviewed-by: Hannes Payer <hpayer@chromium.org>
> Reviewed-by: Toon Verwaest <verwaest@chromium.org>
> Cr-Commit-Position: refs/heads/master@{#65409}

Change-Id: I563aa70fa2b8abe34c981af47aa7220cfc2a7edb
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/1963511
Commit-Queue: Toon Verwaest <verwaest@chromium.org>
Reviewed-by: Toon Verwaest <verwaest@chromium.org>
Reviewed-by: Michael Achenbach <machenbach@chromium.org>
Cr-Commit-Position: refs/heads/master@{#65478}
This commit is contained in:
Zhang, Shiyu 2019-12-14 16:46:38 +08:00 committed by Commit Bot
parent 53308bf7c0
commit 0b812b721b
10 changed files with 390 additions and 1 deletions

View File

@ -75,6 +75,9 @@ declare_args() {
# Sets -dENABLE_VTUNE_JIT_INTERFACE.
v8_enable_vtunejit = false
# Sets -dENABLE_VTUNE_TRACEMARK.
v8_enable_vtunetracemark = false
# Sets -dENABLE_HANDLE_ZAPPING.
v8_enable_handle_zapping = true
@ -408,6 +411,9 @@ config("features") {
if (v8_enable_vtunejit) {
defines += [ "ENABLE_VTUNE_JIT_INTERFACE" ]
}
if (v8_enable_vtunetracemark) {
defines += [ "ENABLE_VTUNE_TRACEMARK" ]
}
if (v8_enable_minor_mc) {
defines += [ "ENABLE_MINOR_MC" ]
}
@ -3335,6 +3341,14 @@ v8_source_set("v8_base_without_compiler") {
v8_current_cpu == "s390" || v8_current_cpu == "s390x") {
libs += [ "atomic" ]
}
if (v8_enable_vtunetracemark && (is_linux || is_win)) {
sources += [
"src/extensions/vtunedomain-support-extension.cc",
"src/extensions/vtunedomain-support-extension.h",
]
deps += [ "src/third_party/vtune:v8_vtune_trace_mark" ]
}
}
group("v8_base") {

8
DEPS
View File

@ -27,6 +27,7 @@ vars = {
'checkout_fuchsia_boot_images': "qemu.x64,qemu.arm64",
'checkout_instrumented_libraries': False,
'checkout_ittapi': False,
'chromium_url': 'https://chromium.googlesource.com',
'android_url': 'https://android.googlesource.com',
'download_gcmole': False,
@ -258,6 +259,12 @@ deps = {
Var('chromium_url') + '/external/github.com/google/protobuf'+ '@' + 'b68a347f56137b4b1a746e8c7438495a6ac1bd91',
'v8/third_party/zlib':
Var('chromium_url') + '/chromium/src/third_party/zlib.git'+ '@' + 'd7f3ca98b2b0d5f72656502961a59353791c4f8a',
'v8/third_party/ittapi': {
# Force checkout ittapi libraries to pass v8 header includes check on
# bots that has check_v8_header_includes enabled.
'url': Var('chromium_url') + '/external/github.com/intel/ittapi' + '@' + 'b4ae0122ba749163096058b4f1bb065bf4a7de94',
'condition': "checkout_ittapi or check_v8_header_includes",
},
}
include_rules = [
@ -265,6 +272,7 @@ include_rules = [
'+include',
'+unicode',
'+third_party/fdlibm',
'+third_party/ittapi/include'
]
# checkdeps.py shouldn't check for includes in these directories:

View File

@ -782,7 +782,7 @@
},
'v8_enable_vtunejit': {
'gn_args': 'v8_enable_vtunejit=true',
'gn_args': 'v8_enable_vtunejit=true v8_enable_vtunetracemark=true',
},
'v8_full_debug': {

View File

@ -0,0 +1,144 @@
// Copyright 2019 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "src/extensions/vtunedomain-support-extension.h"
#include <string>
#include <vector>
namespace v8 {
namespace internal {
namespace libvtune {
int startTask(const std::vector<std::string>& vparams);
int endTask(const std::vector<std::string>& vparams);
const auto& function_map =
*new std::map<std::string, int (*)(const std::vector<std::string>&)>{
{"start", startTask}, {"end", endTask}};
void split(const std::string& str, char delimiter,
std::vector<std::string>* vparams) {
std::string::size_type baseindex = 0;
std::string::size_type offindex = str.find(delimiter);
while (offindex != std::string::npos) {
(*vparams).push_back(str.substr(baseindex, offindex - baseindex));
baseindex = ++offindex;
offindex = str.find(delimiter, offindex);
if (offindex == std::string::npos)
(*vparams).push_back(str.substr(baseindex, str.length()));
}
}
int startTask(const std::vector<std::string>& vparams) {
int errcode = 0;
if (const char* domain_name = vparams[1].c_str()) {
if (const char* task_name = vparams[2].c_str()) {
if (std::shared_ptr<VTuneDomain> domainptr =
VTuneDomain::createDomain(domain_name)) {
if (!domainptr->beginTask(task_name)) {
errcode += TASK_BEGIN_FAILED;
}
} else {
errcode += CREATE_DOMAIN_FAILED;
}
} else {
errcode += NO_TASK_NAME;
}
} else {
errcode = NO_DOMAIN_NAME;
}
return errcode;
}
int endTask(const std::vector<std::string>& vparams) {
int errcode = 0;
if (const char* domain_name = vparams[1].c_str()) {
if (std::shared_ptr<VTuneDomain> domainptr =
VTuneDomain::createDomain(domain_name)) {
domainptr->endTask();
} else {
errcode += CREATE_DOMAIN_FAILED;
}
} else {
errcode = NO_DOMAIN_NAME;
}
return errcode;
}
int invoke(const char* params) {
int errcode = 0;
std::vector<std::string> vparams;
split(*(new std::string(params)), ' ', &vparams);
auto it = function_map.find(vparams[0]);
if (it != function_map.end()) {
(it->second)(vparams);
} else {
errcode += UNKNOWN_PARAMS;
}
return errcode;
}
} // namespace libvtune
v8::Local<v8::FunctionTemplate>
VTuneDomainSupportExtension::GetNativeFunctionTemplate(
v8::Isolate* isolate, v8::Local<v8::String> str) {
return v8::FunctionTemplate::New(isolate, VTuneDomainSupportExtension::Mark);
}
// args should take three parameters
// %0 : string, which is the domain name. Domain is used to tagging trace data
// for different modules or libraryies in a program
// %1 : string, which is the task name. Task is a logical unit of work performed
// by a particular thread statement. Task can nest.
// %2 : string, "start" / "end". Action to be taken on a task in a particular
// domain
void VTuneDomainSupportExtension::Mark(
const v8::FunctionCallbackInfo<v8::Value>& args) {
if (args.Length() != 3 || !args[0]->IsString() || !args[1]->IsString() ||
!args[2]->IsString()) {
args.GetIsolate()->ThrowException(
v8::String::NewFromUtf8(
args.GetIsolate(),
"Parameter number should be exactly three, first domain name"
"second task name, third start/end",
NewStringType::kNormal)
.ToLocalChecked());
return;
}
v8::Isolate* isolate = args.GetIsolate();
v8::String::Utf8Value domainName(isolate, args[0]);
v8::String::Utf8Value taskName(isolate, args[1]);
v8::String::Utf8Value statName(isolate, args[2]);
char* cdomainName = *domainName;
char* ctaskName = *taskName;
char* cstatName = *statName;
std::stringstream params;
params << cstatName << " " << cdomainName << " " << ctaskName;
int r = 0;
if ((r = libvtune::invoke(params.str().c_str())) != 0) {
args.GetIsolate()->ThrowException(
v8::String::NewFromUtf8(args.GetIsolate(), std::to_string(r).c_str(),
NewStringType::kNormal)
.ToLocalChecked());
}
}
} // namespace internal
} // namespace v8

View File

@ -0,0 +1,47 @@
// Copyright 2019 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef V8_EXTENSIONS_VTUNEDOMAIN_SUPPORT_EXTENSION_H_
#define V8_EXTENSIONS_VTUNEDOMAIN_SUPPORT_EXTENSION_H_
#include "include/v8.h"
#include "src/third_party/vtune/vtuneapi.h"
#include "src/utils/utils.h"
#define UNKNOWN_PARAMS 1 << 0
#define NO_DOMAIN_NAME 1 << 1
#define CREATE_DOMAIN_FAILED 1 << 2
#define NO_TASK_NAME 1 << 3
#define CREATE_TASK_FAILED 1 << 4
#define TASK_BEGIN_FAILED 1 << 5
#define TASK_END_FAILED 1 << 6
namespace v8 {
namespace internal {
class VTuneDomainSupportExtension : public v8::Extension {
public:
explicit VTuneDomainSupportExtension(const char* fun_name = "test")
: v8::Extension("v8/vtunedomain",
BuildSource(buffer_, sizeof(buffer_), fun_name)) {}
v8::Local<v8::FunctionTemplate> GetNativeFunctionTemplate(
v8::Isolate* isolate, v8::Local<v8::String> name) override;
private:
static void Mark(const v8::FunctionCallbackInfo<v8::Value>& args);
static const char* BuildSource(char* buf, size_t size, const char* fun_name) {
SNPrintF(Vector<char>(buf, static_cast<int>(size)), "native function %s();",
fun_name);
return buf;
}
char buffer_[50];
};
} // namespace internal
} // namespace v8
#endif // V8_EXTENSIONS_VTUNEDOMAIN_SUPPORT_EXTENSION_H_

View File

@ -1080,6 +1080,9 @@ DEFINE_BOOL(disallow_code_generation_from_strings, false,
DEFINE_BOOL(expose_async_hooks, false, "expose async_hooks object")
DEFINE_STRING(expose_cputracemark_as, nullptr,
"expose cputracemark extension under the specified name")
#ifdef ENABLE_VTUNE_TRACEMARK
DEFINE_BOOL(enable_vtune_domain_support, true, "enable vtune domain support")
#endif // ENABLE_VTUNE_TRACEMARK
// builtins.cc
DEFINE_BOOL(allow_unsafe_function_constructor, false,

View File

@ -19,6 +19,9 @@
#include "src/extensions/ignition-statistics-extension.h"
#include "src/extensions/statistics-extension.h"
#include "src/extensions/trigger-failure-extension.h"
#ifdef ENABLE_VTUNE_TRACEMARK
#include "src/extensions/vtunedomain-support-extension.h"
#endif // ENABLE_VTUNE_TRACEMARK
#include "src/heap/heap-inl.h"
#include "src/logging/counters.h"
#include "src/numbers/math-random.h"
@ -130,6 +133,10 @@ void Bootstrapper::InitializeOncePerProcess() {
v8::RegisterExtension(
std::make_unique<CpuTraceMarkExtension>(FLAG_expose_cputracemark_as));
}
#ifdef ENABLE_VTUNE_TRACEMARK
v8::RegisterExtension(
std::make_unique<VTuneDomainSupportExtension>("vtunedomainmark"));
#endif // ENABLE_VTUNE_TRACEMARK
}
void Bootstrapper::TearDown() {
@ -5032,6 +5039,10 @@ bool Genesis::InstallExtensions(Isolate* isolate,
&extension_states)) &&
(!isValidCpuTraceMarkFunctionName() ||
InstallExtension(isolate, "v8/cpumark", &extension_states)) &&
#ifdef ENABLE_VTUNE_TRACEMARK
(!FLAG_enable_vtune_domain_support ||
InstallExtension(isolate, "v8/vtunedomain", &extension_states)) &&
#endif // ENABLE_VTUNE_TRACEMARK
InstallRequestedExtensions(isolate, extensions, &extension_states);
}

View File

@ -4,6 +4,13 @@
import("//build/toolchain/toolchain.gni")
config("vtune_ittapi") {
include_dirs = [
"../../../third_party/ittapi/include",
"../../../third_party/ittapi/src/ittnotify",
]
}
static_library("v8_vtune") {
sources = [
"ittnotify_config.h",
@ -18,3 +25,27 @@ static_library("v8_vtune") {
"../../..:v8",
]
}
static_library("v8_vtune_trace_mark") {
sources = [
"../../../third_party/ittapi/include/ittnotify.h",
"vtuneapi.cc",
"vtuneapi.h",
]
deps = [
":ittnotify",
]
}
static_library("ittnotify") {
sources = [
"../../../third_party/ittapi/include/ittnotify.h",
"../../../third_party/ittapi/include/legacy/ittnotify.h",
"../../../third_party/ittapi/src/ittnotify/disable-warnings.h",
"../../../third_party/ittapi/src/ittnotify/ittnotify_config.h",
"../../../third_party/ittapi/src/ittnotify/ittnotify_static.c",
"../../../third_party/ittapi/src/ittnotify/ittnotify_static.h",
]
include_dirs = [ "../../../third_party/ittapi/include" ]
deps = []
}

83
src/third_party/vtune/vtuneapi.cc vendored Normal file
View File

@ -0,0 +1,83 @@
#include "vtuneapi.h"
#ifdef _MSC_VER // for msvc
#include <cstdlib>
#endif
std::map<std::string, std::shared_ptr<VTuneDomain>> VTuneDomain::domains_;
std::map<std::string, __itt_string_handle*> VTuneDomain::string_handlers_;
std::shared_ptr<VTuneDomain> VTuneDomain::createDomain(
const char* domain_name) {
auto domain = getDomain(domain_name);
if (domain == nullptr) {
#ifdef _MSC_VER // for msvc
wchar_t buffer[255];
mbstowcs(buffer, domain_name, 255);
__itt_domain* itt_domain = __itt_domain_create(buffer); // call api
#else // for clang and gcc
__itt_domain* itt_domain = __itt_domain_create(domain_name); // call api
#endif
if (itt_domain != NULL) {
std::string key(domain_name);
std::shared_ptr<VTuneDomain> value(new VTuneDomain(itt_domain));
domain = value;
domains_.insert(std::make_pair(key, value));
}
}
return domain;
}
void VTuneDomain::destroyDomain(const char* domain_name) {
auto it = domains_.find(domain_name);
if (it != domains_.end()) {
domains_.erase(it);
}
}
std::shared_ptr<VTuneDomain> VTuneDomain::getDomain(const char* domain_name) {
std::shared_ptr<VTuneDomain> result(nullptr);
auto it = domains_.find(domain_name);
if (it != domains_.end()) {
result = it->second;
}
return result;
}
__itt_string_handle* VTuneDomain::getString(const char* str) {
__itt_string_handle* result = NULL;
auto it = string_handlers_.find(str);
if (it != string_handlers_.end()) {
result = it->second;
} else {
#ifdef _MSC_VER // for msvc
wchar_t buffer[255];
mbstowcs(buffer, str, 255);
result = __itt_string_handle_create(buffer); // call api
#else // for clang and gcc
result = __itt_string_handle_create(str);
#endif
std::string key(str);
string_handlers_.insert(std::make_pair(key, result));
}
return result;
}
bool VTuneDomain::beginTask(const char* task_name) {
bool result = false;
__itt_string_handle* name = getString(task_name);
if (name != NULL) {
__itt_task_begin(domain_, __itt_null, __itt_null, name);
result = true;
}
return result;
}
void VTuneDomain::endTask() { __itt_task_end(domain_); }

48
src/third_party/vtune/vtuneapi.h vendored Normal file
View File

@ -0,0 +1,48 @@
#ifndef __VTUNE_API_H__
#define __VTUNE_API_H__
#include <map>
#include <memory>
#include <string>
#include "third_party/ittapi/include/ittnotify.h"
class VTuneDomain {
/* factory method to create vtune domain */
public:
/* create vtune domain, domain_name should be unique, if there
already has a domain with same name, return false.
*/
static std::shared_ptr<VTuneDomain> createDomain(const char* domain_name);
/* destory vtune domain*/
static void destroyDomain(const char* domain_name);
/* get a domain */
static std::shared_ptr<VTuneDomain> getDomain(const char* domain_name);
/* domain interface */
public:
/* start a task with name, if no task name or null, use "default_task_name"*/
bool beginTask(const char* task_name = "default_task_name");
/* end a task, if there is no stacked task, return false*/
void endTask();
public:
virtual ~VTuneDomain() {}
protected:
static __itt_string_handle* getString(const char* str);
protected:
VTuneDomain(__itt_domain* domain) { domain_ = domain; }
private:
static std::map<std::string, std::shared_ptr<VTuneDomain>> domains_;
static std::map<std::string, __itt_string_handle*> string_handlers_;
private:
__itt_domain* domain_;
};
#endif