OLD | NEW |
1 // Copyright 2006-2008 the V8 project authors. All rights reserved. | 1 // Copyright 2006-2008 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 18 matching lines...) Expand all Loading... |
29 | 29 |
30 #include "frames-inl.h" | 30 #include "frames-inl.h" |
31 #include "mark-compact.h" | 31 #include "mark-compact.h" |
32 #include "scopeinfo.h" | 32 #include "scopeinfo.h" |
33 #include "string-stream.h" | 33 #include "string-stream.h" |
34 #include "top.h" | 34 #include "top.h" |
35 | 35 |
36 namespace v8 { | 36 namespace v8 { |
37 namespace internal { | 37 namespace internal { |
38 | 38 |
| 39 PcToCodeCache::PcToCodeCacheEntry |
| 40 PcToCodeCache::cache_[PcToCodeCache::kPcToCodeCacheSize]; |
| 41 |
| 42 int SafeStackFrameIterator::active_count_ = 0; |
| 43 |
39 // Iterator that supports traversing the stack handlers of a | 44 // Iterator that supports traversing the stack handlers of a |
40 // particular frame. Needs to know the top of the handler chain. | 45 // particular frame. Needs to know the top of the handler chain. |
41 class StackHandlerIterator BASE_EMBEDDED { | 46 class StackHandlerIterator BASE_EMBEDDED { |
42 public: | 47 public: |
43 StackHandlerIterator(const StackFrame* frame, StackHandler* handler) | 48 StackHandlerIterator(const StackFrame* frame, StackHandler* handler) |
44 : limit_(frame->fp()), handler_(handler) { | 49 : limit_(frame->fp()), handler_(handler) { |
45 // Make sure the handler has already been unwound to this frame. | 50 // Make sure the handler has already been unwound to this frame. |
46 ASSERT(frame->sp() <= handler->address()); | 51 ASSERT(frame->sp() <= handler->address()); |
47 } | 52 } |
48 | 53 |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
81 StackFrameIterator::StackFrameIterator(bool use_top, Address fp, Address sp) | 86 StackFrameIterator::StackFrameIterator(bool use_top, Address fp, Address sp) |
82 : STACK_FRAME_TYPE_LIST(INITIALIZE_SINGLETON) | 87 : STACK_FRAME_TYPE_LIST(INITIALIZE_SINGLETON) |
83 frame_(NULL), handler_(NULL), | 88 frame_(NULL), handler_(NULL), |
84 thread_(use_top ? Top::GetCurrentThread() : NULL), | 89 thread_(use_top ? Top::GetCurrentThread() : NULL), |
85 fp_(use_top ? NULL : fp), sp_(sp), | 90 fp_(use_top ? NULL : fp), sp_(sp), |
86 advance_(use_top ? &StackFrameIterator::AdvanceWithHandler : | 91 advance_(use_top ? &StackFrameIterator::AdvanceWithHandler : |
87 &StackFrameIterator::AdvanceWithoutHandler) { | 92 &StackFrameIterator::AdvanceWithoutHandler) { |
88 if (use_top || fp != NULL) { | 93 if (use_top || fp != NULL) { |
89 Reset(); | 94 Reset(); |
90 } | 95 } |
91 JavaScriptFrame_.DisableHeapAccess(); | |
92 } | 96 } |
93 | 97 |
94 #undef INITIALIZE_SINGLETON | 98 #undef INITIALIZE_SINGLETON |
95 | 99 |
96 | 100 |
97 void StackFrameIterator::AdvanceWithHandler() { | 101 void StackFrameIterator::AdvanceWithHandler() { |
98 ASSERT(!done()); | 102 ASSERT(!done()); |
99 // Compute the state of the calling frame before restoring | 103 // Compute the state of the calling frame before restoring |
100 // callee-saved registers and unwinding handlers. This allows the | 104 // callee-saved registers and unwinding handlers. This allows the |
101 // frame code that computes the caller state to access the top | 105 // frame code that computes the caller state to access the top |
(...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
194 return (script->IsScript() && | 198 return (script->IsScript() && |
195 Script::TYPE_NATIVE != Script::cast(script)->type()->value()); | 199 Script::TYPE_NATIVE != Script::cast(script)->type()->value()); |
196 } | 200 } |
197 | 201 |
198 | 202 |
199 // ------------------------------------------------------------------------- | 203 // ------------------------------------------------------------------------- |
200 | 204 |
201 | 205 |
202 SafeStackFrameIterator::SafeStackFrameIterator( | 206 SafeStackFrameIterator::SafeStackFrameIterator( |
203 Address fp, Address sp, Address low_bound, Address high_bound) : | 207 Address fp, Address sp, Address low_bound, Address high_bound) : |
204 low_bound_(low_bound), high_bound_(high_bound), | 208 maintainer_(), low_bound_(low_bound), high_bound_(high_bound), |
205 is_valid_top_( | 209 is_valid_top_( |
206 IsWithinBounds(low_bound, high_bound, | 210 IsWithinBounds(low_bound, high_bound, |
207 Top::c_entry_fp(Top::GetCurrentThread())) && | 211 Top::c_entry_fp(Top::GetCurrentThread())) && |
208 Top::handler(Top::GetCurrentThread()) != NULL), | 212 Top::handler(Top::GetCurrentThread()) != NULL), |
209 is_valid_fp_(IsWithinBounds(low_bound, high_bound, fp)), | 213 is_valid_fp_(IsWithinBounds(low_bound, high_bound, fp)), |
210 is_working_iterator_(is_valid_top_ || is_valid_fp_), | 214 is_working_iterator_(is_valid_top_ || is_valid_fp_), |
211 iteration_done_(!is_working_iterator_), | 215 iteration_done_(!is_working_iterator_), |
212 iterator_(is_valid_top_, is_valid_fp_ ? fp : NULL, sp) { | 216 iterator_(is_valid_top_, is_valid_fp_ ? fp : NULL, sp) { |
213 } | 217 } |
214 | 218 |
(...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
295 void SafeStackTraceFrameIterator::Advance() { | 299 void SafeStackTraceFrameIterator::Advance() { |
296 while (true) { | 300 while (true) { |
297 SafeJavaScriptFrameIterator::Advance(); | 301 SafeJavaScriptFrameIterator::Advance(); |
298 if (done()) return; | 302 if (done()) return; |
299 if (frame()->is_java_script()) return; | 303 if (frame()->is_java_script()) return; |
300 } | 304 } |
301 } | 305 } |
302 #endif | 306 #endif |
303 | 307 |
304 | 308 |
305 // ------------------------------------------------------------------------- | |
306 | |
307 | |
308 void StackHandler::Cook(Code* code) { | |
309 ASSERT(code->contains(pc())); | |
310 set_pc(AddressFrom<Address>(pc() - code->instruction_start())); | |
311 } | |
312 | |
313 | |
314 void StackHandler::Uncook(Code* code) { | |
315 set_pc(code->instruction_start() + OffsetFrom(pc())); | |
316 ASSERT(code->contains(pc())); | |
317 } | |
318 | |
319 | |
320 // ------------------------------------------------------------------------- | |
321 | |
322 | |
323 bool StackFrame::HasHandler() const { | 309 bool StackFrame::HasHandler() const { |
324 StackHandlerIterator it(this, top_handler()); | 310 StackHandlerIterator it(this, top_handler()); |
325 return !it.done(); | 311 return !it.done(); |
326 } | 312 } |
327 | 313 |
328 | 314 void StackFrame::IteratePc(ObjectVisitor* v, |
329 void StackFrame::CookFramesForThread(ThreadLocalTop* thread) { | 315 Address* pc_address, |
330 ASSERT(!thread->stack_is_cooked()); | 316 Code* holder) { |
331 for (StackFrameIterator it(thread); !it.done(); it.Advance()) { | 317 Address pc = *pc_address; |
332 it.frame()->Cook(); | 318 ASSERT(holder->contains(pc)); |
| 319 unsigned pc_offset = pc - holder->instruction_start(); |
| 320 Object* code = holder; |
| 321 v->VisitPointer(&code); |
| 322 if (code != holder) { |
| 323 holder = reinterpret_cast<Code*>(code); |
| 324 pc = holder->instruction_start() + pc_offset; |
| 325 *pc_address = pc; |
333 } | 326 } |
334 thread->set_stack_is_cooked(true); | |
335 } | 327 } |
336 | 328 |
337 | 329 |
338 void StackFrame::UncookFramesForThread(ThreadLocalTop* thread) { | 330 StackFrame::Type StackFrame::ComputeType(State* state) { |
339 ASSERT(thread->stack_is_cooked()); | 331 ASSERT(state->fp != NULL); |
340 for (StackFrameIterator it(thread); !it.done(); it.Advance()) { | 332 if (StandardFrame::IsArgumentsAdaptorFrame(state->fp)) { |
341 it.frame()->Uncook(); | 333 return ARGUMENTS_ADAPTOR; |
342 } | 334 } |
343 thread->set_stack_is_cooked(false); | 335 // The marker and function offsets overlap. If the marker isn't a |
| 336 // smi then the frame is a JavaScript frame -- and the marker is |
| 337 // really the function. |
| 338 const int offset = StandardFrameConstants::kMarkerOffset; |
| 339 Object* marker = Memory::Object_at(state->fp + offset); |
| 340 if (!marker->IsSmi()) return JAVA_SCRIPT; |
| 341 return static_cast<StackFrame::Type>(Smi::cast(marker)->value()); |
344 } | 342 } |
345 | 343 |
346 | 344 |
347 void StackFrame::Cook() { | |
348 Code* code = this->code(); | |
349 ASSERT(code->IsCode()); | |
350 for (StackHandlerIterator it(this, top_handler()); !it.done(); it.Advance()) { | |
351 it.handler()->Cook(code); | |
352 } | |
353 ASSERT(code->contains(pc())); | |
354 set_pc(AddressFrom<Address>(pc() - code->instruction_start())); | |
355 } | |
356 | |
357 | |
358 void StackFrame::Uncook() { | |
359 Code* code = this->code(); | |
360 ASSERT(code->IsCode()); | |
361 for (StackHandlerIterator it(this, top_handler()); !it.done(); it.Advance()) { | |
362 it.handler()->Uncook(code); | |
363 } | |
364 set_pc(code->instruction_start() + OffsetFrom(pc())); | |
365 ASSERT(code->contains(pc())); | |
366 } | |
367 | |
368 | 345 |
369 StackFrame::Type StackFrame::GetCallerState(State* state) const { | 346 StackFrame::Type StackFrame::GetCallerState(State* state) const { |
370 ComputeCallerState(state); | 347 ComputeCallerState(state); |
371 return ComputeType(state); | 348 return ComputeType(state); |
372 } | 349 } |
373 | 350 |
374 | 351 |
375 Code* EntryFrame::unchecked_code() const { | 352 Code* EntryFrame::unchecked_code() const { |
376 return Heap::raw_unchecked_js_entry_code(); | 353 return Heap::raw_unchecked_js_entry_code(); |
377 } | 354 } |
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
418 state->pc_address | 395 state->pc_address |
419 = reinterpret_cast<Address*>(fp() + ExitFrameConstants::kCallerPCOffset); | 396 = reinterpret_cast<Address*>(fp() + ExitFrameConstants::kCallerPCOffset); |
420 } | 397 } |
421 | 398 |
422 | 399 |
423 void ExitFrame::SetCallerFp(Address caller_fp) { | 400 void ExitFrame::SetCallerFp(Address caller_fp) { |
424 Memory::Address_at(fp() + ExitFrameConstants::kCallerFPOffset) = caller_fp; | 401 Memory::Address_at(fp() + ExitFrameConstants::kCallerFPOffset) = caller_fp; |
425 } | 402 } |
426 | 403 |
427 | 404 |
| 405 void ExitFrame::Iterate(ObjectVisitor* v) const { |
| 406 // The arguments are traversed as part of the expression stack of |
| 407 // the calling frame. |
| 408 IteratePc(v, pc_address(), code()); |
| 409 v->VisitPointer(&code_slot()); |
| 410 } |
| 411 |
| 412 |
428 Address ExitFrame::GetCallerStackPointer() const { | 413 Address ExitFrame::GetCallerStackPointer() const { |
429 return fp() + ExitFrameConstants::kCallerSPDisplacement; | 414 return fp() + ExitFrameConstants::kCallerSPDisplacement; |
430 } | 415 } |
431 | 416 |
432 | 417 |
433 Address StandardFrame::GetExpressionAddress(int n) const { | 418 Address StandardFrame::GetExpressionAddress(int n) const { |
434 const int offset = StandardFrameConstants::kExpressionsOffset; | 419 const int offset = StandardFrameConstants::kExpressionsOffset; |
435 return fp() + offset - n * kPointerSize; | 420 return fp() + offset - n * kPointerSize; |
436 } | 421 } |
437 | 422 |
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
492 return IsConstructFrame(fp); | 477 return IsConstructFrame(fp); |
493 } | 478 } |
494 | 479 |
495 | 480 |
496 Code* JavaScriptFrame::unchecked_code() const { | 481 Code* JavaScriptFrame::unchecked_code() const { |
497 JSFunction* function = JSFunction::cast(this->function()); | 482 JSFunction* function = JSFunction::cast(this->function()); |
498 return function->unchecked_code(); | 483 return function->unchecked_code(); |
499 } | 484 } |
500 | 485 |
501 | 486 |
| 487 int JavaScriptFrame::GetProvidedParametersCount() const { |
| 488 return ComputeParametersCount(); |
| 489 } |
| 490 |
| 491 |
| 492 Address JavaScriptFrame::GetCallerStackPointer() const { |
| 493 int arguments; |
| 494 if (Heap::gc_state() != Heap::NOT_IN_GC || |
| 495 SafeStackFrameIterator::is_active()) { |
| 496 // If the we are currently iterating the safe stack the |
| 497 // arguments for frames are traversed as if they were |
| 498 // expression stack elements of the calling frame. The reason for |
| 499 // this rather strange decision is that we cannot access the |
| 500 // function during mark-compact GCs when objects may have been marked. |
| 501 // In fact accessing heap objects (like function->shared() below) |
| 502 // at all during GC is problematic. |
| 503 arguments = 0; |
| 504 } else { |
| 505 // Compute the number of arguments by getting the number of formal |
| 506 // parameters of the function. We must remember to take the |
| 507 // receiver into account (+1). |
| 508 JSFunction* function = JSFunction::cast(this->function()); |
| 509 arguments = function->shared()->formal_parameter_count() + 1; |
| 510 } |
| 511 const int offset = StandardFrameConstants::kCallerSPOffset; |
| 512 return fp() + offset + (arguments * kPointerSize); |
| 513 } |
| 514 |
| 515 |
| 516 Address ArgumentsAdaptorFrame::GetCallerStackPointer() const { |
| 517 const int arguments = Smi::cast(GetExpression(0))->value(); |
| 518 const int offset = StandardFrameConstants::kCallerSPOffset; |
| 519 return fp() + offset + (arguments + 1) * kPointerSize; |
| 520 } |
| 521 |
| 522 |
| 523 Address InternalFrame::GetCallerStackPointer() const { |
| 524 // Internal frames have no arguments. The stack pointer of the |
| 525 // caller is at a fixed offset from the frame pointer. |
| 526 return fp() + StandardFrameConstants::kCallerSPOffset; |
| 527 } |
| 528 |
| 529 |
502 Code* ArgumentsAdaptorFrame::unchecked_code() const { | 530 Code* ArgumentsAdaptorFrame::unchecked_code() const { |
503 return Builtins::builtin(Builtins::ArgumentsAdaptorTrampoline); | 531 return Builtins::builtin(Builtins::ArgumentsAdaptorTrampoline); |
504 } | 532 } |
505 | 533 |
506 | 534 |
507 Code* InternalFrame::unchecked_code() const { | 535 Code* InternalFrame::unchecked_code() const { |
508 const int offset = InternalFrameConstants::kCodeOffset; | 536 const int offset = InternalFrameConstants::kCodeOffset; |
509 Object* code = Memory::Object_at(fp() + offset); | 537 Object* code = Memory::Object_at(fp() + offset); |
510 ASSERT(code != NULL); | 538 ASSERT(code != NULL); |
511 return reinterpret_cast<Code*>(code); | 539 return reinterpret_cast<Code*>(code); |
(...skipping 175 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
687 | 715 |
688 accumulator->Add("}\n\n"); | 716 accumulator->Add("}\n\n"); |
689 } | 717 } |
690 | 718 |
691 | 719 |
692 void EntryFrame::Iterate(ObjectVisitor* v) const { | 720 void EntryFrame::Iterate(ObjectVisitor* v) const { |
693 StackHandlerIterator it(this, top_handler()); | 721 StackHandlerIterator it(this, top_handler()); |
694 ASSERT(!it.done()); | 722 ASSERT(!it.done()); |
695 StackHandler* handler = it.handler(); | 723 StackHandler* handler = it.handler(); |
696 ASSERT(handler->is_entry()); | 724 ASSERT(handler->is_entry()); |
697 handler->Iterate(v); | 725 handler->Iterate(v, code()); |
698 // Make sure that there's the entry frame does not contain more than | |
699 // one stack handler. | |
700 #ifdef DEBUG | 726 #ifdef DEBUG |
| 727 // Make sure that the entry frame does not contain more than one |
| 728 // stack handler. |
701 it.Advance(); | 729 it.Advance(); |
702 ASSERT(it.done()); | 730 ASSERT(it.done()); |
703 #endif | 731 #endif |
| 732 IteratePc(v, pc_address(), code()); |
704 } | 733 } |
705 | 734 |
706 | 735 |
707 void StandardFrame::IterateExpressions(ObjectVisitor* v) const { | 736 void StandardFrame::IterateExpressions(ObjectVisitor* v) const { |
708 const int offset = StandardFrameConstants::kContextOffset; | 737 const int offset = StandardFrameConstants::kContextOffset; |
709 Object** base = &Memory::Object_at(sp()); | 738 Object** base = &Memory::Object_at(sp()); |
710 Object** limit = &Memory::Object_at(fp() + offset) + 1; | 739 Object** limit = &Memory::Object_at(fp() + offset) + 1; |
711 for (StackHandlerIterator it(this, top_handler()); !it.done(); it.Advance()) { | 740 for (StackHandlerIterator it(this, top_handler()); !it.done(); it.Advance()) { |
712 StackHandler* handler = it.handler(); | 741 StackHandler* handler = it.handler(); |
713 // Traverse pointers down to - but not including - the next | 742 // Traverse pointers down to - but not including - the next |
714 // handler in the handler chain. Update the base to skip the | 743 // handler in the handler chain. Update the base to skip the |
715 // handler and allow the handler to traverse its own pointers. | 744 // handler and allow the handler to traverse its own pointers. |
716 const Address address = handler->address(); | 745 const Address address = handler->address(); |
717 v->VisitPointers(base, reinterpret_cast<Object**>(address)); | 746 v->VisitPointers(base, reinterpret_cast<Object**>(address)); |
718 base = reinterpret_cast<Object**>(address + StackHandlerConstants::kSize); | 747 base = reinterpret_cast<Object**>(address + StackHandlerConstants::kSize); |
719 // Traverse the pointers in the handler itself. | 748 // Traverse the pointers in the handler itself. |
720 handler->Iterate(v); | 749 handler->Iterate(v, code()); |
721 } | 750 } |
722 v->VisitPointers(base, limit); | 751 v->VisitPointers(base, limit); |
723 } | 752 } |
724 | 753 |
725 | 754 |
726 void JavaScriptFrame::Iterate(ObjectVisitor* v) const { | 755 void JavaScriptFrame::Iterate(ObjectVisitor* v) const { |
727 IterateExpressions(v); | 756 IterateExpressions(v); |
| 757 IteratePc(v, pc_address(), code()); |
728 | 758 |
729 // Traverse callee-saved registers, receiver, and parameters. | 759 // Traverse callee-saved registers, receiver, and parameters. |
730 const int kBaseOffset = JavaScriptFrameConstants::kSavedRegistersOffset; | 760 const int kBaseOffset = JavaScriptFrameConstants::kSavedRegistersOffset; |
731 const int kLimitOffset = JavaScriptFrameConstants::kReceiverOffset; | 761 const int kLimitOffset = JavaScriptFrameConstants::kReceiverOffset; |
732 Object** base = &Memory::Object_at(fp() + kBaseOffset); | 762 Object** base = &Memory::Object_at(fp() + kBaseOffset); |
733 Object** limit = &Memory::Object_at(caller_sp() + kLimitOffset) + 1; | 763 Object** limit = &Memory::Object_at(caller_sp() + kLimitOffset) + 1; |
734 v->VisitPointers(base, limit); | 764 v->VisitPointers(base, limit); |
735 } | 765 } |
736 | 766 |
737 | 767 |
738 void InternalFrame::Iterate(ObjectVisitor* v) const { | 768 void InternalFrame::Iterate(ObjectVisitor* v) const { |
739 // Internal frames only have object pointers on the expression stack | 769 // Internal frames only have object pointers on the expression stack |
740 // as they never have any arguments. | 770 // as they never have any arguments. |
741 IterateExpressions(v); | 771 IterateExpressions(v); |
| 772 IteratePc(v, pc_address(), code()); |
742 } | 773 } |
743 | 774 |
744 | 775 |
745 // ------------------------------------------------------------------------- | 776 // ------------------------------------------------------------------------- |
746 | 777 |
747 | 778 |
748 JavaScriptFrame* StackFrameLocator::FindJavaScriptFrame(int n) { | 779 JavaScriptFrame* StackFrameLocator::FindJavaScriptFrame(int n) { |
749 ASSERT(n >= 0); | 780 ASSERT(n >= 0); |
750 for (int i = 0; i <= n; i++) { | 781 for (int i = 0; i <= n; i++) { |
751 while (!iterator_.frame()->is_java_script()) iterator_.Advance(); | 782 while (!iterator_.frame()->is_java_script()) iterator_.Advance(); |
752 if (i == n) return JavaScriptFrame::cast(iterator_.frame()); | 783 if (i == n) return JavaScriptFrame::cast(iterator_.frame()); |
753 iterator_.Advance(); | 784 iterator_.Advance(); |
754 } | 785 } |
755 UNREACHABLE(); | 786 UNREACHABLE(); |
756 return NULL; | 787 return NULL; |
757 } | 788 } |
758 | 789 |
759 | 790 |
760 // ------------------------------------------------------------------------- | 791 // ------------------------------------------------------------------------- |
761 | 792 |
762 | 793 |
| 794 Code* PcToCodeCache::GcSafeCastToCode(HeapObject* object, Address pc) { |
| 795 Code* code = reinterpret_cast<Code*>(object); |
| 796 ASSERT(code != NULL && code->contains(pc)); |
| 797 return code; |
| 798 } |
| 799 |
| 800 |
| 801 Code* PcToCodeCache::GcSafeFindCodeForPc(Address pc) { |
| 802 // Check if the pc points into a large object chunk. |
| 803 LargeObjectChunk* chunk = Heap::lo_space()->FindChunkContainingPc(pc); |
| 804 if (chunk != NULL) return GcSafeCastToCode(chunk->GetObject(), pc); |
| 805 |
| 806 // Iterate through the 8K page until we reach the end or find an |
| 807 // object starting after the pc. |
| 808 Page* page = Page::FromAddress(pc); |
| 809 HeapObjectIterator iterator(page, Heap::GcSafeSizeOfOldObjectFunction()); |
| 810 HeapObject* previous = NULL; |
| 811 while (true) { |
| 812 HeapObject* next = iterator.next(); |
| 813 if (next == NULL || next->address() >= pc) { |
| 814 return GcSafeCastToCode(previous, pc); |
| 815 } |
| 816 previous = next; |
| 817 } |
| 818 } |
| 819 |
| 820 PcToCodeCache::PcToCodeCacheEntry* PcToCodeCache::GetCacheEntry(Address pc) { |
| 821 Counters::pc_to_code.Increment(); |
| 822 ASSERT(IsPowerOf2(kPcToCodeCacheSize)); |
| 823 uint32_t hash = ComputeIntegerHash( |
| 824 static_cast<uint32_t>(reinterpret_cast<uintptr_t>(pc))); |
| 825 uint32_t index = hash & (kPcToCodeCacheSize - 1); |
| 826 PcToCodeCacheEntry* entry = cache(index); |
| 827 if (entry->pc == pc) { |
| 828 Counters::pc_to_code_cached.Increment(); |
| 829 ASSERT(entry->code == GcSafeFindCodeForPc(pc)); |
| 830 } else { |
| 831 // Because this code may be interrupted by a profiling signal that |
| 832 // also queries the cache, we cannot update pc before the code has |
| 833 // been set. Otherwise, we risk trying to use a cache entry before |
| 834 // the code has been computed. |
| 835 entry->code = GcSafeFindCodeForPc(pc); |
| 836 entry->pc = pc; |
| 837 } |
| 838 return entry; |
| 839 } |
| 840 |
| 841 |
| 842 // ------------------------------------------------------------------------- |
| 843 |
763 int NumRegs(RegList reglist) { | 844 int NumRegs(RegList reglist) { |
764 int n = 0; | 845 int n = 0; |
765 while (reglist != 0) { | 846 while (reglist != 0) { |
766 n++; | 847 n++; |
767 reglist &= reglist - 1; // clear one bit | 848 reglist &= reglist - 1; // clear one bit |
768 } | 849 } |
769 return n; | 850 return n; |
770 } | 851 } |
771 | 852 |
772 | 853 |
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
817 ZoneList<StackFrame*> list(10); | 898 ZoneList<StackFrame*> list(10); |
818 for (StackFrameIterator it; !it.done(); it.Advance()) { | 899 for (StackFrameIterator it; !it.done(); it.Advance()) { |
819 StackFrame* frame = AllocateFrameCopy(it.frame()); | 900 StackFrame* frame = AllocateFrameCopy(it.frame()); |
820 list.Add(frame); | 901 list.Add(frame); |
821 } | 902 } |
822 return list.ToVector(); | 903 return list.ToVector(); |
823 } | 904 } |
824 | 905 |
825 | 906 |
826 } } // namespace v8::internal | 907 } } // namespace v8::internal |
OLD | NEW |