Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(183)

Side by Side Diff: src/profile-generator.cc

Issue 2083005: CPU profiler: add secure profiles by filtering out functions using security tokens. (Closed)
Patch Set: Reworded comment Created 10 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « src/profile-generator.h ('k') | src/profile-generator-inl.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2010 the V8 project authors. All rights reserved. 1 // Copyright 2010 the V8 project authors. All rights reserved.
2 // Redistribution and use in source and binary forms, with or without 2 // Redistribution and use in source and binary forms, with or without
3 // modification, are permitted provided that the following conditions are 3 // modification, are permitted provided that the following conditions are
4 // met: 4 // met:
5 // 5 //
6 // * Redistributions of source code must retain the above copyright 6 // * Redistributions of source code must retain the above copyright
7 // notice, this list of conditions and the following disclaimer. 7 // notice, this list of conditions and the following disclaimer.
8 // * Redistributions in binary form must reproduce the above 8 // * Redistributions in binary form must reproduce the above
9 // copyright notice, this list of conditions and the following 9 // copyright notice, this list of conditions and the following
10 // disclaimer in the documentation and/or other materials provided 10 // disclaimer in the documentation and/or other materials provided
(...skipping 10 matching lines...) Expand all
21 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 21 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 22 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 27
28 #ifdef ENABLE_LOGGING_AND_PROFILING 28 #ifdef ENABLE_LOGGING_AND_PROFILING
29 29
30 #include "v8.h" 30 #include "v8.h"
31 #include "global-handles.h"
31 32
32 #include "profile-generator-inl.h" 33 #include "profile-generator-inl.h"
33 34
34 #include "../include/v8-profiler.h" 35 #include "../include/v8-profiler.h"
35 36
36 namespace v8 { 37 namespace v8 {
37 namespace internal { 38 namespace internal {
38 39
39 40
41 TokenEnumerator::TokenEnumerator()
42 : token_locations_(4),
43 token_removed_(4) {
44 }
45
46
47 TokenEnumerator::~TokenEnumerator() {
48 for (int i = 0; i < token_locations_.length(); ++i) {
49 if (!token_removed_[i]) {
50 GlobalHandles::ClearWeakness(token_locations_[i]);
51 GlobalHandles::Destroy(token_locations_[i]);
52 }
53 }
54 }
55
56
57 int TokenEnumerator::GetTokenId(Object* token) {
58 if (token == NULL) return CodeEntry::kNoSecurityToken;
59 for (int i = 0; i < token_locations_.length(); ++i) {
60 if (*token_locations_[i] == token && !token_removed_[i]) return i;
61 }
62 Handle<Object> handle = GlobalHandles::Create(token);
63 // handle.location() points to a memory cell holding a pointer
64 // to a token object in the V8's heap.
65 GlobalHandles::MakeWeak(handle.location(), this, TokenRemovedCallback);
66 token_locations_.Add(handle.location());
67 token_removed_.Add(false);
68 return token_locations_.length() - 1;
69 }
70
71
72 void TokenEnumerator::TokenRemovedCallback(v8::Persistent<v8::Value> handle,
73 void* parameter) {
74 reinterpret_cast<TokenEnumerator*>(parameter)->TokenRemoved(
75 Utils::OpenHandle(*handle).location());
76 }
77
78
79 void TokenEnumerator::TokenRemoved(Object** token_location) {
80 for (int i = 0; i < token_locations_.length(); ++i) {
81 if (token_locations_[i] == token_location && !token_removed_[i]) {
82 token_removed_[i] = true;
83 return;
84 }
85 }
86 }
87
88
40 const char* CodeEntry::kEmptyNamePrefix = ""; 89 const char* CodeEntry::kEmptyNamePrefix = "";
41 unsigned CodeEntry::next_call_uid_ = 1; 90 unsigned CodeEntry::next_call_uid_ = 1;
42 91
43 92
93 void CodeEntry::CopyData(const CodeEntry& source) {
94 call_uid_ = source.call_uid_;
95 tag_ = source.tag_;
96 name_prefix_ = source.name_prefix_;
97 name_ = source.name_;
98 resource_name_ = source.resource_name_;
99 line_number_ = source.line_number_;
100 }
101
102
44 ProfileNode* ProfileNode::FindChild(CodeEntry* entry) { 103 ProfileNode* ProfileNode::FindChild(CodeEntry* entry) {
45 HashMap::Entry* map_entry = 104 HashMap::Entry* map_entry =
46 children_.Lookup(entry, CodeEntryHash(entry), false); 105 children_.Lookup(entry, CodeEntryHash(entry), false);
47 return map_entry != NULL ? 106 return map_entry != NULL ?
48 reinterpret_cast<ProfileNode*>(map_entry->value) : NULL; 107 reinterpret_cast<ProfileNode*>(map_entry->value) : NULL;
49 } 108 }
50 109
51 110
52 ProfileNode* ProfileNode::FindOrAddChild(CodeEntry* entry) { 111 ProfileNode* ProfileNode::FindOrAddChild(CodeEntry* entry) {
53 HashMap::Entry* map_entry = 112 HashMap::Entry* map_entry =
(...skipping 12 matching lines...) Expand all
66 return tree_->TicksToMillis(self_ticks_); 125 return tree_->TicksToMillis(self_ticks_);
67 } 126 }
68 127
69 128
70 double ProfileNode::GetTotalMillis() const { 129 double ProfileNode::GetTotalMillis() const {
71 return tree_->TicksToMillis(total_ticks_); 130 return tree_->TicksToMillis(total_ticks_);
72 } 131 }
73 132
74 133
75 void ProfileNode::Print(int indent) { 134 void ProfileNode::Print(int indent) {
76 OS::Print("%5u %5u %*c %s%s", 135 OS::Print("%5u %5u %*c %s%s [%d]",
77 total_ticks_, self_ticks_, 136 total_ticks_, self_ticks_,
78 indent, ' ', 137 indent, ' ',
79 entry_->name_prefix(), 138 entry_->name_prefix(),
80 entry_->name()); 139 entry_->name(),
140 entry_->security_token_id());
81 if (entry_->resource_name()[0] != '\0') 141 if (entry_->resource_name()[0] != '\0')
82 OS::Print(" %s:%d", entry_->resource_name(), entry_->line_number()); 142 OS::Print(" %s:%d", entry_->resource_name(), entry_->line_number());
83 OS::Print("\n"); 143 OS::Print("\n");
84 for (HashMap::Entry* p = children_.Start(); 144 for (HashMap::Entry* p = children_.Start();
85 p != NULL; 145 p != NULL;
86 p = children_.Next(p)) { 146 p = children_.Next(p)) {
87 reinterpret_cast<ProfileNode*>(p->value)->Print(indent + 2); 147 reinterpret_cast<ProfileNode*>(p->value)->Print(indent + 2);
88 } 148 }
89 } 149 }
90 150
91 151
92 namespace { 152 namespace {
93 153
94 class DeleteNodesCallback { 154 class DeleteNodesCallback {
95 public: 155 public:
156 void BeforeTraversingChild(ProfileNode*, ProfileNode*) { }
157
96 void AfterAllChildrenTraversed(ProfileNode* node) { 158 void AfterAllChildrenTraversed(ProfileNode* node) {
97 delete node; 159 delete node;
98 } 160 }
99 161
100 void AfterChildTraversed(ProfileNode*, ProfileNode*) { } 162 void AfterChildTraversed(ProfileNode*, ProfileNode*) { }
101 }; 163 };
102 164
103 } // namespace 165 } // namespace
104 166
105 167
106 ProfileTree::ProfileTree() 168 ProfileTree::ProfileTree()
107 : root_entry_(Logger::FUNCTION_TAG, "", "(root)", "", 0), 169 : root_entry_(Logger::FUNCTION_TAG,
170 "",
171 "(root)",
172 "",
173 0,
174 CodeEntry::kNoSecurityToken),
108 root_(new ProfileNode(this, &root_entry_)) { 175 root_(new ProfileNode(this, &root_entry_)) {
109 } 176 }
110 177
111 178
112 ProfileTree::~ProfileTree() { 179 ProfileTree::~ProfileTree() {
113 DeleteNodesCallback cb; 180 DeleteNodesCallback cb;
114 TraverseDepthFirstPostOrder(&cb); 181 TraverseDepthFirst(&cb);
115 } 182 }
116 183
117 184
118 void ProfileTree::AddPathFromEnd(const Vector<CodeEntry*>& path) { 185 void ProfileTree::AddPathFromEnd(const Vector<CodeEntry*>& path) {
119 ProfileNode* node = root_; 186 ProfileNode* node = root_;
120 for (CodeEntry** entry = path.start() + path.length() - 1; 187 for (CodeEntry** entry = path.start() + path.length() - 1;
121 entry != path.start() - 1; 188 entry != path.start() - 1;
122 --entry) { 189 --entry) {
123 if (*entry != NULL) { 190 if (*entry != NULL) {
124 node = node->FindOrAddChild(*entry); 191 node = node->FindOrAddChild(*entry);
125 } 192 }
126 } 193 }
127 node->IncrementSelfTicks(); 194 node->IncrementSelfTicks();
128 } 195 }
129 196
130 197
131 void ProfileTree::AddPathFromStart(const Vector<CodeEntry*>& path) { 198 void ProfileTree::AddPathFromStart(const Vector<CodeEntry*>& path) {
132 ProfileNode* node = root_; 199 ProfileNode* node = root_;
133 for (CodeEntry** entry = path.start(); 200 for (CodeEntry** entry = path.start();
134 entry != path.start() + path.length(); 201 entry != path.start() + path.length();
135 ++entry) { 202 ++entry) {
136 if (*entry != NULL) { 203 if (*entry != NULL) {
137 node = node->FindOrAddChild(*entry); 204 node = node->FindOrAddChild(*entry);
138 } 205 }
139 } 206 }
140 node->IncrementSelfTicks(); 207 node->IncrementSelfTicks();
141 } 208 }
142 209
143 210
211 namespace {
212
213 struct NodesPair {
214 NodesPair(ProfileNode* src, ProfileNode* dst)
215 : src(src), dst(dst) { }
216 ProfileNode* src;
217 ProfileNode* dst;
218 };
219
220
221 class FilteredCloneCallback {
222 public:
223 explicit FilteredCloneCallback(ProfileNode* dst_root, int security_token_id)
224 : stack_(10),
225 security_token_id_(security_token_id) {
226 stack_.Add(NodesPair(NULL, dst_root));
227 }
228
229 void BeforeTraversingChild(ProfileNode* parent, ProfileNode* child) {
230 if (IsTokenAcceptable(child->entry()->security_token_id(),
231 parent->entry()->security_token_id())) {
232 ProfileNode* clone = stack_.last().dst->FindOrAddChild(child->entry());
233 clone->IncreaseSelfTicks(child->self_ticks());
234 stack_.Add(NodesPair(child, clone));
235 } else {
236 // Attribute ticks to parent node.
237 stack_.last().dst->IncreaseSelfTicks(child->self_ticks());
238 }
239 }
240
241 void AfterAllChildrenTraversed(ProfileNode* parent) { }
242
243 void AfterChildTraversed(ProfileNode*, ProfileNode* child) {
244 if (stack_.last().src == child) {
245 stack_.RemoveLast();
246 }
247 }
248
249 private:
250 bool IsTokenAcceptable(int token, int parent_token) {
251 if (token == CodeEntry::kNoSecurityToken
252 || token == security_token_id_) return true;
253 if (token == CodeEntry::kInheritsSecurityToken) {
254 ASSERT(parent_token != CodeEntry::kInheritsSecurityToken);
255 return parent_token == CodeEntry::kNoSecurityToken
256 || parent_token == security_token_id_;
257 }
258 return false;
259 }
260
261 List<NodesPair> stack_;
262 int security_token_id_;
263 };
264
265 } // namespace
266
267 void ProfileTree::FilteredClone(ProfileTree* src, int security_token_id) {
268 ms_to_ticks_scale_ = src->ms_to_ticks_scale_;
269 FilteredCloneCallback cb(root_, security_token_id);
270 src->TraverseDepthFirst(&cb);
271 CalculateTotalTicks();
272 }
273
274
144 void ProfileTree::SetTickRatePerMs(double ticks_per_ms) { 275 void ProfileTree::SetTickRatePerMs(double ticks_per_ms) {
145 ms_to_ticks_scale_ = ticks_per_ms > 0 ? 1.0 / ticks_per_ms : 1.0; 276 ms_to_ticks_scale_ = ticks_per_ms > 0 ? 1.0 / ticks_per_ms : 1.0;
146 } 277 }
147 278
148 279
149 namespace { 280 namespace {
150 281
151 class Position { 282 class Position {
152 public: 283 public:
153 explicit Position(ProfileNode* node) 284 explicit Position(ProfileNode* node)
154 : node(node), child_idx_(0) { } 285 : node(node), child_idx_(0) { }
155 INLINE(ProfileNode* current_child()) { 286 INLINE(ProfileNode* current_child()) {
156 return node->children()->at(child_idx_); 287 return node->children()->at(child_idx_);
157 } 288 }
158 INLINE(bool has_current_child()) { 289 INLINE(bool has_current_child()) {
159 return child_idx_ < node->children()->length(); 290 return child_idx_ < node->children()->length();
160 } 291 }
161 INLINE(void next_child()) { ++child_idx_; } 292 INLINE(void next_child()) { ++child_idx_; }
162 293
163 ProfileNode* node; 294 ProfileNode* node;
164 private: 295 private:
165 int child_idx_; 296 int child_idx_;
166 }; 297 };
167 298
168 } // namespace 299 } // namespace
169 300
170 301
171 // Non-recursive implementation of a depth-first post-order tree traversal. 302 // Non-recursive implementation of a depth-first post-order tree traversal.
172 template <typename Callback> 303 template <typename Callback>
173 void ProfileTree::TraverseDepthFirstPostOrder(Callback* callback) { 304 void ProfileTree::TraverseDepthFirst(Callback* callback) {
174 List<Position> stack(10); 305 List<Position> stack(10);
175 stack.Add(Position(root_)); 306 stack.Add(Position(root_));
176 do { 307 while (stack.length() > 0) {
177 Position& current = stack.last(); 308 Position& current = stack.last();
178 if (current.has_current_child()) { 309 if (current.has_current_child()) {
310 callback->BeforeTraversingChild(current.node, current.current_child());
179 stack.Add(Position(current.current_child())); 311 stack.Add(Position(current.current_child()));
180 } else { 312 } else {
181 callback->AfterAllChildrenTraversed(current.node); 313 callback->AfterAllChildrenTraversed(current.node);
182 if (stack.length() > 1) { 314 if (stack.length() > 1) {
183 Position& parent = stack[stack.length() - 2]; 315 Position& parent = stack[stack.length() - 2];
184 callback->AfterChildTraversed(parent.node, current.node); 316 callback->AfterChildTraversed(parent.node, current.node);
185 parent.next_child(); 317 parent.next_child();
186 // Remove child from the stack.
187 stack.RemoveLast();
188 } 318 }
319 // Remove child from the stack.
320 stack.RemoveLast();
189 } 321 }
190 } while (stack.length() > 1 || stack.last().has_current_child()); 322 }
191 } 323 }
192 324
193 325
194 namespace { 326 namespace {
195 327
196 class CalculateTotalTicksCallback { 328 class CalculateTotalTicksCallback {
197 public: 329 public:
330 void BeforeTraversingChild(ProfileNode*, ProfileNode*) { }
331
198 void AfterAllChildrenTraversed(ProfileNode* node) { 332 void AfterAllChildrenTraversed(ProfileNode* node) {
199 node->IncreaseTotalTicks(node->self_ticks()); 333 node->IncreaseTotalTicks(node->self_ticks());
200 } 334 }
201 335
202 void AfterChildTraversed(ProfileNode* parent, ProfileNode* child) { 336 void AfterChildTraversed(ProfileNode* parent, ProfileNode* child) {
203 parent->IncreaseTotalTicks(child->total_ticks()); 337 parent->IncreaseTotalTicks(child->total_ticks());
204 } 338 }
205 }; 339 };
206 340
207 } // namespace 341 } // namespace
208 342
209 343
210 void ProfileTree::CalculateTotalTicks() { 344 void ProfileTree::CalculateTotalTicks() {
211 CalculateTotalTicksCallback cb; 345 CalculateTotalTicksCallback cb;
212 TraverseDepthFirstPostOrder(&cb); 346 TraverseDepthFirst(&cb);
213 } 347 }
214 348
215 349
216 void ProfileTree::ShortPrint() { 350 void ProfileTree::ShortPrint() {
217 OS::Print("root: %u %u %.2fms %.2fms\n", 351 OS::Print("root: %u %u %.2fms %.2fms\n",
218 root_->total_ticks(), root_->self_ticks(), 352 root_->total_ticks(), root_->self_ticks(),
219 root_->GetTotalMillis(), root_->GetSelfMillis()); 353 root_->GetTotalMillis(), root_->GetSelfMillis());
220 } 354 }
221 355
222 356
223 void CpuProfile::AddPath(const Vector<CodeEntry*>& path) { 357 void CpuProfile::AddPath(const Vector<CodeEntry*>& path) {
224 top_down_.AddPathFromEnd(path); 358 top_down_.AddPathFromEnd(path);
225 bottom_up_.AddPathFromStart(path); 359 bottom_up_.AddPathFromStart(path);
226 } 360 }
227 361
228 362
229 void CpuProfile::CalculateTotalTicks() { 363 void CpuProfile::CalculateTotalTicks() {
230 top_down_.CalculateTotalTicks(); 364 top_down_.CalculateTotalTicks();
231 bottom_up_.CalculateTotalTicks(); 365 bottom_up_.CalculateTotalTicks();
232 } 366 }
233 367
234 368
235 void CpuProfile::SetActualSamplingRate(double actual_sampling_rate) { 369 void CpuProfile::SetActualSamplingRate(double actual_sampling_rate) {
236 top_down_.SetTickRatePerMs(actual_sampling_rate); 370 top_down_.SetTickRatePerMs(actual_sampling_rate);
237 bottom_up_.SetTickRatePerMs(actual_sampling_rate); 371 bottom_up_.SetTickRatePerMs(actual_sampling_rate);
238 } 372 }
239 373
240 374
375 CpuProfile* CpuProfile::FilteredClone(int security_token_id) {
376 ASSERT(security_token_id != CodeEntry::kNoSecurityToken);
377 CpuProfile* clone = new CpuProfile(title_, uid_);
378 clone->top_down_.FilteredClone(&top_down_, security_token_id);
379 clone->bottom_up_.FilteredClone(&bottom_up_, security_token_id);
380 return clone;
381 }
382
383
241 void CpuProfile::ShortPrint() { 384 void CpuProfile::ShortPrint() {
242 OS::Print("top down "); 385 OS::Print("top down ");
243 top_down_.ShortPrint(); 386 top_down_.ShortPrint();
244 OS::Print("bottom up "); 387 OS::Print("bottom up ");
245 bottom_up_.ShortPrint(); 388 bottom_up_.ShortPrint();
246 } 389 }
247 390
248 391
249 void CpuProfile::Print() { 392 void CpuProfile::Print() {
250 OS::Print("[Top down]:\n"); 393 OS::Print("[Top down]:\n");
251 top_down_.Print(); 394 top_down_.Print();
252 OS::Print("[Bottom up]:\n"); 395 OS::Print("[Bottom up]:\n");
253 bottom_up_.Print(); 396 bottom_up_.Print();
254 } 397 }
255 398
256 399
257 const CodeMap::CodeTreeConfig::Key CodeMap::CodeTreeConfig::kNoKey = NULL; 400 const CodeMap::CodeTreeConfig::Key CodeMap::CodeTreeConfig::kNoKey = NULL;
258 const CodeMap::CodeTreeConfig::Value CodeMap::CodeTreeConfig::kNoValue = 401 const CodeMap::CodeTreeConfig::Value CodeMap::CodeTreeConfig::kNoValue =
259 CodeMap::CodeEntryInfo(NULL, 0); 402 CodeMap::CodeEntryInfo(NULL, 0);
260 403
261 404
262 void CodeMap::AddAlias(Address alias, Address addr) { 405 void CodeMap::AddAlias(Address start, CodeEntry* entry, Address code_start) {
263 CodeTree::Locator locator; 406 CodeTree::Locator locator;
264 if (tree_.Find(addr, &locator)) { 407 if (tree_.Find(code_start, &locator)) {
265 const CodeEntryInfo& entry_info = locator.value(); 408 const CodeEntryInfo& code_info = locator.value();
266 tree_.Insert(alias, &locator); 409 entry->CopyData(*code_info.entry);
267 locator.set_value(entry_info); 410 tree_.Insert(start, &locator);
411 locator.set_value(CodeEntryInfo(entry, code_info.size));
268 } 412 }
269 } 413 }
270 414
271 415
272 CodeEntry* CodeMap::FindEntry(Address addr) { 416 CodeEntry* CodeMap::FindEntry(Address addr) {
273 CodeTree::Locator locator; 417 CodeTree::Locator locator;
274 if (tree_.FindGreatestLessThan(addr, &locator)) { 418 if (tree_.FindGreatestLessThan(addr, &locator)) {
275 // locator.key() <= addr. Need to check that addr is within entry. 419 // locator.key() <= addr. Need to check that addr is within entry.
276 const CodeEntryInfo& entry = locator.value(); 420 const CodeEntryInfo& entry = locator.value();
277 if (addr < (locator.key() + entry.size)) 421 if (addr < (locator.key() + entry.size))
(...skipping 10 matching lines...) Expand all
288 432
289 433
290 void CodeMap::Print() { 434 void CodeMap::Print() {
291 CodeTreePrinter printer; 435 CodeTreePrinter printer;
292 tree_.ForEach(&printer); 436 tree_.ForEach(&printer);
293 } 437 }
294 438
295 439
296 CpuProfilesCollection::CpuProfilesCollection() 440 CpuProfilesCollection::CpuProfilesCollection()
297 : function_and_resource_names_(StringsMatch), 441 : function_and_resource_names_(StringsMatch),
298 profiles_uids_(CpuProfilesMatch), 442 profiles_uids_(UidsMatch),
299 current_profiles_semaphore_(OS::CreateSemaphore(1)) { 443 current_profiles_semaphore_(OS::CreateSemaphore(1)) {
444 // Create list of unabridged profiles.
445 profiles_by_token_.Add(new List<CpuProfile*>());
300 } 446 }
301 447
302 448
303 static void DeleteArgsCountName(char** name_ptr) { 449 static void DeleteArgsCountName(char** name_ptr) {
304 DeleteArray(*name_ptr); 450 DeleteArray(*name_ptr);
305 } 451 }
306 452
307 453
308 static void DeleteCodeEntry(CodeEntry** entry_ptr) { 454 static void DeleteCodeEntry(CodeEntry** entry_ptr) {
309 delete *entry_ptr; 455 delete *entry_ptr;
310 } 456 }
311 457
312 static void DeleteCpuProfile(CpuProfile** profile_ptr) { 458 static void DeleteCpuProfile(CpuProfile** profile_ptr) {
313 delete *profile_ptr; 459 delete *profile_ptr;
314 } 460 }
315 461
462 static void DeleteProfilesList(List<CpuProfile*>** list_ptr) {
463 (*list_ptr)->Iterate(DeleteCpuProfile);
464 delete *list_ptr;
465 }
316 466
317 CpuProfilesCollection::~CpuProfilesCollection() { 467 CpuProfilesCollection::~CpuProfilesCollection() {
318 delete current_profiles_semaphore_; 468 delete current_profiles_semaphore_;
319 current_profiles_.Iterate(DeleteCpuProfile); 469 current_profiles_.Iterate(DeleteCpuProfile);
320 profiles_.Iterate(DeleteCpuProfile); 470 profiles_by_token_.Iterate(DeleteProfilesList);
321 code_entries_.Iterate(DeleteCodeEntry); 471 code_entries_.Iterate(DeleteCodeEntry);
322 args_count_names_.Iterate(DeleteArgsCountName); 472 args_count_names_.Iterate(DeleteArgsCountName);
323 for (HashMap::Entry* p = function_and_resource_names_.Start(); 473 for (HashMap::Entry* p = function_and_resource_names_.Start();
324 p != NULL; 474 p != NULL;
325 p = function_and_resource_names_.Next(p)) { 475 p = function_and_resource_names_.Next(p)) {
326 DeleteArray(reinterpret_cast<const char*>(p->value)); 476 DeleteArray(reinterpret_cast<const char*>(p->value));
327 } 477 }
328 } 478 }
329 479
330 480
(...skipping 11 matching lines...) Expand all
342 current_profiles_semaphore_->Signal(); 492 current_profiles_semaphore_->Signal();
343 return true; 493 return true;
344 } 494 }
345 495
346 496
347 bool CpuProfilesCollection::StartProfiling(String* title, unsigned uid) { 497 bool CpuProfilesCollection::StartProfiling(String* title, unsigned uid) {
348 return StartProfiling(GetName(title), uid); 498 return StartProfiling(GetName(title), uid);
349 } 499 }
350 500
351 501
352 CpuProfile* CpuProfilesCollection::StopProfiling(const char* title, 502 CpuProfile* CpuProfilesCollection::StopProfiling(int security_token_id,
503 const char* title,
353 double actual_sampling_rate) { 504 double actual_sampling_rate) {
354 const int title_len = StrLength(title); 505 const int title_len = StrLength(title);
355 CpuProfile* profile = NULL; 506 CpuProfile* profile = NULL;
356 current_profiles_semaphore_->Wait(); 507 current_profiles_semaphore_->Wait();
357 for (int i = current_profiles_.length() - 1; i >= 0; --i) { 508 for (int i = current_profiles_.length() - 1; i >= 0; --i) {
358 if (title_len == 0 || strcmp(current_profiles_[i]->title(), title) == 0) { 509 if (title_len == 0 || strcmp(current_profiles_[i]->title(), title) == 0) {
359 profile = current_profiles_.Remove(i); 510 profile = current_profiles_.Remove(i);
360 break; 511 break;
361 } 512 }
362 } 513 }
363 current_profiles_semaphore_->Signal(); 514 current_profiles_semaphore_->Signal();
364 515
365 if (profile != NULL) { 516 if (profile != NULL) {
366 profile->CalculateTotalTicks(); 517 profile->CalculateTotalTicks();
367 profile->SetActualSamplingRate(actual_sampling_rate); 518 profile->SetActualSamplingRate(actual_sampling_rate);
368 profiles_.Add(profile); 519 List<CpuProfile*>* unabridged_list =
520 profiles_by_token_[TokenToIndex(CodeEntry::kNoSecurityToken)];
521 unabridged_list->Add(profile);
369 HashMap::Entry* entry = 522 HashMap::Entry* entry =
370 profiles_uids_.Lookup(reinterpret_cast<void*>(profile->uid()), 523 profiles_uids_.Lookup(reinterpret_cast<void*>(profile->uid()),
371 static_cast<uint32_t>(profile->uid()), 524 static_cast<uint32_t>(profile->uid()),
372 true); 525 true);
373 ASSERT(entry->value == NULL); 526 ASSERT(entry->value == NULL);
374 entry->value = profile; 527 entry->value = reinterpret_cast<void*>(unabridged_list->length() - 1);
528 return GetProfile(security_token_id, profile->uid());
375 } 529 }
376 return profile; 530 return NULL;
377 } 531 }
378 532
379 533
380 CpuProfile* CpuProfilesCollection::StopProfiling(String* title, 534 CpuProfile* CpuProfilesCollection::StopProfiling(int security_token_id,
535 String* title,
381 double actual_sampling_rate) { 536 double actual_sampling_rate) {
382 return StopProfiling(GetName(title), actual_sampling_rate); 537 return StopProfiling(security_token_id, GetName(title), actual_sampling_rate);
383 } 538 }
384 539
385 540
386 CpuProfile* CpuProfilesCollection::GetProfile(unsigned uid) { 541 CpuProfile* CpuProfilesCollection::GetProfile(int security_token_id,
542 unsigned uid) {
387 HashMap::Entry* entry = profiles_uids_.Lookup(reinterpret_cast<void*>(uid), 543 HashMap::Entry* entry = profiles_uids_.Lookup(reinterpret_cast<void*>(uid),
388 static_cast<uint32_t>(uid), 544 static_cast<uint32_t>(uid),
389 false); 545 false);
390 return entry != NULL ? reinterpret_cast<CpuProfile*>(entry->value) : NULL; 546 int index;
547 if (entry != NULL) {
548 index = reinterpret_cast<int>(entry->value);
549 } else {
550 return NULL;
551 }
552 List<CpuProfile*>* unabridged_list =
553 profiles_by_token_[TokenToIndex(CodeEntry::kNoSecurityToken)];
554 if (security_token_id == CodeEntry::kNoSecurityToken) {
555 return unabridged_list->at(index);
556 }
557 List<CpuProfile*>* list = GetProfilesList(security_token_id);
558 if (list->at(index) == NULL) {
559 list->at(index) =
560 unabridged_list->at(index)->FilteredClone(security_token_id);
561 }
562 return list->at(index);
391 } 563 }
392 564
393 565
566 int CpuProfilesCollection::TokenToIndex(int security_token_id) {
567 ASSERT(CodeEntry::kNoSecurityToken == -1);
568 return security_token_id + 1; // kNoSecurityToken -> 0, 0 -> 1, ...
569 }
570
571
572 List<CpuProfile*>* CpuProfilesCollection::GetProfilesList(
573 int security_token_id) {
574 const int index = TokenToIndex(security_token_id);
575 profiles_by_token_.AddBlock(NULL, profiles_by_token_.length() - index + 1);
576 List<CpuProfile*>* unabridged_list =
577 profiles_by_token_[TokenToIndex(CodeEntry::kNoSecurityToken)];
578 const int current_count = unabridged_list->length();
579 if (profiles_by_token_[index] == NULL) {
580 profiles_by_token_[index] = new List<CpuProfile*>(current_count);
581 }
582 List<CpuProfile*>* list = profiles_by_token_[index];
583 list->AddBlock(NULL, current_count - list->length());
584 return list;
585 }
586
587
588 List<CpuProfile*>* CpuProfilesCollection::Profiles(int security_token_id) {
589 List<CpuProfile*>* unabridged_list =
590 profiles_by_token_[TokenToIndex(CodeEntry::kNoSecurityToken)];
591 if (security_token_id == CodeEntry::kNoSecurityToken) {
592 return unabridged_list;
593 }
594 List<CpuProfile*>* list = GetProfilesList(security_token_id);
595 const int current_count = unabridged_list->length();
596 for (int i = 0; i < current_count; ++i) {
597 if (list->at(i) == NULL) {
598 list->at(i) = unabridged_list->at(i)->FilteredClone(security_token_id);
599 }
600 }
601 return list;
602 }
603
604
394 CodeEntry* CpuProfilesCollection::NewCodeEntry(Logger::LogEventsAndTags tag, 605 CodeEntry* CpuProfilesCollection::NewCodeEntry(Logger::LogEventsAndTags tag,
395 String* name, 606 String* name,
396 String* resource_name, 607 String* resource_name,
397 int line_number) { 608 int line_number) {
398 CodeEntry* entry = new CodeEntry(tag, 609 CodeEntry* entry = new CodeEntry(tag,
399 CodeEntry::kEmptyNamePrefix, 610 CodeEntry::kEmptyNamePrefix,
400 GetFunctionName(name), 611 GetFunctionName(name),
401 GetName(resource_name), 612 GetName(resource_name),
402 line_number); 613 line_number,
614 CodeEntry::kNoSecurityToken);
403 code_entries_.Add(entry); 615 code_entries_.Add(entry);
404 return entry; 616 return entry;
405 } 617 }
406 618
407 619
408 CodeEntry* CpuProfilesCollection::NewCodeEntry(Logger::LogEventsAndTags tag, 620 CodeEntry* CpuProfilesCollection::NewCodeEntry(Logger::LogEventsAndTags tag,
409 const char* name) { 621 const char* name) {
410 CodeEntry* entry = new CodeEntry(tag, 622 CodeEntry* entry = new CodeEntry(tag,
411 CodeEntry::kEmptyNamePrefix, 623 CodeEntry::kEmptyNamePrefix,
412 GetFunctionName(name), 624 GetFunctionName(name),
413 "", 625 "",
414 v8::CpuProfileNode::kNoLineNumberInfo); 626 v8::CpuProfileNode::kNoLineNumberInfo,
627 CodeEntry::kNoSecurityToken);
415 code_entries_.Add(entry); 628 code_entries_.Add(entry);
416 return entry; 629 return entry;
417 } 630 }
418 631
419 632
420 CodeEntry* CpuProfilesCollection::NewCodeEntry(Logger::LogEventsAndTags tag, 633 CodeEntry* CpuProfilesCollection::NewCodeEntry(Logger::LogEventsAndTags tag,
421 const char* name_prefix, 634 const char* name_prefix,
422 String* name) { 635 String* name) {
423 CodeEntry* entry = new CodeEntry(tag, 636 CodeEntry* entry = new CodeEntry(tag,
424 name_prefix, 637 name_prefix,
425 GetName(name), 638 GetName(name),
426 "", 639 "",
427 v8::CpuProfileNode::kNoLineNumberInfo); 640 v8::CpuProfileNode::kNoLineNumberInfo,
641 CodeEntry::kInheritsSecurityToken);
428 code_entries_.Add(entry); 642 code_entries_.Add(entry);
429 return entry; 643 return entry;
430 } 644 }
431 645
432 646
433 CodeEntry* CpuProfilesCollection::NewCodeEntry(Logger::LogEventsAndTags tag, 647 CodeEntry* CpuProfilesCollection::NewCodeEntry(Logger::LogEventsAndTags tag,
434 int args_count) { 648 int args_count) {
435 CodeEntry* entry = new CodeEntry(tag, 649 CodeEntry* entry = new CodeEntry(tag,
436 "args_count: ", 650 "args_count: ",
437 GetName(args_count), 651 GetName(args_count),
438 "", 652 "",
439 v8::CpuProfileNode::kNoLineNumberInfo); 653 v8::CpuProfileNode::kNoLineNumberInfo,
654 CodeEntry::kInheritsSecurityToken);
440 code_entries_.Add(entry); 655 code_entries_.Add(entry);
441 return entry; 656 return entry;
442 } 657 }
658
659
660 CodeEntry* CpuProfilesCollection::NewCodeEntry(int security_token_id) {
661 CodeEntry* entry = new CodeEntry(security_token_id);
662 code_entries_.Add(entry);
663 return entry;
664 }
443 665
444 666
445 const char* CpuProfilesCollection::GetName(String* name) { 667 const char* CpuProfilesCollection::GetName(String* name) {
446 if (name->IsString()) { 668 if (name->IsString()) {
447 char* c_name = 669 char* c_name =
448 name->ToCString(DISALLOW_NULLS, ROBUST_STRING_TRAVERSAL).Detach(); 670 name->ToCString(DISALLOW_NULLS, ROBUST_STRING_TRAVERSAL).Detach();
449 HashMap::Entry* cache_entry = 671 HashMap::Entry* cache_entry =
450 function_and_resource_names_.Lookup(c_name, 672 function_and_resource_names_.Lookup(c_name,
451 name->Hash(), 673 name->Hash(),
452 true); 674 true);
(...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after
540 memset(entry, 0, entries.length() * sizeof(*entry)); 762 memset(entry, 0, entries.length() * sizeof(*entry));
541 if (sample.pc != NULL) { 763 if (sample.pc != NULL) {
542 *entry++ = code_map_.FindEntry(sample.pc); 764 *entry++ = code_map_.FindEntry(sample.pc);
543 765
544 if (sample.function != NULL) { 766 if (sample.function != NULL) {
545 *entry = code_map_.FindEntry(sample.function); 767 *entry = code_map_.FindEntry(sample.function);
546 if (*entry != NULL && !(*entry)->is_js_function()) { 768 if (*entry != NULL && !(*entry)->is_js_function()) {
547 *entry = NULL; 769 *entry = NULL;
548 } else { 770 } else {
549 CodeEntry* pc_entry = *entries.start(); 771 CodeEntry* pc_entry = *entries.start();
550 if (pc_entry == NULL || pc_entry->is_js_function()) 772 if (pc_entry == NULL) {
551 *entry = NULL; 773 *entry = NULL;
774 } else if (pc_entry->is_js_function()) {
775 // Use function entry in favor of pc entry, as function
776 // entry has security token.
777 *entries.start() = NULL;
778 }
552 } 779 }
553 entry++; 780 entry++;
554 } 781 }
555 782
556 for (const Address *stack_pos = sample.stack, 783 for (const Address *stack_pos = sample.stack,
557 *stack_end = stack_pos + sample.frames_count; 784 *stack_end = stack_pos + sample.frames_count;
558 stack_pos != stack_end; 785 stack_pos != stack_end;
559 ++stack_pos) { 786 ++stack_pos) {
560 *entry++ = code_map_.FindEntry(*stack_pos); 787 *entry++ = code_map_.FindEntry(*stack_pos);
561 } 788 }
(...skipping 12 matching lines...) Expand all
574 *entry++ = EntryForVMState(sample.state); 801 *entry++ = EntryForVMState(sample.state);
575 } 802 }
576 } 803 }
577 804
578 profiles_->AddPathToCurrentProfiles(entries); 805 profiles_->AddPathToCurrentProfiles(entries);
579 } 806 }
580 807
581 } } // namespace v8::internal 808 } } // namespace v8::internal
582 809
583 #endif // ENABLE_LOGGING_AND_PROFILING 810 #endif // ENABLE_LOGGING_AND_PROFILING
OLDNEW
« no previous file with comments | « src/profile-generator.h ('k') | src/profile-generator-inl.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698