1 // Copyright 2019 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #include "src/extensions/vtunedomain-support-extension.h"
6 #include <string>
7 #include <vector>
8 
9 namespace v8 {
10 namespace internal {
11 
12 namespace libvtune {
13 
14 int startTask(const std::vector<std::string>& vparams);
15 int endTask(const std::vector<std::string>& vparams);
16 
17 const auto& function_map =
18     *new std::map<std::string, int (*)(const std::vector<std::string>&)>{
19         {"start", startTask}, {"end", endTask}};
20 
split(const std::string & str,char delimiter,std::vector<std::string> * vparams)21 void split(const std::string& str, char delimiter,
22            std::vector<std::string>* vparams) {
23   std::string::size_type baseindex = 0;
24   std::string::size_type offindex = str.find(delimiter);
25 
26   while (offindex != std::string::npos) {
27     (*vparams).push_back(str.substr(baseindex, offindex - baseindex));
28     baseindex = ++offindex;
29     offindex = str.find(delimiter, offindex);
30 
31     if (offindex == std::string::npos)
32       (*vparams).push_back(str.substr(baseindex, str.length()));
33   }
34 }
35 
startTask(const std::vector<std::string> & vparams)36 int startTask(const std::vector<std::string>& vparams) {
37   int errcode = 0;
38 
39   if (const char* domain_name = vparams[1].c_str()) {
40     if (const char* task_name = vparams[2].c_str()) {
41       if (std::shared_ptr<VTuneDomain> domainptr =
42               VTuneDomain::createDomain(domain_name)) {
43         if (!domainptr->beginTask(task_name)) {
44           errcode += TASK_BEGIN_FAILED;
45         }
46       } else {
47         errcode += CREATE_DOMAIN_FAILED;
48       }
49     } else {
50       errcode += NO_TASK_NAME;
51     }
52 
53   } else {
54     errcode = NO_DOMAIN_NAME;
55   }
56 
57   return errcode;
58 }
59 
endTask(const std::vector<std::string> & vparams)60 int endTask(const std::vector<std::string>& vparams) {
61   int errcode = 0;
62 
63   if (const char* domain_name = vparams[1].c_str()) {
64     if (std::shared_ptr<VTuneDomain> domainptr =
65             VTuneDomain::createDomain(domain_name)) {
66       domainptr->endTask();
67     } else {
68       errcode += CREATE_DOMAIN_FAILED;
69     }
70   } else {
71     errcode = NO_DOMAIN_NAME;
72   }
73 
74   return errcode;
75 }
76 
invoke(const char * params)77 int invoke(const char* params) {
78   int errcode = 0;
79   std::vector<std::string> vparams;
80 
81   split(*(new std::string(params)), ' ', &vparams);
82 
83   auto it = function_map.find(vparams[0]);
84   if (it != function_map.end()) {
85     (it->second)(vparams);
86   } else {
87     errcode += UNKNOWN_PARAMS;
88   }
89 
90   return errcode;
91 }
92 
93 }  // namespace libvtune
94 
95 v8::Local<v8::FunctionTemplate>
GetNativeFunctionTemplate(v8::Isolate * isolate,v8::Local<v8::String> str)96 VTuneDomainSupportExtension::GetNativeFunctionTemplate(
97     v8::Isolate* isolate, v8::Local<v8::String> str) {
98   return v8::FunctionTemplate::New(isolate, VTuneDomainSupportExtension::Mark);
99 }
100 
101 // args should take three parameters
102 // %0 : string, which is the domain name. Domain is used to tagging trace data
103 // for different modules or libraryies in a program
104 // %1 : string, which is the task name. Task is a logical unit of work performed
105 // by a particular thread statement. Task can nest.
106 // %2 : string, "start" / "end". Action to be taken on a task in a particular
107 // domain
Mark(const v8::FunctionCallbackInfo<v8::Value> & args)108 void VTuneDomainSupportExtension::Mark(
109     const v8::FunctionCallbackInfo<v8::Value>& args) {
110   if (args.Length() != 3 || !args[0]->IsString() || !args[1]->IsString() ||
111       !args[2]->IsString()) {
112     args.GetIsolate()->ThrowException(v8::String::NewFromUtf8Literal(
113         args.GetIsolate(),
114         "Parameter number should be exactly three, first domain name"
115         "second task name, third start/end"));
116     return;
117   }
118 
119   v8::Isolate* isolate = args.GetIsolate();
120   v8::String::Utf8Value domainName(isolate, args[0]);
121   v8::String::Utf8Value taskName(isolate, args[1]);
122   v8::String::Utf8Value statName(isolate, args[2]);
123 
124   char* cdomainName = *domainName;
125   char* ctaskName = *taskName;
126   char* cstatName = *statName;
127 
128   std::stringstream params;
129   params << cstatName << " " << cdomainName << " " << ctaskName;
130 
131   int r = 0;
132   if ((r = libvtune::invoke(params.str().c_str())) != 0) {
133     args.GetIsolate()->ThrowException(
134         v8::String::NewFromUtf8(args.GetIsolate(), std::to_string(r).c_str())
135             .ToLocalChecked());
136   }
137 }
138 
139 }  // namespace internal
140 }  // namespace v8
141