OLD | NEW |
---|---|
1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 the V8 project authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "src/v8.h" | 5 #include "src/v8.h" |
6 | 6 |
7 #include "src/profile-generator-inl.h" | 7 #include "src/profile-generator-inl.h" |
8 | 8 |
9 #include "src/compiler.h" | 9 #include "src/compiler.h" |
10 #include "src/debug.h" | 10 #include "src/debug.h" |
(...skipping 126 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
137 } | 137 } |
138 | 138 |
139 | 139 |
140 const char* const CodeEntry::kEmptyNamePrefix = ""; | 140 const char* const CodeEntry::kEmptyNamePrefix = ""; |
141 const char* const CodeEntry::kEmptyResourceName = ""; | 141 const char* const CodeEntry::kEmptyResourceName = ""; |
142 const char* const CodeEntry::kEmptyBailoutReason = ""; | 142 const char* const CodeEntry::kEmptyBailoutReason = ""; |
143 | 143 |
144 | 144 |
145 CodeEntry::~CodeEntry() { | 145 CodeEntry::~CodeEntry() { |
146 delete no_frame_ranges_; | 146 delete no_frame_ranges_; |
147 delete line_info_; | |
147 } | 148 } |
148 | 149 |
149 | 150 |
150 uint32_t CodeEntry::GetCallUid() const { | 151 uint32_t CodeEntry::GetCallUid() const { |
151 uint32_t hash = ComputeIntegerHash(tag_, v8::internal::kZeroHashSeed); | 152 uint32_t hash = ComputeIntegerHash(tag_, v8::internal::kZeroHashSeed); |
152 if (shared_id_ != 0) { | 153 if (shared_id_ != 0) { |
153 hash ^= ComputeIntegerHash(static_cast<uint32_t>(shared_id_), | 154 hash ^= ComputeIntegerHash(static_cast<uint32_t>(shared_id_), |
154 v8::internal::kZeroHashSeed); | 155 v8::internal::kZeroHashSeed); |
155 } else { | 156 } else { |
156 hash ^= ComputeIntegerHash( | 157 hash ^= ComputeIntegerHash( |
(...skipping 22 matching lines...) Expand all Loading... | |
179 && line_number_ == entry->line_number_))); | 180 && line_number_ == entry->line_number_))); |
180 } | 181 } |
181 | 182 |
182 | 183 |
183 void CodeEntry::SetBuiltinId(Builtins::Name id) { | 184 void CodeEntry::SetBuiltinId(Builtins::Name id) { |
184 tag_ = Logger::BUILTIN_TAG; | 185 tag_ = Logger::BUILTIN_TAG; |
185 builtin_id_ = id; | 186 builtin_id_ = id; |
186 } | 187 } |
187 | 188 |
188 | 189 |
190 int CodeEntry::GetSourceLine(int pc_offset) const { | |
191 if (line_info_ && !line_info_->Empty()) { | |
192 return line_info_->GetSourceLineNumber(pc_offset); | |
193 } | |
194 return v8::CpuProfileNode::kNoLineNumberInfo; | |
195 } | |
196 | |
197 | |
189 ProfileNode* ProfileNode::FindChild(CodeEntry* entry) { | 198 ProfileNode* ProfileNode::FindChild(CodeEntry* entry) { |
190 HashMap::Entry* map_entry = | 199 HashMap::Entry* map_entry = |
191 children_.Lookup(entry, CodeEntryHash(entry), false); | 200 children_.Lookup(entry, CodeEntryHash(entry), false); |
192 return map_entry != NULL ? | 201 return map_entry != NULL ? |
193 reinterpret_cast<ProfileNode*>(map_entry->value) : NULL; | 202 reinterpret_cast<ProfileNode*>(map_entry->value) : NULL; |
194 } | 203 } |
195 | 204 |
196 | 205 |
197 ProfileNode* ProfileNode::FindOrAddChild(CodeEntry* entry) { | 206 ProfileNode* ProfileNode::FindOrAddChild(CodeEntry* entry) { |
198 HashMap::Entry* map_entry = | 207 HashMap::Entry* map_entry = |
199 children_.Lookup(entry, CodeEntryHash(entry), true); | 208 children_.Lookup(entry, CodeEntryHash(entry), true); |
200 if (map_entry->value == NULL) { | 209 if (map_entry->value == NULL) { |
201 // New node added. | 210 // New node added. |
202 ProfileNode* new_node = new ProfileNode(tree_, entry); | 211 ProfileNode* new_node = new ProfileNode(tree_, entry); |
203 map_entry->value = new_node; | 212 map_entry->value = new_node; |
204 children_list_.Add(new_node); | 213 children_list_.Add(new_node); |
205 } | 214 } |
206 return reinterpret_cast<ProfileNode*>(map_entry->value); | 215 return reinterpret_cast<ProfileNode*>(map_entry->value); |
207 } | 216 } |
208 | 217 |
209 | 218 |
219 void ProfileNode::IncrementLineTicks(int src_line) { | |
220 if (src_line == v8::CpuProfileNode::kNoLineNumberInfo) return; | |
221 // Increment a hit counter of a certain source line. | |
222 // Add a new source line if not found. | |
223 HashMap::Entry* e = | |
224 line_ticks_.Lookup(reinterpret_cast<void*>(src_line), src_line, true); | |
225 ASSERT(e); | |
226 e->value = static_cast<char*>(e->value) + 1; | |
227 } | |
228 | |
229 | |
230 bool ProfileNode::GetLineTicks(v8::CpuProfileNode::LineTick* entries, | |
231 unsigned int number) const { | |
yurys
2014/08/08 08:13:23
nit: number -> length
| |
232 if (entries == NULL || number == 0) return false; | |
233 | |
234 unsigned line_number = line_ticks_.occupancy(); | |
yurys
2014/08/08 08:13:23
line_count
| |
235 | |
236 if (line_number == 0) return false; | |
237 if (number < line_number) return false; | |
238 | |
239 v8::CpuProfileNode::LineTick* entry = entries; | |
240 | |
241 for (HashMap::Entry* p = line_ticks_.Start(); | |
242 p != NULL; | |
243 p = line_ticks_.Next(p), entry++) { | |
244 entry->line = reinterpret_cast<uintptr_t>(p->key); | |
245 entry->hit_count = reinterpret_cast<uintptr_t>(p->value); | |
246 } | |
247 | |
248 return true; | |
249 } | |
250 | |
251 | |
210 void ProfileNode::Print(int indent) { | 252 void ProfileNode::Print(int indent) { |
211 base::OS::Print("%5u %*s %s%s %d #%d %s", self_ticks_, indent, "", | 253 base::OS::Print("%5u %*s %s%s %d #%d %s", self_ticks_, indent, "", |
212 entry_->name_prefix(), entry_->name(), entry_->script_id(), | 254 entry_->name_prefix(), entry_->name(), entry_->script_id(), |
213 id(), entry_->bailout_reason()); | 255 id(), entry_->bailout_reason()); |
214 if (entry_->resource_name()[0] != '\0') | 256 if (entry_->resource_name()[0] != '\0') |
215 base::OS::Print(" %s:%d", entry_->resource_name(), entry_->line_number()); | 257 base::OS::Print(" %s:%d", entry_->resource_name(), entry_->line_number()); |
216 base::OS::Print("\n"); | 258 base::OS::Print("\n"); |
217 for (HashMap::Entry* p = children_.Start(); | 259 for (HashMap::Entry* p = children_.Start(); |
218 p != NULL; | 260 p != NULL; |
219 p = children_.Next(p)) { | 261 p = children_.Next(p)) { |
(...skipping 20 matching lines...) Expand all Loading... | |
240 root_(new ProfileNode(this, &root_entry_)) { | 282 root_(new ProfileNode(this, &root_entry_)) { |
241 } | 283 } |
242 | 284 |
243 | 285 |
244 ProfileTree::~ProfileTree() { | 286 ProfileTree::~ProfileTree() { |
245 DeleteNodesCallback cb; | 287 DeleteNodesCallback cb; |
246 TraverseDepthFirst(&cb); | 288 TraverseDepthFirst(&cb); |
247 } | 289 } |
248 | 290 |
249 | 291 |
250 ProfileNode* ProfileTree::AddPathFromEnd(const Vector<CodeEntry*>& path) { | 292 ProfileNode* ProfileTree::AddPathFromEnd(const Vector<CodeEntry*>& path, |
293 int src_line) { | |
251 ProfileNode* node = root_; | 294 ProfileNode* node = root_; |
252 for (CodeEntry** entry = path.start() + path.length() - 1; | 295 for (CodeEntry** entry = path.start() + path.length() - 1; |
253 entry != path.start() - 1; | 296 entry != path.start() - 1; |
254 --entry) { | 297 --entry) { |
255 if (*entry != NULL) { | 298 if (*entry != NULL) { |
256 node = node->FindOrAddChild(*entry); | 299 node = node->FindOrAddChild(*entry); |
257 } | 300 } |
258 } | 301 } |
259 node->IncrementSelfTicks(); | 302 node->IncrementSelfTicks(); |
303 if (src_line != v8::CpuProfileNode::kNoLineNumberInfo) { | |
304 node->IncrementLineTicks(src_line); | |
305 } | |
260 return node; | 306 return node; |
261 } | 307 } |
262 | 308 |
263 | 309 |
264 void ProfileTree::AddPathFromStart(const Vector<CodeEntry*>& path) { | 310 void ProfileTree::AddPathFromStart(const Vector<CodeEntry*>& path, |
311 int src_line) { | |
265 ProfileNode* node = root_; | 312 ProfileNode* node = root_; |
266 for (CodeEntry** entry = path.start(); | 313 for (CodeEntry** entry = path.start(); |
267 entry != path.start() + path.length(); | 314 entry != path.start() + path.length(); |
268 ++entry) { | 315 ++entry) { |
269 if (*entry != NULL) { | 316 if (*entry != NULL) { |
270 node = node->FindOrAddChild(*entry); | 317 node = node->FindOrAddChild(*entry); |
271 } | 318 } |
272 } | 319 } |
273 node->IncrementSelfTicks(); | 320 node->IncrementSelfTicks(); |
321 if (src_line != v8::CpuProfileNode::kNoLineNumberInfo) { | |
322 node->IncrementLineTicks(src_line); | |
323 } | |
274 } | 324 } |
275 | 325 |
276 | 326 |
277 struct NodesPair { | 327 struct NodesPair { |
278 NodesPair(ProfileNode* src, ProfileNode* dst) | 328 NodesPair(ProfileNode* src, ProfileNode* dst) |
279 : src(src), dst(dst) { } | 329 : src(src), dst(dst) { } |
280 ProfileNode* src; | 330 ProfileNode* src; |
281 ProfileNode* dst; | 331 ProfileNode* dst; |
282 }; | 332 }; |
283 | 333 |
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
325 | 375 |
326 | 376 |
327 CpuProfile::CpuProfile(const char* title, bool record_samples) | 377 CpuProfile::CpuProfile(const char* title, bool record_samples) |
328 : title_(title), | 378 : title_(title), |
329 record_samples_(record_samples), | 379 record_samples_(record_samples), |
330 start_time_(base::TimeTicks::HighResolutionNow()) { | 380 start_time_(base::TimeTicks::HighResolutionNow()) { |
331 } | 381 } |
332 | 382 |
333 | 383 |
334 void CpuProfile::AddPath(base::TimeTicks timestamp, | 384 void CpuProfile::AddPath(base::TimeTicks timestamp, |
335 const Vector<CodeEntry*>& path) { | 385 const Vector<CodeEntry*>& path, |
336 ProfileNode* top_frame_node = top_down_.AddPathFromEnd(path); | 386 int src_line) { |
387 ProfileNode* top_frame_node = top_down_.AddPathFromEnd(path, src_line); | |
337 if (record_samples_) { | 388 if (record_samples_) { |
338 timestamps_.Add(timestamp); | 389 timestamps_.Add(timestamp); |
339 samples_.Add(top_frame_node); | 390 samples_.Add(top_frame_node); |
340 } | 391 } |
341 } | 392 } |
342 | 393 |
343 | 394 |
344 void CpuProfile::CalculateTotalTicksAndSamplingRate() { | 395 void CpuProfile::CalculateTotalTicksAndSamplingRate() { |
345 end_time_ = base::TimeTicks::HighResolutionNow(); | 396 end_time_ = base::TimeTicks::HighResolutionNow(); |
346 } | 397 } |
(...skipping 168 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
515 if (profile == finished_profiles_[i]) { | 566 if (profile == finished_profiles_[i]) { |
516 finished_profiles_.Remove(i); | 567 finished_profiles_.Remove(i); |
517 return; | 568 return; |
518 } | 569 } |
519 } | 570 } |
520 UNREACHABLE(); | 571 UNREACHABLE(); |
521 } | 572 } |
522 | 573 |
523 | 574 |
524 void CpuProfilesCollection::AddPathToCurrentProfiles( | 575 void CpuProfilesCollection::AddPathToCurrentProfiles( |
525 base::TimeTicks timestamp, const Vector<CodeEntry*>& path) { | 576 base::TimeTicks timestamp, |
577 const Vector<CodeEntry*>& path, | |
578 int src_line) { | |
526 // As starting / stopping profiles is rare relatively to this | 579 // As starting / stopping profiles is rare relatively to this |
527 // method, we don't bother minimizing the duration of lock holding, | 580 // method, we don't bother minimizing the duration of lock holding, |
528 // e.g. copying contents of the list to a local vector. | 581 // e.g. copying contents of the list to a local vector. |
529 current_profiles_semaphore_.Wait(); | 582 current_profiles_semaphore_.Wait(); |
530 for (int i = 0; i < current_profiles_.length(); ++i) { | 583 for (int i = 0; i < current_profiles_.length(); ++i) { |
531 current_profiles_[i]->AddPath(timestamp, path); | 584 current_profiles_[i]->AddPath(timestamp, path, src_line); |
532 } | 585 } |
533 current_profiles_semaphore_.Signal(); | 586 current_profiles_semaphore_.Signal(); |
534 } | 587 } |
535 | 588 |
536 | 589 |
537 CodeEntry* CpuProfilesCollection::NewCodeEntry( | 590 CodeEntry* CpuProfilesCollection::NewCodeEntry( |
538 Logger::LogEventsAndTags tag, | 591 Logger::LogEventsAndTags tag, |
539 const char* name, | 592 const char* name, |
540 const char* name_prefix, | 593 const char* name_prefix, |
541 const char* resource_name, | 594 const char* resource_name, |
542 int line_number, | 595 int line_number, |
543 int column_number) { | 596 int column_number, |
597 JITLineInfoTable* line_info) { | |
544 CodeEntry* code_entry = new CodeEntry(tag, | 598 CodeEntry* code_entry = new CodeEntry(tag, |
545 name, | 599 name, |
546 name_prefix, | 600 name_prefix, |
547 resource_name, | 601 resource_name, |
548 line_number, | 602 line_number, |
549 column_number); | 603 column_number, |
604 line_info); | |
550 code_entries_.Add(code_entry); | 605 code_entries_.Add(code_entry); |
551 return code_entry; | 606 return code_entry; |
552 } | 607 } |
553 | 608 |
554 | 609 |
555 const char* const ProfileGenerator::kAnonymousFunctionName = | 610 const char* const ProfileGenerator::kAnonymousFunctionName = |
556 "(anonymous function)"; | 611 "(anonymous function)"; |
557 const char* const ProfileGenerator::kProgramEntryName = | 612 const char* const ProfileGenerator::kProgramEntryName = |
558 "(program)"; | 613 "(program)"; |
559 const char* const ProfileGenerator::kIdleEntryName = | 614 const char* const ProfileGenerator::kIdleEntryName = |
(...skipping 19 matching lines...) Expand all Loading... | |
579 } | 634 } |
580 | 635 |
581 | 636 |
582 void ProfileGenerator::RecordTickSample(const TickSample& sample) { | 637 void ProfileGenerator::RecordTickSample(const TickSample& sample) { |
583 // Allocate space for stack frames + pc + function + vm-state. | 638 // Allocate space for stack frames + pc + function + vm-state. |
584 ScopedVector<CodeEntry*> entries(sample.frames_count + 3); | 639 ScopedVector<CodeEntry*> entries(sample.frames_count + 3); |
585 // As actual number of decoded code entries may vary, initialize | 640 // As actual number of decoded code entries may vary, initialize |
586 // entries vector with NULL values. | 641 // entries vector with NULL values. |
587 CodeEntry** entry = entries.start(); | 642 CodeEntry** entry = entries.start(); |
588 memset(entry, 0, entries.length() * sizeof(*entry)); | 643 memset(entry, 0, entries.length() * sizeof(*entry)); |
644 | |
645 // The ProfileNode knows nothing about all versions of generated code for | |
646 // the same JS function. The line number information associated with | |
647 // the latest version of generated code is used to find a source line number | |
648 // for a JS function. Then, the detected source line is passed to | |
649 // ProfileNode to accumulate the samples. | |
650 int src_line = v8::CpuProfileNode::kNoLineNumberInfo; | |
651 | |
589 if (sample.pc != NULL) { | 652 if (sample.pc != NULL) { |
590 if (sample.has_external_callback && sample.state == EXTERNAL && | 653 if (sample.has_external_callback && sample.state == EXTERNAL && |
591 sample.top_frame_type == StackFrame::EXIT) { | 654 sample.top_frame_type == StackFrame::EXIT) { |
592 // Don't use PC when in external callback code, as it can point | 655 // Don't use PC when in external callback code, as it can point |
593 // inside callback's code, and we will erroneously report | 656 // inside callback's code, and we will erroneously report |
594 // that a callback calls itself. | 657 // that a callback calls itself. |
595 *entry++ = code_map_.FindEntry(sample.external_callback); | 658 *entry++ = code_map_.FindEntry(sample.external_callback); |
596 } else { | 659 } else { |
597 Address start; | 660 Address start; |
598 CodeEntry* pc_entry = code_map_.FindEntry(sample.pc, &start); | 661 CodeEntry* pc_entry = code_map_.FindEntry(sample.pc, &start); |
599 // If pc is in the function code before it set up stack frame or after the | 662 // If pc is in the function code before it set up stack frame or after the |
600 // frame was destroyed SafeStackFrameIterator incorrectly thinks that | 663 // frame was destroyed SafeStackFrameIterator incorrectly thinks that |
601 // ebp contains return address of the current function and skips caller's | 664 // ebp contains return address of the current function and skips caller's |
602 // frame. Check for this case and just skip such samples. | 665 // frame. Check for this case and just skip such samples. |
603 if (pc_entry) { | 666 if (pc_entry) { |
604 List<OffsetRange>* ranges = pc_entry->no_frame_ranges(); | 667 List<OffsetRange>* ranges = pc_entry->no_frame_ranges(); |
668 Code* code = Code::cast(HeapObject::FromAddress(start)); | |
669 int pc_offset = static_cast<int>(sample.pc - code->instruction_start()); | |
670 src_line = pc_entry->GetSourceLine(pc_offset); | |
605 if (ranges) { | 671 if (ranges) { |
606 Code* code = Code::cast(HeapObject::FromAddress(start)); | |
607 int pc_offset = static_cast<int>( | |
608 sample.pc - code->instruction_start()); | |
609 for (int i = 0; i < ranges->length(); i++) { | 672 for (int i = 0; i < ranges->length(); i++) { |
610 OffsetRange& range = ranges->at(i); | 673 OffsetRange& range = ranges->at(i); |
611 if (range.from <= pc_offset && pc_offset < range.to) { | 674 if (range.from <= pc_offset && pc_offset < range.to) { |
612 return; | 675 return; |
613 } | 676 } |
614 } | 677 } |
615 } | 678 } |
616 *entry++ = pc_entry; | 679 *entry++ = pc_entry; |
617 | 680 |
618 if (pc_entry->builtin_id() == Builtins::kFunctionCall || | 681 if (pc_entry->builtin_id() == Builtins::kFunctionCall || |
619 pc_entry->builtin_id() == Builtins::kFunctionApply) { | 682 pc_entry->builtin_id() == Builtins::kFunctionApply) { |
620 // When current function is FunctionCall or FunctionApply builtin the | 683 // When current function is FunctionCall or FunctionApply builtin the |
621 // top frame is either frame of the calling JS function or internal | 684 // top frame is either frame of the calling JS function or internal |
622 // frame. In the latter case we know the caller for sure but in the | 685 // frame. In the latter case we know the caller for sure but in the |
623 // former case we don't so we simply replace the frame with | 686 // former case we don't so we simply replace the frame with |
624 // 'unresolved' entry. | 687 // 'unresolved' entry. |
625 if (sample.top_frame_type == StackFrame::JAVA_SCRIPT) { | 688 if (sample.top_frame_type == StackFrame::JAVA_SCRIPT) { |
626 *entry++ = unresolved_entry_; | 689 *entry++ = unresolved_entry_; |
627 } | 690 } |
628 } | 691 } |
629 } | 692 } |
630 } | 693 } |
631 | 694 |
695 bool src_line_not_found = src_line == v8::CpuProfileNode::kNoLineNumberInfo; | |
696 | |
632 for (const Address* stack_pos = sample.stack, | 697 for (const Address* stack_pos = sample.stack, |
633 *stack_end = stack_pos + sample.frames_count; | 698 *stack_end = stack_pos + sample.frames_count; |
634 stack_pos != stack_end; | 699 stack_pos != stack_end; |
635 ++stack_pos) { | 700 ++stack_pos) { |
636 *entry++ = code_map_.FindEntry(*stack_pos); | 701 Address start = NULL; |
702 *entry = code_map_.FindEntry(*stack_pos, &start); | |
703 | |
704 // Skip unresolved frames (e.g. internal frame) and get source line of | |
705 // the JS caller. | |
706 if (src_line_not_found && *entry) { | |
707 Code* code = Code::cast(HeapObject::FromAddress(start)); | |
708 int pc_offset = | |
709 static_cast<int>(*stack_pos - code->instruction_start()); | |
710 src_line = (*entry)->GetSourceLine(pc_offset); | |
711 if (src_line == v8::CpuProfileNode::kNoLineNumberInfo) { | |
712 src_line = (*entry)->line_number(); | |
713 } | |
714 src_line_not_found = false; | |
715 } | |
716 | |
717 entry++; | |
637 } | 718 } |
638 } | 719 } |
639 | 720 |
640 if (FLAG_prof_browser_mode) { | 721 if (FLAG_prof_browser_mode) { |
641 bool no_symbolized_entries = true; | 722 bool no_symbolized_entries = true; |
642 for (CodeEntry** e = entries.start(); e != entry; ++e) { | 723 for (CodeEntry** e = entries.start(); e != entry; ++e) { |
643 if (*e != NULL) { | 724 if (*e != NULL) { |
644 no_symbolized_entries = false; | 725 no_symbolized_entries = false; |
645 break; | 726 break; |
646 } | 727 } |
647 } | 728 } |
648 // If no frames were symbolized, put the VM state entry in. | 729 // If no frames were symbolized, put the VM state entry in. |
649 if (no_symbolized_entries) { | 730 if (no_symbolized_entries) { |
650 *entry++ = EntryForVMState(sample.state); | 731 *entry++ = EntryForVMState(sample.state); |
651 } | 732 } |
652 } | 733 } |
653 | 734 |
654 profiles_->AddPathToCurrentProfiles(sample.timestamp, entries); | 735 profiles_->AddPathToCurrentProfiles(sample.timestamp, entries, src_line); |
655 } | 736 } |
656 | 737 |
657 | 738 |
658 CodeEntry* ProfileGenerator::EntryForVMState(StateTag tag) { | 739 CodeEntry* ProfileGenerator::EntryForVMState(StateTag tag) { |
659 switch (tag) { | 740 switch (tag) { |
660 case GC: | 741 case GC: |
661 return gc_entry_; | 742 return gc_entry_; |
662 case JS: | 743 case JS: |
663 case COMPILER: | 744 case COMPILER: |
664 // DOM events handlers are reported as OTHER / EXTERNAL entries. | 745 // DOM events handlers are reported as OTHER / EXTERNAL entries. |
665 // To avoid confusing people, let's put all these entries into | 746 // To avoid confusing people, let's put all these entries into |
666 // one bucket. | 747 // one bucket. |
667 case OTHER: | 748 case OTHER: |
668 case EXTERNAL: | 749 case EXTERNAL: |
669 return program_entry_; | 750 return program_entry_; |
670 case IDLE: | 751 case IDLE: |
671 return idle_entry_; | 752 return idle_entry_; |
672 default: return NULL; | 753 default: return NULL; |
673 } | 754 } |
674 } | 755 } |
675 | 756 |
676 } } // namespace v8::internal | 757 } } // namespace v8::internal |
OLD | NEW |